Why does Box need 16 bytes in memory, but a referenced slice needs only 8? (on x64 machine) Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30 pm US/Eastern) Data science time! April 2019 and salary with experience The Ask Question Wizard is Live!Why does Rust borrow checker reject this code?How do I implement a struct that takes a generic vector with lifetime annotations?Clone not invoked for Moved value?Which library to use for Weak referencesClosing stdout or stdinWhat is the use of into_boxed_slice() methods?Reverse order of a reference to immutable array sliceHow to prepend a slice to a VecWhy does storing to and loading from an AVX2 256bit vector have different results in debug and release mode?Why does a function taking a reference to a generic care that the generic is Sized?

Co-worker works way more than he should

Is there an efficient way for synchronising audio events real-time with LEDs using an MCU?

What is /etc/mtab in Linux?

Processing ADC conversion result: DMA vs Processor Registers

Is there a verb for listening stealthily?

Why isn't everyone flabbergasted about Bran's "gift"?

Simulate round-robin tournament draw

What to do with someone that cheated their way though university and a PhD program?

What is a 'Key' in computer science?

/bin/ls sorts differently than just ls

Is it OK if I do not take the receipt in Germany?

Why did Israel vote against lifting the American embargo on Cuba?

All ASCII characters with a given bit count

How would you suggest I follow up with coworkers about our deadline that's today?

Variable does not exist: sObjectType (Task.sObjectType)

What is the numbering system used for the DSN dishes?

Is it accepted to use working hours to read general interest books?

Writing a T-SQL stored procedure to receive 4 numbers and insert them into a table

When does Bran Stark remember Jamie pushing him?

Coin Game with infinite paradox

Is Bran literally the world's memory?

Protagonist's race is hidden - should I reveal it?

Determinant of a matrix with 2 equal rows

How to keep bees out of canned beverages?



Why does Box need 16 bytes in memory, but a referenced slice needs only 8? (on x64 machine)



Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30 pm US/Eastern)
Data science time! April 2019 and salary with experience
The Ask Question Wizard is Live!Why does Rust borrow checker reject this code?How do I implement a struct that takes a generic vector with lifetime annotations?Clone not invoked for Moved value?Which library to use for Weak referencesClosing stdout or stdinWhat is the use of into_boxed_slice() methods?Reverse order of a reference to immutable array sliceHow to prepend a slice to a VecWhy does storing to and loading from an AVX2 256bit vector have different results in debug and release mode?Why does a function taking a reference to a generic care that the generic is Sized?



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








11















Consider:



fn main() 
// Prints 8, 8, 16
println!(
", , ",
std::mem::size_of::<Box<i8>>(),
std::mem::size_of::<Box<&[i8]>>(),
std::mem::size_of::<Box<[i8]>>(),
);



Why do owned slices take 16 bytes, but referenced slices take only 8?









share
























  • Playground: play.rust-lang.org/…

    – French Boiethios
    9 hours ago






  • 2





    Previous discussion: i.stack.imgur.com/Xt6L3.png

    – hellow
    8 hours ago

















11















Consider:



fn main() 
// Prints 8, 8, 16
println!(
", , ",
std::mem::size_of::<Box<i8>>(),
std::mem::size_of::<Box<&[i8]>>(),
std::mem::size_of::<Box<[i8]>>(),
);



Why do owned slices take 16 bytes, but referenced slices take only 8?









share
























  • Playground: play.rust-lang.org/…

    – French Boiethios
    9 hours ago






  • 2





    Previous discussion: i.stack.imgur.com/Xt6L3.png

    – hellow
    8 hours ago













11












11








11








Consider:



fn main() 
// Prints 8, 8, 16
println!(
", , ",
std::mem::size_of::<Box<i8>>(),
std::mem::size_of::<Box<&[i8]>>(),
std::mem::size_of::<Box<[i8]>>(),
);



Why do owned slices take 16 bytes, but referenced slices take only 8?









share
















Consider:



fn main() 
// Prints 8, 8, 16
println!(
", , ",
std::mem::size_of::<Box<i8>>(),
std::mem::size_of::<Box<&[i8]>>(),
std::mem::size_of::<Box<[i8]>>(),
);



Why do owned slices take 16 bytes, but referenced slices take only 8?







rust





share














share












share



share








edited 2 hours ago









Tim Diekmann

3,58291940




3,58291940










asked 9 hours ago









aminamin

1,29312042




