void*是否始终具有与char*相同的表示形式?

void*是否始终具有与char*相同的表示形式?,c,pointers,language-lawyer,C,Pointers,Language Lawyer,void*是否总是与char*具有相同的表示形式 详细信息: 我想使用一个变量函数,它接受以(char*)0结尾的char*,如下所示: int variadic(char*, ...); //<-prototype variadic("foo", "bar", (char*)0); //<- usage 我使用它来终止我的变量(char*,…)合法吗?特别允许使用va_arg(args,char*)访问void*参数,反之亦然,而不仅仅是空指针 另见C11第6.2.5条第28款(

void*
是否总是与
char*
具有相同的表示形式

详细信息:

我想使用一个变量函数,它接受以
(char*)0
结尾的char*,如下所示:

int variadic(char*, ...); //<-prototype
variadic("foo", "bar", (char*)0); //<- usage

我使用它来终止我的变量(char*,…)合法吗?

特别允许使用
va_arg(args,char*)
访问
void*
参数,反之亦然,而不仅仅是空指针

另见C11第6.2.5条第28款(草案)规定:

指向void的指针应具有相同的表示和对齐方式 作为字符类型指针的要求。48)类似地,指针 兼容类型的合格或不合格版本应具有 相同的表示和对齐要求


(我的重点)。

A
void*
总是隐式转换为任何其他(数据)指针类型,这是
C
标准给定的。@StoryTeller:是的,但这仅在进行转换时才起作用。您是否检查了实现中如何定义
NULL
宏?它通常是
((void*)0)
。但是如果将
0
传递给一个可变函数,它将作为
int
传递,这不是您想要的。所以你必须投下它。@PSkocik:看最后一句。(也许我应该加上“……为了安全起见”)。从早期版本的C开始,整个
NULL
/
0
东西就被设计破坏了。我总是想知道为什么当时没有遵循Pascal(Algol?)轨迹,并将其作为特殊关键字提供。@LưuVĩnhPhúC:这不一样,因为空指针和变量函数参数一样特殊。这实际上是一个有趣的要求。因此,在代码指针大于数据指针的体系结构中,这一要求强制填充字符指针。Intel 80C51就是这样一个例子,因为它有128字节的ram,但有4 KB的程序rom。(虽然这是一个经过修改的哈佛体系结构,允许将程序rom作为数据读取,因此统一的数据指针仍然需要更多的空间)@poizan42我认为函数指针和数据指针在C中的处理方式不同,显式处理您提到的代码指针较大的情况。POSIX(但不是C语言标准)需要将代码指针无损地转换为
void*
,以便
dlsym
函数工作。请注意,这不足以允许
void*
作为非类型参数传递,被调用方希望
char*
,反之亦然。(根据MSalters的回答,在
va_arg
的定义中有其他规则可以弥补这一差距。)这在C90中不是一个要求。@dan04:这仅适用于通过
dlsym()
获得的函数指针。原则上,其他函数指针值可能无法无损转换为
void*
。这是在C99中添加的。在C90中,您是不允许这样做的。@zwol:老实说,这已经有四分之一世纪了。@MSalters,但是,我猜C89仍然是绝大多数C编译器的默认值。@zwol我想说,在C90中,这是允许的,但没有明确规定。很难找到C90标准为什么会有这样一行:“指向void的指针应具有与指向字符类型的指针相同的表示和对齐要求。”如果不是出于此目的。在标准化之前,该语言没有
void*
;我似乎很清楚,其目的是对于非原型函数参数(包括K&R样式的参数,以及原型变量函数的变量部分),
char*
void*
是可互换的
#define NIL (void*)0 /*<= never a plain 0*/