I understand that a char
variable can accept a null
character(1 byte) i.e; \0
as its value but, I don't understand how a char variable in my application below accepts a pointer(4 bytes) as its value and still works properly?
#include<stdio.h>
int main()
{
char p[10]="Its C";
printf("%s\n",p);
p[3]='\0'; // assigning null character
printf("%s\n",p);
p[2]=NULL; // assigning null pointer to a char variable
printf("%s\n",p);
p[1]=(void *)0; // assigning null pointer to a char variable
printf("%s\n",p);
return 0;
}
Note: GCC Compiler (32 Bit Linux Platform).
The NULL
macro is required to expand to "an implementation-defined null pointer constant".
A null pointer constant is defined as "An integer constant expression with the value 0, or such an expression cast to type void *
". Counterintuitively, this definition does not require the expansion of NULL
to be an expression of pointer type. A common implementation is:
#define NULL 0
A null pointer constant, when used in a context that requires a pointer, may be implicitly converted to a pointer value; the result is a null pointer. It may also be explicitly converted using a cast, such as (int*)NULL
.
But there's no requirement that an expression that qualifies as a null pointer constant may only be used in such a context. Which means that if the implementation chooses to define NULL
as above, then this:
char c = NULL; // legal but ugly
is legal and initializes c
to the null character.
Such an initialization is non-portable (since NULL
may also expand to ((void*)0)
and misleading, so it should be avoided, but a compiler is likely to let it through without warning; NULL
is expanded to 0
by the preprocessing phase of the compiler, and later phases see it as char c = 0;
, which is legal and innocuous -- though personally I'd prefer char c = '\0';
.
I just tried your example on my own 32-bit Ubuntu system, with gcc 4.7. With no options specified, the compiler warned about both p[2]=NULL;
and p[1]=(void *)0;
:
c.c:8:9: warning: assignment makes integer from pointer without a cast [enabled by default]
c.c:10:9: warning: assignment makes integer from pointer without a cast [enabled by default]
The second warning is to be expected from any C compiler; the first indicates that NULL
is actually defined as ((void*)0)
(running the code through gcc -E
confirms this).
The compiler didn't simply "accept" these assignments; it warned you about them. The C language standard merely requires a "diagnostic" for any violation of the language rules, even a syntax error; that diagnostic may legally be a non-fatal warning message. You can make gcc behave more strictly with -std=c89 -pedantic-errors
; replace c89
by c99
or c11
to enforce rules from later versions of the standard. (EDIT: I see from comments that you're using a web interface to the compiler that hides warnings; see my comment on your question for a workaround. Warnings are important.)
If you post C code that produces compiler warnings please show us the warnings and pay close attention to them yourself. They often indicate serious problems, even illegalities, in your program.
A language-lawyer quibble: it's not even clear that this:
char c = (void*)0;
specifies a conversion from void*
to char
. My own view is that, since it violates a constraint, it has no defined semantics. Most compilers that don't reject it will treat it as if it were a void*
-to-char
conversion, and it's also been argued that this is the required behavior. But you can avoid such questions if you simply pay attention to compiler warnings and/or don't write code like that in the first place.
(The rules are a bit different for C++, but you're asking about C so I won't get into that.)
NULL
is a macro and for almost platform is defined in this way
#ifndef __cplusplus
#define NULL ((void *)0)
#else /* C++ */
#define NULL 0
#endif /* C++ */
(from stddef.h
from my Ubuntu)
and when you write
p[2]=NULL;
It's the same
p[2]=(void *)0; //for c
p[2]=0; //for c++
It's the same
p[2] = 0; // the 0 is casted to char 0 for C --> '\0'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With