Path: csiph.com!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: Null pointer constant Date: Mon, 19 Jun 2017 14:28:29 -0700 Organization: None to speak of Lines: 53 Message-ID: References: <9zM1B.193976$KK7.183000@fx12.am4> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: mx02.eternal-september.org; posting-host="6cbb5d51c319bdfdc6c4f737cfea8267"; logging-data="11779"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19rkmrRBbD8cOLM2d3r8tKU" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:YcBNfnyYhovMY9Uy7BZL79O9n10= sha1:+1W4ET+yi+b9NEMtzWn+cd2nUFc= Xref: csiph.com comp.lang.c:112639 Ike Naar writes: > On 2017-06-19, Keith Thompson wrote: >> David Brown writes: >>> You can also write: >>> >>> p = (a, b, NULL); >>> >>> That is one of the purposes of having the NULL macro - it is /always/ a >>> null pointer constant. >> >> So is 0. Indeed NULL can be #defined simply as 0. > > Indeed it can, but it can lead to unpleasant surprises. But defining it as ((void*)0) doesn't avoid all those surprises. > Consider variadic functions. > > If a variadic function expects a pointer in the variable part of > the parameter list, and the caller provides a NULL argument that > expands to an unadorned 0, the NULL is interpreted as an int in > such a context, and it is not passed correctly if ints and pointers > have different sizes. > > In the past I've been bitten by this with variadic functions from > the X window system that expected a list of strings (pointer to > char), terminated by a null pointer to char. If one called such a > function as > > function("Martha", "my", "dear", NULL); > > one would get all kinds of weird errors on an implementation that > defined NULL as plain 0, when on that platform sizeof (int) != > sizeof (char*). > > Those calls had to be changed to > > function("Martha", "my", "dear", (char*) NULL); If the function treats its arguments as a char* or void*, then passing an unadorned NULL should work if NULL is defined as ((void*)0). But if the function expects, for example, an int*, then ((void*)0) is not guaranteed to have the same representation, and may cause undefined behavior. If you need to pass a null pointer as a variadic argument, always cast it to the appropriate printer type. -- Keith Thompson (The_Other_Keith) kst-u@mib.org Working, but not speaking, for JetHead Development, Inc. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister"