C 标准是否定义了空指针常数以将所有位设置为零?

C 标准是否定义了空指针常数以将所有位设置为零?,c,standards,language-lawyer,C,Standards,Language Lawyer,(我引用的是ISO/IEC 9899:201x) 这里我们看到,整数常量表达式有一个整数类型: 6.6常量表达式 六,。 整型常量表达式应为整型,且只能有操作数 它们是整数常量、枚举常量、字符常量、sizeof 结果为整型常量、\u个表达式和浮点的表达式 作为强制转换的直接操作数的常量。整数常量中的强制转换运算符 表达式只能将算术类型转换为整数类型,但作为 操作数到sizeof或_Alignof运算符 那么,这对于任何整数类型都适用: 6.2.6.2整数类型 五,。 未指定任何填充位的值。有效(

(我引用的是ISO/IEC 9899:201x)

这里我们看到,整数常量表达式有一个整数类型:

6.6常量表达式

六,。 整型常量表达式应为整型,且只能有操作数 它们是整数常量、枚举常量、字符常量、sizeof 结果为整型常量、\u个表达式和浮点的表达式 作为强制转换的直接操作数的常量。整数常量中的强制转换运算符 表达式只能将算术类型转换为整数类型,但作为 操作数到sizeof或_Alignof运算符

那么,这对于任何整数类型都适用:

6.2.6.2整数类型

五,。 未指定任何填充位的值。有效(非陷阱)对象表示形式 符号位为零的有符号整数类型的有效对象表示形式 对应的无符号类型,且应表示相同的值。对于任何整数类型, 所有位均为零的对象表示应为值的表示 那种类型的零

然后,我们看到空指针常量是使用值为0的整数常量表达式定义的

6.3.2.3指针

三,。 值为0的整型常量表达式,或转换为类型的此类表达式 void*,称为空指针常量。如果将空指针常量转换为 指针类型,结果指针称为空指针,保证比较不相等 指向任何对象或函数的指针

因此,空指针常量的所有位都必须设置为零

但是网上和网上有很多答案都说那不是真的

考虑到引用的部分,我很难相信他们

(请参考最新标准进行回答)

标准是否定义了空指针常数以将所有位设置为零

不,没有。C标准的任何段落均未规定此类要求

void *p = 0;
例如,
p
是空指针,但标准不要求对象
p
必须设置所有位


有关信息,c-faq网站在这里提到了一些具有非零空指针表示的系统:

询问空指针常量的表示是毫无意义的


空指针常量具有整数类型或void*类型。不管它是什么,它都是一种价值。它不是一个物体。值没有表示形式,只有对象有表示形式。我们只能通过获取对象的地址,将其强制转换为char*或unsigned char*并查看字节来讨论表示。对于空指针常量,我们不能这样做。一旦分配给对象,它就不再是空指针常量

不,NULL不一定要全部为零位

N1570 6.3.2.3指针第3段:

值为0的整型常量表达式,或转换为类型的此类表达式 void*,称为空指针常量。66)如果将空指针常量转换为 指针类型,生成的指针称为空指针,保证比较不相等 指向任何对象或函数的指针

请参见上面我的重点:整数
0
在必要时进行转换,它不必具有相同的位表示

页面底部的注释66表示:

66)宏NULL在(和其他标头)中定义为NULL指针常量;见7.19

这就引出了该章的一段:

宏是

NULL

它扩展为实现定义的空指针常量

此外,附件J.3.12(可移植性问题、实现定义的行为、库函数)中指出:

-宏null扩展到的null指针常量(7.19)


C标准的一个主要限制是,由于作者希望避免禁止编译器以任何地方的任何生产代码可能依赖的任何方式运行,因此它没有指定程序员需要知道的许多事情。因此,通常需要对标准中没有规定但符合常见编译器行为的内容进行假设。构成空指针的所有字节都为零的事实就是这样一个假设

除了每种数据类型(包括指针)的每一个可能值都可以表示为
char
value(*)序列之外,C标准中没有规定任何关于任何指针的位级表示的内容。尽管如此,在几乎所有通用平台上,将与结构关联的所有字节归零相当于将所有成员的类型设置为静态默认值(指针的默认值为null)。此外,使用
calloc
接收结构集合的RAM块清零的代码通常比使用
malloc
然后必须手动清除每个结构的每个成员的代码快得多,或者使用
calloc
,但仍然手动清除每个结构的每个非整数成员

因此,我建议,在许多情况下,编写针对C语言的代码是完全合理的,其中空指针存储为所有字节零,并且有一个文档化的要求,即它将不适用于不是这种情况的语言。也许有一天,ISO会提供一种标准方法,通过这种方法,这些要求可以以机器可读的形式记录下来(这样每个编译器都必须遵守程序规定的要求或拒绝编译),但据我所知,目前还不存在

(*)据我所知,编译器是否需要
int funcomp(int **pp, int **qq)
{
    int *p,*q;
    p = (int*)malloc(1234);
    *pp = p;
    free(p);
    q = (int*)malloc(1234);
    *qq = q;
    *q = 1234;
    if (!memcmp(pp, qq, sizeof p))
      return *p;
    return 0;
 }