Re: varargs in C (AMD64 architecture)

Discussion in 'C Programming' started by Grumble, Dec 22, 2005.

  1. Grumble

    Grumble Guest

    [ Cross-posted to c.l.c. and Followup-To set ]

    Tim Roberts wrote:

    > Dave Thompson wrote:
    >
    >> I have heard of a machine where all-bits-0 is not a null
    >> pointer so passing 0 for a null pointer is wrong even though it is the
    >> correct size.

    >
    > This is dead wrong. Regardless of what the actual bit pattern for a null
    > pointer is for a particular compiler on a particular piece of hardware, the
    > constant 0 is ALWAYS a valid way to spell "null pointer" in standard
    > programs, and a null pointer must ALWAYS compare equal to the constant 0.
    > That's one of the more magical constructs in the ISO standards.


    Sure. But what if you do this:

    struct toto { char *p1, *p2; };

    int main(void) {
    struct toto foo = calloc(12, sizeof foo);
    return 0;
    }

    foo.p{1,2} are initialized to all-bits-0

    >> I don't know of any machine where null pointers differ
    >> from each other and so (char*)0 versus (int*)0 will actually fail, but
    >> the C standard would allow it.

    >
    > No, it would not. (char*)0 and (int*)0 (and 0, for that matter) are both
    > REQUIRED to be acceptable as null pointers.
    >
    >> If you want to live within the "letter
    >> of the law" and be guaranteed to work on machines you've never seen,
    >> even those that don't exist yet, (CorrectType*)0 is the way.

    >
    > Not true. For C, the universally acceptable spelling for "null pointer" is
    > ((void*)0). For C++, the universally acceptable spelling for "null
    > pointer" is 0. The compiler is REQUIRED to make these work. See
    > <stddef.h>.
    Grumble, Dec 22, 2005
    #1
    1. Advertising

  2. Grumble

    Flash Gordon Guest

    Grumble wrote:
    > [ Cross-posted to c.l.c. and Followup-To set ]
    >
    > Tim Roberts wrote:
    >
    >> Dave Thompson wrote:
    >>
    >>> I have heard of a machine where all-bits-0 is not a null
    >>> pointer so passing 0 for a null pointer is wrong even though it is the
    >>> correct size.

    >> This is dead wrong. Regardless of what the actual bit pattern for a null
    >> pointer is for a particular compiler on a particular piece of hardware, the
    >> constant 0 is ALWAYS a valid way to spell "null pointer" in standard
    >> programs, and a null pointer must ALWAYS compare equal to the constant 0.
    >> That's one of the more magical constructs in the ISO standards.

    >
    > Sure. But what if you do this:
    >
    > struct toto { char *p1, *p2; };
    >
    > int main(void) {
    > struct toto foo = calloc(12, sizeof foo);


    I think you mean:
    struct toto *foo = calloc(12, sizeof *foo);

    > return 0;
    > }
    >
    > foo.p{1,2} are initialized to all-bits-0


    No, that is not guaranteed to produce null pointers.

    >>> I don't know of any machine where null pointers differ
    >>> from each other and so (char*)0 versus (int*)0 will actually fail, but
    >>> the C standard would allow it.

    >> No, it would not. (char*)0 and (int*)0 (and 0, for that matter) are both
    >> REQUIRED to be acceptable as null pointers.


    You would have to cast the int* to a char* (or void*) but yes, they are
    then required to compare equal even if the compiler has to do some
    clever stuff.

    >>> If you want to live within the "letter
    >>> of the law" and be guaranteed to work on machines you've never seen,
    >>> even those that don't exist yet, (CorrectType*)0 is the way.

    >> Not true. For C, the universally acceptable spelling for "null pointer" is
    >> ((void*)0). For C++, the universally acceptable spelling for "null
    >> pointer" is 0.


    0 is also guaranteed to be a null pointer constant on C. You do have to
    cast it in some conditions, such as passing it as one of the optional
    arguments on a varidac function, since then the compiler does not know
    that it is meant to be a pointer instead of an int.

    >> The compiler is REQUIRED to make these work. See
    >> <stddef.h>.


    Many other headers also declare NULL.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
    Flash Gordon, Dec 22, 2005
    #2
    1. Advertising

  3. Grumble <> writes:
    > [ Cross-posted to c.l.c. and Followup-To set ]
    > Tim Roberts wrote:
    >> Dave Thompson wrote:
    >>> I have heard of a machine where all-bits-0 is not a null
    >>> pointer so passing 0 for a null pointer is wrong even though it is the
    >>> correct size.

    >>
    >> This is dead wrong. Regardless of what the actual bit pattern for a null
    >> pointer is for a particular compiler on a particular piece of hardware, the
    >> constant 0 is ALWAYS a valid way to spell "null pointer" in standard
    >> programs, and a null pointer must ALWAYS compare equal to the constant 0.
    >> That's one of the more magical constructs in the ISO standards.


    In C, 0 one of many forms of null pointer constant. By itself,
    though, it's an expression of type int. It's guaranteed to yield a
    null pointer (a value at execution time) *when converted to a pointer
    type*.

    In most contexts where you'd want to use a null pointer constant, this
    conversion will be done implicitly. But the conversion *won't* be
    done if it's an argument to a function with no visible prototype
    (solution: always provide a visible prototype) or to a function such
    as printf that takes a variable number of arguments (solution: use a
    cast, one of the few cases where an explicit cast does more good than
    harm).

    For example:

    printf("%d", 0); /* ok, 0 is of type int */
    printf("%p", 0); /* not ok, 0 is still of type int */
    printf("%p", (void*)0)); /* ok */
    printf("%p", NULL); /* not ok, NULL could be defined as 0 */
    printf("%p", (void*)NULL); /* ok */

    The cases mark "not ok" invoke undefined behavior. (The second one
    may or may not invoke UB, depending on how the implementation defines
    NULL, but conditional UB should be treated as UB, i.e., Don't Do That.)

    As a matter of style, I recommend always using the NULL macro to
    denote a null pointer constant; it makes the code less ambiguous to
    the reader (though the compiler, of course, doesn't care as long as
    you get it right). NULL could expand to *any* valid null pointer
    constant; don't make any assumptions about which one.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Dec 22, 2005
    #3
    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. Muhammad Khan
    Replies:
    4
    Views:
    1,214
    Mike Treseler
    Jul 10, 2003
  2. Replies:
    3
    Views:
    503
    Malcolm
    Sep 29, 2005
  3. rashmi
    Replies:
    2
    Views:
    449
    Grumble
    Jul 5, 2005
  4. Replies:
    3
    Views:
    414
    Malcolm
    Sep 29, 2005
  5. Replies:
    4
    Views:
    653
    Malcolm
    Sep 29, 2005
Loading...

Share This Page