sizeof()'s strange behviour

Discussion in 'C Programming' started by Richard Bos, Apr 8, 2008.

  1. Richard Bos

    Richard Bos Guest

    arnuld <> wrote:

    > sizeof() operator gives 2 different types of size outputs :\ but I do not
    > understand why:


    You need to read this <http://c-faq.com/aryptr/index.html> section of
    the FAQ; in particular question 6.4, but the rest will be useful, too.

    Richard
    Richard Bos, Apr 8, 2008
    #1
    1. Advertising

  2. arnuld wrote:
    > sizeof() operator gives 2 different types of size outputs :\ but I do not
    > understand why:
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    >
    >
    > int my_size( char [] );
    >
    >
    > int main()
    > {
    > char s[] = "Saurabh Nirkhey";
    >
    > printf("sizeof(%s): %d\n", s, sizeof(s));
    > printf("sizeof(%s): %d\n", s, my_size(s));
    >
    >
    > return 0;
    > }
    >
    > int my_size( char s[] )
    > {
    > return sizeof(s);
    > }


    In C, arrays cannot be used as function parameters. While it looks like
    my_size() takes a char [], C rewrites the declaration so that it
    actually takes a char *. The value passed to my_size() is a pointer to
    the first element of s (if it helps, you can think of it as &s[0]). The
    s within my_size is therefore a char *, and sizeof(s) tells you the size
    of a char *.

    Usually strlen() is the correct tool when dealing with strings.

    See also FAQ question 6.4 (the clc FAQ is at http://c-faq.com/), and the
    whole of section 6 is probably useful.

    pgp@bullfinch:~/tmp$ cat str.c
    #include <stdio.h>
    #include <string.h>
    int main(void) {
    char str1[10] = "String";
    char str2[100] = "String";
    printf("str1 and str2 are %s\n",
    strcmp(str1,str2) == 0 ? "equal" : "not equal");
    printf("strlen(str1) == %d, strlen(str2) == %d\n",
    strlen(str1),strlen(str2));
    printf("sizeof str1 == %d, sizeof str2 == %d\n",
    sizeof str1, sizeof str2);
    return 0;
    }
    pgp@bullfinch:~/tmp$ gcc -ansi -pedantic -ostr str.c
    pgp@bullfinch:~/tmp$ ./str
    str1 and str2 are equal
    strlen(str1) == 6, strlen(str2) == 6
    sizeof str1 == 10, sizeof str2 == 100
    pgp@bullfinch:~/tmp$

    The above shows that sizeof and strlen are measuring different things.
    sizeof tells you the size of a type (in this case two array types,
    char[10] and char[100]), while strlen() tells you the length of a string
    (which may not fill the whole array).
    Philip Potter, Apr 8, 2008
    #2
    1. Advertising

  3. Richard Bos

    arnuld Guest

    sizeof() operator gives 2 different types of size outputs :\ but I do not
    understand why:


    #include <stdio.h>
    #include <stdlib.h>


    int my_size( char [] );


    int main()
    {
    char s[] = "Saurabh Nirkhey";

    printf("sizeof(%s): %d\n", s, sizeof(s));
    printf("sizeof(%s): %d\n", s, my_size(s));


    return 0;
    }



    int my_size( char s[] )
    {
    return sizeof(s);
    }


    ============ OUTPUT =============
    /home/arnuld/programs/C $ gcc -ansi -pedantic -Wall -Wextra 5-4.c
    /home/arnuld/programs/C $ ./a.out
    sizeof(Saurabh Nirkhey): 16
    sizeof(Saurabh Nirkhey): 4
    /home/arnuld/programs/C $


    --http://lispmachine.wordpress.com/

    Please remove capital 'V's when you reply to me via e-mail.
    arnuld, Apr 8, 2008
    #3
  4. Richard Heathfield <> writes:
    > arnuld said:

    [...]
    >> printf("sizeof(%s): %d\n", s, sizeof(s));

    >
    > ...so we'd expect this to print 16 in place of the second % format
    > specifier. Note that your printf is misleading. It will print:
    >
    > sizeof(Saurabh Nirkhey): 16
    >
    > but in fact it's sizeof s that is 16.

    [...]

    Furthermore, "%d" causes printf to expect an int argument, but
    sizeof(s) is of type size_t. It's likely to happen to work on systems
    where int and size_t are the same size, but the right way is (with a
    couple of other tweaks):

    printf("sizeof s: %d\n", (int)sizeof s);

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Apr 8, 2008
    #4
  5. Keith Thompson wrote:
    > Richard Heathfield <> writes:
    >> arnuld said:

    > [...]
    >>> printf("sizeof(%s): %d\n", s, sizeof(s));

    >> ...so we'd expect this to print 16 in place of the second % format
    >> specifier. Note that your printf is misleading. It will print:
    >>
    >> sizeof(Saurabh Nirkhey): 16
    >>
    >> but in fact it's sizeof s that is 16.

    > [...]
    >
    > Furthermore, "%d" causes printf to expect an int argument, but
    > sizeof(s) is of type size_t. It's likely to happen to work on systems
    > where int and size_t are the same size, but the right way is (with a
    > couple of other tweaks):
    >
    > printf("sizeof s: %d\n", (int)sizeof s);
    >

    Richard mentioned this already in his post.

    I'd add that C99 provides the 'z' format modifier for size_t values:

    printf("sizeof s: %zd\n", sizeof s);

    ....although if your code isn't C99 for other reasons, this is hardly a
    great reason to break C90 compatibility.
    Philip Potter, Apr 8, 2008
    #5
  6. Philip Potter <> writes:
    > Keith Thompson wrote:
    >> Richard Heathfield <> writes:
    >>> arnuld said:

    >> [...]
    >>>> printf("sizeof(%s): %d\n", s, sizeof(s));
    >>> ...so we'd expect this to print 16 in place of the second % format
    >>> specifier. Note that your printf is misleading. It will print:
    >>>
    >>> sizeof(Saurabh Nirkhey): 16
    >>>
    >>> but in fact it's sizeof s that is 16.

    >> [...]
    >>
    >> Furthermore, "%d" causes printf to expect an int argument, but
    >> sizeof(s) is of type size_t. It's likely to happen to work on systems
    >> where int and size_t are the same size, but the right way is (with a
    >> couple of other tweaks):
    >>
    >> printf("sizeof s: %d\n", (int)sizeof s);
    >>

    > Richard mentioned this already in his post.


    Did he? I expected him to do so, and I was surprised when I didn't
    see it, and surprised again when I didn't see it when I re-read his
    article just now. He did mention that size_t yields a size_t rather
    than an int, but in the context of returning the result from the OP's
    my_size() function, not in the context of passing the result to
    printf.

    [...]

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Apr 8, 2008
    #6
  7. Richard Bos

    arnuld Guest

    > On Tue, 08 Apr 2008 11:16:40 +0000, Richard Heathfield wrote:

    > Anyway, bottom line is: what you've discovered is that you can't pass
    > arrays to functions. You can fake it, but you can't actually pass the
    > array itself. If you try to take an array's value (e.g. by passing it to a
    > function or adding it to an integer value), what you actually get is a
    > pointer to the array's first element.


    > .... {SNIP}...


    > So evaluating the name of an array gives a pointer to the first element,
    > QED.



    okay, I have written this. So now I know about both sizeof() and that
    arrays can not be passed to functions :

    /* A program to understand the output of sizeof operator
    *
    */



    #include <stdio.h>
    #include <stdlib.h>


    int main()
    {
    int arr_char, arr_int, arr_LD;
    char ac[] = "abc";
    int ai[] = { 1, 2, 3};
    long double ald[] = { 1.3, 78659.90098, 0.0001 };

    /* casting to int because sizeof yields a size_t value */
    arr_char = (int) sizeof( ac );
    arr_int = (int) sizeof( ai );
    arr_LD = (int) sizeof( ald );

    printf("Size of different types of Arrays in BYTES: \n");
    printf("\n%d\n", arr_char);
    printf("%d\n", arr_int);
    printf("%d\n", arr_LD);

    arr_char = ( (int) sizeof(ac) / sizeof(char) ) - 1;
    arr_int = ( (int) sizeof(ai) / sizeof(int) );
    arr_LD = ( (int) sizeof(ald) / sizeof(long double) );
    printf("\nSize of Arrays themselves, number of elements they contain: \n");
    printf("\n%d\n", arr_char);
    printf("%d\n", arr_int);
    printf("%d\n", arr_LD);


    return EXIT_SUCCESS;
    }

    ========= OUTPUT ==============
    /home/arnuld/programs/C $ gcc -ansi -pedantic -Wall -Wextra test.c
    /home/arnuld/programs/C $ ./a.out
    Size of different types of Arrays in BYTES:

    4
    12
    36

    Size of Arrays themselves, number of elements they contain:

    3
    3
    3
    /home/arnuld/programs/C $




    -- http://lispmachine.wordpress.com/

    Please remove capital 'V's when you reply to me via e-mail.
    arnuld, Apr 9, 2008
    #7
  8. arnuld <> writes:
    [...]
    > okay, I have written this. So now I know about both sizeof() and that
    > arrays can not be passed to functions :
    >
    > /* A program to understand the output of sizeof operator
    > *
    > */
    >


    Overall, it's not a bad demonstration, but I have few comments.

    >
    > #include <stdio.h>
    > #include <stdlib.h>
    >
    >
    > int main()


    Ok, but "int main(void)" is preferred.

    > {
    > int arr_char, arr_int, arr_LD;
    > char ac[] = "abc";
    > int ai[] = { 1, 2, 3};
    > long double ald[] = { 1.3, 78659.90098, 0.0001 };
    >
    > /* casting to int because sizeof yields a size_t value */
    > arr_char = (int) sizeof( ac );
    > arr_int = (int) sizeof( ai );
    > arr_LD = (int) sizeof( ald );


    The casts are unnecessary. Both size_t and int are integral types;
    one will be implicitly converted to the other by the assignment.

    The parentheses on the sizeof operators are also unnecessary; they're
    needed only when the argument is a type name, or when you need them to
    specify grouping. Thus:

    arr_char = sizeof ac;
    arr_int = sizeof ai;
    arr_LD = sizeof ald;

    Better yet, since these three variables hold the result of sizeof,
    declare them as size_t (or maybe not; see below).

    > printf("Size of different types of Arrays in BYTES: \n");
    > printf("\n%d\n", arr_char);
    > printf("%d\n", arr_int);
    > printf("%d\n", arr_LD);


    Good. Note that if you followed my advice above and declared these as
    size_t, you'd need to cast them to int for printf. It's usually best
    to declare something of the appropriate type for what it needs to
    hold, but in this case using int does simplify the code. There are
    always tradeoffs.

    > arr_char = ( (int) sizeof(ac) / sizeof(char) ) - 1;
    > arr_int = ( (int) sizeof(ai) / sizeof(int) );
    > arr_LD = ( (int) sizeof(ald) / sizeof(long double) );


    More unnecessary casts and excessive parentheses. And the "- 1" for
    arr_char presumably is intended to allow for the trailing '\0' on the
    string -- but that '\0' is just as much part of the array as the 'a',
    'b', and 'c' are. Your array ac is 4 elements long, not 3.

    Note that sizeof(char) is 1 by definition.

    And here's a good idiom for computing the length of an array:

    arr_char = sizeof ac / sizeof ac[0];
    arr_int = sizeof ai / sizeof ai[0];
    arr_LD = sizeof ald / sizeof ald[0];

    Of course, when using this idiom you have to make sure that the name
    (ac, ai, or ald) is actually the name of an array object, not of, say,
    a function parameter that's really a pointer.

    > printf("\nSize of Arrays themselves, number of elements they contain: \n");
    > printf("\n%d\n", arr_char);
    > printf("%d\n", arr_int);
    > printf("%d\n", arr_LD);
    >
    >
    > return EXIT_SUCCESS;
    > }


    Good. (Note that "return 0;" is equally valid.)

    [snip]

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Apr 9, 2008
    #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. Replies:
    1
    Views:
    1,358
    Roedy Green
    Oct 26, 2005
  2. Derek
    Replies:
    7
    Views:
    24,301
    Ron Natalie
    Oct 14, 2004
  3. Trevor

    sizeof(str) or sizeof(str) - 1 ?

    Trevor, Apr 3, 2004, in forum: C Programming
    Replies:
    9
    Views:
    613
    CBFalconer
    Apr 10, 2004
  4. Vinu
    Replies:
    13
    Views:
    1,383
    Lawrence Kirby
    May 12, 2005
  5. blufox

    sizeof( int ) != sizeof( void * )

    blufox, May 22, 2006, in forum: C Programming
    Replies:
    2
    Views:
    542
    Joe Smith
    May 22, 2006
Loading...

Share This Page