sizeof observation

Discussion in 'C++' started by nzanella@cs.mun.ca, Aug 2, 2005.

  1. Guest

    Hello,

    I just thought I would share the following observation with the rest
    of the group. The sizeof operator seems to act differently according
    to whether the number of elements in the array is known. Hence when
    passing arrays to functions the number of elements in the array must
    always be passed as an argument. If STL is available then people can
    just use vectors of course. Anyways, I guess this stuff is pretty
    standard. Well, have a nice day,

    Neil

    #include <cstdio>

    void hello(const char *foo[]) {
    printf("%u\n", sizeof(foo)/sizeof(char));
    }

    int main() {
    const char *foo[8];
    const char *bar[] = { "aa", "bb" };
    printf("%u\n", sizeof(foo)/sizeof(char));
    //BTW sizeof(char) is always going to be one
    printf("%u\n", sizeof(bar)/sizeof(char));
    //BTW sizeof(char) is always going to be one
    hello(foo);
    }

    Output:

    $ ./a.out
    32
    8
    4
     
    , Aug 2, 2005
    #1
    1. Advertising

  2. wrote:
    > I just thought I would share the following observation with the rest
    > of the group. The sizeof operator seems to act differently according
    > to whether the number of elements in the array is known.


    No, it "acts" differently when you supply different types to it.

    > Hence when
    > passing arrays to functions the number of elements in the array must
    > always be passed as an argument. If STL is available then people can
    > just use vectors of course. Anyways, I guess this stuff is pretty
    > standard.


    Yes. And pretty basic too.

    > Well, have a nice day,


    Thanks. Same to you.

    >
    > Neil
    >
    > #include <cstdio>
    >
    > void hello(const char *foo[]) {


    In this function 'foo' is not an array. It's a pointer. The [] notation
    is a left-over from C days (like the "native" arrays, of course), and it
    simply declares the argument as a pointer. If you want to pass an array,
    you can, by reference. You should do

    void hello(const char *(&foo)[8])

    In that case, 'foo' is a reference to an array of eight pointers to const
    char. And, just like with any other reference, if you use the 'sizeof'
    operator on it, you will get the size of the object it refers to.

    > printf("%u\n", sizeof(foo)/sizeof(char));


    BTW, 'sizeof(char)' is _always_ 1. Dividing by it makes no sense. You
    probably wanted to divide by 'sizeof(const char*)' which would give you
    the _number_ of elements in the array.

    > }
    >
    > int main() {
    > const char *foo[8];
    > const char *bar[] = { "aa", "bb" };
    > printf("%u\n", sizeof(foo)/sizeof(char));
    > //BTW sizeof(char) is always going to be one


    Yes, by definition of 'sizeof'. There is no sense in dividing by 1, is
    there?

    > printf("%u\n", sizeof(bar)/sizeof(char));
    > //BTW sizeof(char) is always going to be one
    > hello(foo);
    > }
    >
    > Output:
    >
    > $ ./a.out
    > 32
    > 8
    > 4



    V
     
    Victor Bazarov, Aug 2, 2005
    #2
    1. Advertising

  3. Alipha Guest

    wrote:
    > Hello,
    >
    > I just thought I would share the following observation with the rest
    > of the group. The sizeof operator seems to act differently according
    > to whether the number of elements in the array is known. Hence when
    > passing arrays to functions the number of elements in the array must
    > always be passed as an argument. If STL is available then people can
    > just use vectors of course. Anyways, I guess this stuff is pretty
    > standard. Well, have a nice day,
    >
    > Neil
    >
    > #include <cstdio>
    >
    > void hello(const char *foo[]) {
    > printf("%u\n", sizeof(foo)/sizeof(char));
    > }
    >
    > int main() {
    > const char *foo[8];
    > const char *bar[] = { "aa", "bb" };
    > printf("%u\n", sizeof(foo)/sizeof(char));
    > //BTW sizeof(char) is always going to be one
    > printf("%u\n", sizeof(bar)/sizeof(char));
    > //BTW sizeof(char) is always going to be one
    > hello(foo);
    > }
    >
    > Output:
    >
    > $ ./a.out
    > 32
    > 8
    > 4


    Instead of the sizeof idiom for determining the number of elements in
    an array, you might want to consider using this function instead:

    template<typename T, std::size_t N>
    inline std::size_t countof( T (&)[N] ) { return N; }

    this function won't compile if you pass a pointer to it (calling
    countof(foo) inside hello will error) and you can't make mistakes such
    as dividing by sizeof(char) instead of by sizeof(const char*) like you
    should be doing.

    btw, if you're including <cstdio> (why not <iostream>?) it is
    std::printf, etc. all standard identifiers are in the std namespace.
     
    Alipha, Aug 2, 2005
    #3
  4. Guest

    Victor Bazarov wrote:
    ....
    >
    > > printf("%u\n", sizeof(foo)/sizeof(char));

    >
    > BTW, 'sizeof(char)' is _always_ 1. Dividing by it makes no sense. You
    > probably wanted to divide by 'sizeof(const char*)' which would give you
    > the _number_ of elements in the array.

    ....

    This may not be true if you're trying to write code that is valid as
    either C or C++ code. C originally defined sizeof to return the
    number of bytes of storage needed, and a byte and a char were not
    necessarily the same thing. Architectures with instructions that
    operated on units of memory whose size wasn't a power of two
    disappeared from widespread use around 1980, and C++ assumed the dead
    would not rise again.
     
    , Aug 2, 2005
    #4
  5. wrote:
    > Victor Bazarov wrote:
    > ...
    >
    >>> printf("%u\n", sizeof(foo)/sizeof(char));

    >>
    >>BTW, 'sizeof(char)' is _always_ 1. Dividing by it makes no sense. You
    >>probably wanted to divide by 'sizeof(const char*)' which would give you
    >>the _number_ of elements in the array.

    >
    > ...
    >
    > This may not be true if you're trying to write code that is valid as
    > either C or C++ code.


    That's nonsense. It's true for both C and C++.

    > C originally defined sizeof to return the
    > number of bytes of storage needed, and a byte and a char were not
    > necessarily the same thing.


    Care to give a quote from some document which would define that?

    > Architectures with instructions that
    > operated on units of memory whose size wasn't a power of two
    > disappeared from widespread use around 1980, and C++ assumed the dead
    > would not rise again.
    >


    C defines 'byte' to be "addressable unit of data storage large enough to
    hold any member of the basic character set of the execution environment".
    And also in 6.5.3.4, it says "When applied to an operand that has type
    char, unsigned char, or signed char, (or a qualified version thereof) the
    result is 1." Where you see a conflict with some [unusual or now dead]
    architectures, I am not sure.

    V
     
    Victor Bazarov, Aug 2, 2005
    #5
  6. Guest

    Victor Bazarov wrote:
    > wrote:
    > > Victor Bazarov wrote:
    > > ...
    > >
    > >>> printf("%u\n", sizeof(foo)/sizeof(char));
    > >>
    > >>BTW, 'sizeof(char)' is _always_ 1. Dividing by it makes no sense. You
    > >>probably wanted to divide by 'sizeof(const char*)' which would give you
    > >>the _number_ of elements in the array.

    > >
    > > ...
    > >
    > > This may not be true if you're trying to write code that is valid as
    > > either C or C++ code.

    >
    > That's nonsense. It's true for both C and C++.


    I'll take your word for it that sizeof(char) == 1 has made it
    into the C Standard now as well. But I still see alot of
    "#ifdef ANSI_C" as I'm browsing through C code. C is all
    about anachronism these days, which could make for a big lag
    between compiler versions in wide usage and the current
    C Standard.

    > > C originally defined sizeof to return the
    > > number of bytes of storage needed, and a byte and a char were not
    > > necessarily the same thing.

    >
    > Care to give a quote from some document which would define that?


    Nah, too lazy to try.

    > > Architectures with instructions that
    > > operated on units of memory whose size wasn't a power of two
    > > disappeared from widespread use around 1980, and C++ assumed the dead
    > > would not rise again.
    > >

    >
    > C defines 'byte' to be "addressable unit of data storage large enough to
    > hold any member of the basic character set of the execution environment".
    > And also in 6.5.3.4, it says "When applied to an operand that has type
    > char, unsigned char, or signed char, (or a qualified version thereof) the
    > result is 1." Where you see a conflict with some [unusual or now dead]
    > architectures, I am not sure.


    The DEC/PDP 10 had word size of 36 bits. The size of a character could
    be set (by loading a special register) to 6, 7, 8 or 9 bits. I never
    saw a C implementation for the DEC 10. If char was defined to be
    8 bits, then it would probably make sense to define a byte to be 4 bits
    rather than 8 (unless sizeof was redefined to return a float).
     
    , Aug 3, 2005
    #6
  7. Default User Guest

    wrote:

    > Victor Bazarov wrote:


    > > That's nonsense. It's true for both C and C++.

    >
    > I'll take your word for it that sizeof(char) == 1 has made it
    > into the C Standard now as well.


    If made it into there years before C++ even had a standard.

    > But I still see alot of
    > "#ifdef ANSI_C" as I'm browsing through C code. C is all
    > about anachronism these days, which could make for a big lag
    > between compiler versions in wide usage and the current
    > C Standard.


    What nonsense is this? There's still some old pre-standard C code
    around, yeah, but the same is true (probably more so) for C++. C has
    been standardized several years longer.

    > The DEC/PDP 10 had word size of 36 bits. The size of a character
    > could be set (by loading a special register) to 6, 7, 8 or 9 bits. I
    > never saw a C implementation for the DEC 10. If char was defined to
    > be 8 bits, then it would probably make sense to define a byte to be 4
    > bits rather than 8 (unless sizeof was redefined to return a float).


    There's no requirement for char to be eight bits, in either language.
    It must be at least eight.



    Brian
     
    Default User, Aug 3, 2005
    #7
  8. Guest

    Default User wrote:
    > wrote:
    >
    > > Victor Bazarov wrote:

    >
    > > > That's nonsense. It's true for both C and C++.

    > >
    > > I'll take your word for it that sizeof(char) == 1 has made it
    > > into the C Standard now as well.

    >
    > If made it into there years before C++ even had a standard.


    Looks like you're right about that, it was in the first ANSI
    C Standard. Anyone still got a first ed. of K&R? Be interested
    to hear what it says about this issue.

    > > But I still see alot of
    > > "#ifdef ANSI_C" as I'm browsing through C code. C is all
    > > about anachronism these days, which could make for a big lag
    > > between compiler versions in wide usage and the current
    > > C Standard.

    >
    > What nonsense is this? There's still some old pre-standard C code
    > around, yeah, but the same is true (probably more so) for C++. C has
    > been standardized several years longer.


    There's a high probability that no C/C++ compiler in use now (or that
    was ever used) has sizeof(char) != 1 . But in general, for both C
    and C++, if you really want to maximize the portability of your
    source code (even for those nonsensical and morally inferior people
    who use a compiler that isn't 100% Standard compliant), it's more
    complex than just coding to the standard.

    > > The DEC/PDP 10 had word size of 36 bits. The size of a character
    > > could be set (by loading a special register) to 6, 7, 8 or 9 bits. I
    > > never saw a C implementation for the DEC 10. If char was defined to
    > > be 8 bits, then it would probably make sense to define a byte to be 4
    > > bits rather than 8 (unless sizeof was redefined to return a float).

    >
    > There's no requirement for char to be eight bits, in either language.
    > It must be at least eight.


    Yeah just make it 9 bits and waste a bit. I guess I just need to get
    over the traumas of having learned to program on a machine that used
    magnetic core memory.
     
    , Aug 3, 2005
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. VisionSet

    Roedy style observation ;-/

    VisionSet, Sep 21, 2003, in forum: Java
    Replies:
    30
    Views:
    853
    Thomas G. Marshall
    Sep 30, 2003
  2. Sameer

    An Interesting Observation

    Sameer, Jan 9, 2006, in forum: Java
    Replies:
    2
    Views:
    347
    Oliver Wong
    Jan 9, 2006
  3. lallous

    std::map observation

    lallous, Jan 14, 2004, in forum: C++
    Replies:
    3
    Views:
    4,166
    Ron Natalie
    Jan 14, 2004
  4. John Coleman

    Observation on "Core Python Programming"

    John Coleman, Oct 29, 2006, in forum: Python
    Replies:
    11
    Views:
    489
    John Salerno
    Oct 30, 2006
  5. Replies:
    40
    Views:
    1,073
    Keith Thompson
    Feb 8, 2005
Loading...

Share This Page