1,29312042












  • Playground: play.rust-lang.org/…

    – French Boiethios
    9 hours ago






  • 2





    Previous discussion: i.stack.imgur.com/Xt6L3.png

    – hellow
    8 hours ago

















  • Playground: play.rust-lang.org/…

    – French Boiethios
    9 hours ago






  • 2





    Previous discussion: i.stack.imgur.com/Xt6L3.png

    – hellow
    8 hours ago
















Playground: play.rust-lang.org/…

– French Boiethios
9 hours ago





Playground: play.rust-lang.org/…

– French Boiethios
9 hours ago




2




2





Previous discussion: i.stack.imgur.com/Xt6L3.png

– hellow
8 hours ago





Previous discussion: i.stack.imgur.com/Xt6L3.png

– hellow
8 hours ago












2 Answers
2






active

oldest

votes


















14














Box<T> is basically *const T (Actually it's a newtype around Unique<T>, which itself is a NonNull<T> with PhantomData<T> (for dropck), but let's stick to *const T for simplicity).



A pointer in Rust normally has the same size as size_of::<usize>() except when T is a dynamically sized type (DST). Currently, a Box<DST> is 2 * size_of::<usize>() in size (the exact representation is not stable at the time of writing). A pointer to a DST is called FatPtr.



Currently, there are two kinds of DSTs: Slices and traits. A FatPtr to a slice is defined like this:



#[repr(C)]
struct FatPtr<T>
data: *const T,
len: usize,



Note: For a trait pointer, len is replaced by a pointer to the vtable.



With those information, your question can be answered:




  • Box<i8>: i8 is a sized type => basically the same as *const i8 => 8 bytes in size (with 64 bit pointer width)


  • Box<[i8]>: [i8] is a DST => basically the same as FatPtr<i8> => 16 bytes in size (with 64 bit pointer width)


  • Box<&[i8]>: &[i8] is not a DST. It's basically the same as *const FatPtr<i8> => 8 bytes in size (with 64 bit pointer width)




