I want initialize a function pointer so that it is null. Which of these two ways is preferred?
void (*Pointer)(void) = NULL;
Or
void (*Pointer)(void) = (void (*)(void))0;
0 is implicit convertible to any pointer type. Though how your compiler implements NULL depends.
In your code you can simply write
void (*Pointer)(void) = 0; but it won't be portable , so write void (*Pointer)(void) = NULL;
The standard (ISO/IEC 9899:2011) says:
§6.3.2.3 Pointers
¶1 A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
¶2 For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal.
¶3 An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.66) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
¶4 Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.
…
¶8 A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.
66) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.19.
§7.19 Common definitions <stddef.h>
¶3 The macros are
NULL
which expands to an implementation-defined null pointer constant; …
All of which adds up to say that either of the notations used in the question is valid and they (and other similar expressions) are equivalent and there will be no problem.
void (*Pointer)(void) = NULL;
void (*Pointer)(void) = (void (*)(void))0;
void (*Pointer)(void) = 0;
Do note that the standard doesn't explicitly say you can convert a pointer to an object type into a pointer to a function type, or vice versa, or that round-tripping is guaranteed to work. Remember, there were once memory models for early Intel machines where data (object) pointers were a different size from function pointers — and that can still happen on other machines (IBM AS/400 and its heirs and successors is another example).
You could also study the questions and answers on the null pointer from http://c-faq.com/.
NULL is defined to be a null pointer constant. A null pointer constant can be used to initialise any pointer (data pointer or function pointer) to a null pointer of the correct type, so assigning NULL is just fine.
0 will also work, because 0 is also a null pointer constant. So will 0L, (13*12-156) and many other ways. NULL is preferred because it shows your intent to assign a null pointer.
The line below that is just unnecessary work.
Related
Will a void* always have the same representation as a char* ?
Details:
I want to work with a variadic function that takes char*'s terminated by a (char*)0 like so:
int variadic(char*, ...); //<-prototype
variadic("foo", "bar", (char*)0); //<- usage
I wanted to replace (char*)0 with NULL, but judging from
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf's:
66) The macro NULL is defined in (and other headers) as a
null pointer constant; see 7.19.
3 An integer constant expression with the value 0, or such an
expression cast to type void *, is called a null pointer constant. 66)
If a null pointer constant is converted to a pointer type, the
resulting pointer, called a null pointer, is guaranteed to compare
unequal to a pointer to any object or function.
I can't, because in the variadic context, I absolutely need a char* and a plain 0 is unacceptable.
If I defined:
#define NIL (void*)0 /*<= never a plain 0*/
would it be legal for me to use it to terminate my variadic(char*,...)?
C11, §6.2.5, ¶28 (draft N1570) says:
A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type. 48) Similarly, pointers
to qualified or unqualified versions of compatible types shall have the
same representation and alignment requirements.
(emphasis mine).
It's specifically allowed to access a void* argument using va_arg(args, char*) and vice versa, not just for the null pointer.
See also http://en.cppreference.com/w/cpp/utility/variadic/va_arg
Is it guaranteed, in C, that any pointer type can round-trip through void * successfully?
That is, something like the following guaranteed to work:
typedef struct {
...
} A;
A *p = ...;
void *v = p;
A *p2 = v;
// use p2 here
No matter what the type of A?
Object pointers can indeed be round-tripped through void*. From C11 6.3.2.3 paragraph 1:
A pointer to void may be converted to or from a pointer to any object type. A pointer to
any object type may be converted to a pointer to void and back again; the result shall
compare equal to the original pointer.
Note that the opposite direction is not true, when you convert a void pointer to some object pointer and back you are not guaranteed the same value as what you started with.
Note also that this is not true of function pointers; however, all function pointer types are mutually round-trippable: Paragraph 8 says:
A pointer to a function of one type may be converted to a pointer to a function of another
type and back again; the result shall compare equal to the original pointer.
Moreover, object pointers are also round-trippable among themselves (not involving void pointers), subject to some constraints, by paragraph 7:
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned) for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer.
Will a void* always have the same representation as a char* ?
Details:
I want to work with a variadic function that takes char*'s terminated by a (char*)0 like so:
int variadic(char*, ...); //<-prototype
variadic("foo", "bar", (char*)0); //<- usage
I wanted to replace (char*)0 with NULL, but judging from
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf's:
66) The macro NULL is defined in (and other headers) as a
null pointer constant; see 7.19.
3 An integer constant expression with the value 0, or such an
expression cast to type void *, is called a null pointer constant. 66)
If a null pointer constant is converted to a pointer type, the
resulting pointer, called a null pointer, is guaranteed to compare
unequal to a pointer to any object or function.
I can't, because in the variadic context, I absolutely need a char* and a plain 0 is unacceptable.
If I defined:
#define NIL (void*)0 /*<= never a plain 0*/
would it be legal for me to use it to terminate my variadic(char*,...)?
C11, §6.2.5, ¶28 (draft N1570) says:
A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type. 48) Similarly, pointers
to qualified or unqualified versions of compatible types shall have the
same representation and alignment requirements.
(emphasis mine).
It's specifically allowed to access a void* argument using va_arg(args, char*) and vice versa, not just for the null pointer.
See also http://en.cppreference.com/w/cpp/utility/variadic/va_arg
Literally, does (char *) 0 mean a pointer to some location that contains a zero? Does the system create such an address with value 0 for each such declaration?
No, it's a cast of 0 to type char *. That is, a null pointer. A 0 in any pointer context refers to the null pointer constant.
What exactly it points to doesn't matter - dereferencing it would cause undefined behaviour.
For more, check out the C FAQ Part 5: Null Pointers.
It is null pointer value of type char *.
From the C++ Standard
A null pointer constant can be converted to a pointer type; the result
is the null pointer value of that type
And from the C Standard
3 An integer constant expression with the value 0, or such an
expression cast to type void *, is called a null pointer constant.66)
If a null pointer constant is converted to a pointer type, the
resulting pointer, called a null pointer, is guaranteed to compare
unequal to a pointer to any object or function.
4 Conversion of a null pointer to another pointer type yields a null
pointer of that type. Any two null pointers shall compare equal.
It is not a pointer that points to a locarion that contains 0. So the system creates nothing. As it is written in the C Standard the null pointer "is guaranteed to compare unequal to a pointer to any object or function". So it is used to determine whether a pointer points to some object or function.
its an explicit cast to a null pointer. i believe there is a #define macro for it allowing you to just write NULL
In the context of another question there was some discussion on whether it was allowed (i.e. would or would not introduce implementation defined or undefined behavior) to cast int** to void** and subsequently assign a value to the dereferenced void*. This brings me to my question on the interpretation of the C11 standard
6.2.5 (28) A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. ...
6.3.2.3 (1) A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
6.3.2.3 (7) ... When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. ...
My question is whether this
int* intptr = NULL;
void* dvoidptr = &intptr; /* 6.3.2.3 (1) */
*(void**)dvoidptr = malloc(sizeof *intptr); /* using 6.3.2.3 (1) */
conforms with the standard or not? It seems strange to me, but I cannot find a conclusive line of argument why not. void* to void** is guaranteed by 6.3.2.3 and 6.2.5 together with 6.3.2.3 help with the alignment.
Code is not valid.
See the emphasis:
6.3.2.3 (1) A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
You are converting int** to void* (fine), and then to different type void** (not ok). C gives no quarantee that you can safely convert void* to anything other than the original type (aside from converting to char *)
In addition, *(void**)dvoidptr results in void* when in reality there is int*. What if, for example, sizeof(void*) == 2 and sizeof(int*) == 1? You can convert void* pointer to other type, but you cannot reinterpret it directly as other type.