24
votes

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*,...)?

2
A void* is always implicitly convertible to any other (data) pointer type, that's a given by the C standard.StoryTeller - Unslander Monica
@StoryTeller: Yes, but that only matters if there is a conversion being done.MSalters
Did you check how the NULL macro is defined in your implementation? It typically is ((void *)0). But if you pass 0 to a variadic function, it will be passed as int, which is not what you want. So you have to cast it anyway.too honest for this site
@PSkocik: See the last sentence. (Maybe I should have added "... to be on the safe side"). That whole NULL/0 stuff is broken by design since early versions of C. I always wonder why then did not follow the Pascal (Algol?)-Trail and provided that as special keyword.too honest for this site
@LưuVĩnhPhúc: It is not the same, because null pointers are special as are variadic function parameters.too honest for this site

2 Answers

35
votes

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).

11
votes

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