share
































    2














    The size of a reference depends on the "sizeness" of the referenced type:



    • A reference to a sized type is a single pointer to the memory address.


    • A reference to an unsized type is a pointer to the memory and the size of the pointed datum. That's what is called a fat pointer:



      #[repr(C)]
      struct FatPtr<T>
      data: *const T,
      len: usize,



    A Box is a special kind of pointer that points to the heap, but it is a pointer anyway.



    Knowing that, you understand that:




    • Box<i8> is 8 bytes because i8 is sized,


    • Box<&[i8]> is 8 bytes because a reference is sized,


    • Box<[i8]> is 8 bytes because a slice is unsized




    share























    • Box<[i8]> is 16 in your own playground link

      – Stargateur
      2 hours ago











    • @Stargateur I guess this was a typo :)

      – Tim Diekmann
      2 hours ago


















    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    14














    Box<T> is basically *const T (Actually it's a newtype around Unique<T>, which itself is a NonNull<T> with PhantomData<T> (for dropck), but let's stick to *const T for simplicity).



    A pointer in Rust normally has the same size as size_of::<usize>() except when T is a dynamically sized type (DST). Currently, a Box<DST> is 2 * size_of::<usize>() in size (the exact representation is not stable at the time of writing). A pointer to a DST is called FatPtr.



    Currently, there are two kinds of DSTs: Slices and traits. A FatPtr to a slice is defined like this:



    #[repr(C)]
    struct FatPtr<T>
    data: *const T,
    len: usize,



    Note: For a trait pointer, len is replaced by a pointer to the vtable.



    With those information, your question can be answered:




    • Box<i8>: i8 is a sized type => basically the same as *const i8 => 8 bytes in size (with 64 bit pointer width)


    • Box<[i8]>: [i8] is a DST => basically the same as FatPtr<i8> => 16 bytes in size (with 64 bit pointer width)


    • Box<&[i8]>: &[i8] is not a DST. It's basically the same as *const FatPtr<i8> => 8 bytes in size (with 64 bit pointer width)




    share





























      14














      Box<T> is basically *const T (Actually it's a newtype around Unique<T>, which itself is a NonNull<T> with PhantomData<T> (for dropck), but let's stick to *const T for simplicity).



      A pointer in Rust normally has the same size as size_of::<usize>() except when T is a dynamically sized type (DST). Currently, a Box<DST> is 2 * size_of::<usize>() in size (the exact representation is not stable at the time of writing). A pointer to a DST is called FatPtr.



      Currently, there are two kinds of DSTs: Slices and traits. A FatPtr to a slice is defined like this:



      #[repr(C)]
      struct FatPtr<T>
      data: *const T,
      len: usize,



      Note: For a trait pointer, len is replaced by a pointer to the vtable.



      With those information, your question can be answered:




      • Box<i8>: i8 is a sized type => basically the same as *const i8 => 8 bytes in size (with 64 bit pointer width)


      • Box<[i8]>: [i8] is a DST => basically the same as FatPtr<i8> => 16 bytes in size (with 64 bit pointer width)


      • Box<&[i8]>: &[i8] is not a DST. It's basically the same as *const FatPtr<i8> => 8 bytes in size (with 64 bit pointer width)




      share



























        14












        14








        14







        Box<T> is basically *const T (Actually it's a newtype around Unique<T>, which itself is a NonNull<T> with PhantomData<T> (for dropck), but let's stick to *const T for simplicity).



        A pointer in Rust normally has the same size as size_of::<usize>() except when T is a dynamically sized type (DST). Currently, a Box<DST> is 2 * size_of::<usize>() in size (the exact representation is not stable at the time of writing). A pointer to a DST is called FatPtr.



        Currently, there are two kinds of DSTs: Slices and traits. A FatPtr to a slice is defined like this:



        #[repr(C)]
        struct FatPtr<T>
        data: *const T,
        len: usize,



        Note: For a trait pointer, len is replaced by a pointer to the vtable.



        With those information, your question can be answered:




        • Box<i8>: i8 is a sized type => basically the same as *const i8 => 8 bytes in size (with 64 bit pointer width)


        • Box<[i8]>: [i8] is a DST => basically the same as FatPtr<i8> => 16 bytes in size (with 64 bit pointer width)


        • Box<&[i8]>: &[i8] is not a DST. It's basically the same as *const FatPtr<i8> => 8 bytes in size (with 64 bit pointer width)




        share















        Box<T> is basically *const T (Actually it's a newtype around Unique<T>, which itself is a NonNull<T> with PhantomData<T> (for dropck), but let's stick to *const T for simplicity).



        A pointer in Rust normally has the same size as size_of::<usize>() except when T is a dynamically sized type (DST). Currently, a Box<DST> is 2 * size_of::<usize>() in size (the exact representation is not stable at the time of writing). A pointer to a DST is called FatPtr.



        Currently, there are two kinds of DSTs: Slices and traits. A FatPtr to a slice is defined like this:



        #[repr(C)]
        struct FatPtr<T>
        data: *const T,
        len: usize,



        Note: For a trait pointer, len is replaced by a pointer to the vtable.



        With those information, your question can be answered:




        • Box<i8>: i8 is a sized type => basically the same as *const i8 => 8 bytes in size (with 64 bit pointer width)


        • Box<[i8]>: [i8] is a DST => basically the same as FatPtr<i8> => 16 bytes in size (with 64 bit pointer width)


        • Box<&[i8]>: &[i8] is not a DST. It's basically the same as *const FatPtr<i8> => 8 bytes in size (with 64 bit pointer width)





        share













        share


        share








        edited 27 mins ago

























        answered 8 hours ago









        Tim DiekmannTim Diekmann

        3,58291940




        3,58291940























            2














            The size of a reference depends on the "sizeness" of the referenced type:



            • A reference to a sized type is a single pointer to the memory address.


            • A reference to an unsized type is a pointer to the memory and the size of the pointed datum. That's what is called a fat pointer:



              #[repr(C)]
              struct FatPtr<T>
              data: *const T,
              len: usize,



            A Box is a special kind of pointer that points to the heap, but it is a pointer anyway.



            Knowing that, you understand that:




            • Box<i8> is 8 bytes because i8 is sized,


            • Box<&[i8]> is 8 bytes because a reference is sized,


            • Box<[i8]> is 8 bytes because a slice is unsized




            share























            • Box<[i8]> is 16 in your own playground link

              – Stargateur
              2 hours ago











            • @Stargateur I guess this was a typo :)

              – Tim Diekmann
              2 hours ago















            2














            The size of a reference depends on the "sizeness" of the referenced type:



            • A reference to a sized type is a single pointer to the memory address.


            • A reference to an unsized type is a pointer to the memory and the size of the pointed datum. That's what is called a fat pointer:



              #[repr(C)]
              struct FatPtr<T>
              data: *const T,
              len: usize,



            A Box is a special kind of pointer that points to the heap, but it is a pointer anyway.



            Knowing that, you understand that:




            • Box<i8> is 8 bytes because i8 is sized,


            • Box<&[i8]> is 8 bytes because a reference is sized,


            • Box<[i8]> is 8 bytes because a slice is unsized




            share























            • Box<[i8]> is 16 in your own playground link

              – Stargateur
              2 hours ago











            • @Stargateur I guess this was a typo :)

              – Tim Diekmann
              2 hours ago













            2












            2








            2







            The size of a reference depends on the "sizeness" of the referenced type:



            • A reference to a sized type is a single pointer to the memory address.


            • A reference to an unsized type is a pointer to the memory and the size of the pointed datum. That's what is called a fat pointer:



              #[repr(C)]
              struct FatPtr<T>
              data: *const T,
              len: usize,



            A Box is a special kind of pointer that points to the heap, but it is a pointer anyway.



            Knowing that, you understand that:




            • Box<i8> is 8 bytes because i8 is sized,


            • Box<&[i8]> is 8 bytes because a reference is sized,


            • Box<[i8]> is 8 bytes because a slice is unsized




            share













            The size of a reference depends on the "sizeness" of the referenced type:



            • A reference to a sized type is a single pointer to the memory address.


            • A reference to an unsized type is a pointer to the memory and the size of the pointed datum. That's what is called a fat pointer:



              #[repr(C)]
              struct FatPtr<T>
              data: *const T,
              len: usize,



            A Box is a special kind of pointer that points to the heap, but it is a pointer anyway.



            Knowing that, you understand that:




            • Box<i8> is 8 bytes because i8 is sized,


            • Box<&[i8]> is 8 bytes because a reference is sized,


            • Box<[i8]> is 8 bytes because a slice is unsized





            share











            share


            share










            answered 8 hours ago









            French BoiethiosFrench Boiethios

            11.4k44081




            11.4k44081












            • Box<[i8]> is 16 in your own playground link

              – Stargateur
              2 hours ago











            • @Stargateur I guess this was a typo :)

              – Tim Diekmann
              2 hours ago

















            • Box<[i8]> is 16 in your own playground link

              – Stargateur
              2 hours ago











            • @Stargateur I guess this was a typo :)

              – Tim Diekmann
              2 hours ago
















            Box<[i8]> is 16 in your own playground link

            – Stargateur
            2 hours ago





            Box<[i8]> is 16 in your own playground link

            – Stargateur
            2 hours ago













            @Stargateur I guess this was a typo :)

            – Tim Diekmann
            2 hours ago





            @Stargateur I guess this was a typo :)

            – Tim Diekmann
            2 hours ago



            Popular posts from this blog

            The Calvary Singular or Plural The 2019 Stack Overflow Developer Survey Results Are InAre collective nouns always plural, or are certain ones singular?Is “audience” singular or plural?“Wasn't” vs. “weren't” in a vernacular sentence“My last couple of years” — singular or plural?Is 'rest' singular or plural?Is “all but one” singular or plural?Whether to use the singular or plural form of basis?Singular and Plural for numbersIs there a plural form of teeth?performance: plural vs singular?singular or plural nouns?Singular and Plural

            Is it possible to static_assert that a lambda is not generic?Can we get the type of a lambda argument?Is it possible to write a template to check for a function's existence?What is a lambda expression in C++11?Compiling with gcc fails if using lambda function for QObject::connect()c++11 - getting result_of, decltype, std::function and variadic templates working togetherTemplate Type Deduction with LambdasVariadic template method and std::function - compilation errorRecursively visiting an `std::variant` using lambdas and fixed-point combinatorsClang can't find template binary operator in fold expressionGenerating lambda from class templateGetting active value in std::visit without knowing which value is active

            What is the correct present continuous form of “thunder” and “lightning”? Unicorn Meta Zoo #1: Why another podcast? Announcing the arrival of Valued Associate #679: Cesar ManaraWhat is the past tense of “lightning”?What part of speech is the “be + verb” here? What tense are these sentences in?Present perfect and present perfect continuous for actions in progressIs it correct to mix past, present and future tense in a sentence?Correct verb form in two sentencesSimple vs Continuous in the Past Tense and in the Future TenseUsing present continuous passive (is being) for describing repeating (undesirable) actionssituations in which simple present and present continuous are interchangeable?Present Perfect Simple vs Present Perfect ContinuousWhat is the proper way to express a future action that depends on a past event?Progressive Form of Be and Lately in Present Continuous