language-lawyer - c 是( ( void* ) 0 ) 一个空指针常量?

  显示原文与译文双语对照的内容

在 this constants和括号中,作者引用了C 标准中的§ 6.3.2.3 和 parenthesized,并说明:

它并不表示圆括号空指针常数是空指针常量。

严格来说,(void*)0 是一个空指针常量,但 ((void*)0) 不是。

然后:

i,大多数C 实现都将带括号的空指针常量当作空指针常量,并将它的定义为。((void*)0) 或者其他形式的空指针常量。

两个引用的部分表示:

6.3.2.3

带值 0或者这样的表达式强制转换为 void *,的整数常量表达式被称为空指针常量。

§ 6.5.1

括号式表达式是主要表达式。 的类型和值与unparenthesized表达式的值相同。 它是左值,函数指示符,或者如果unparenthesized表达式分别是左值。函数指示符或者void表达式,则为void表达式。

粗体句不与作者声明 ((void*)0) 不是空指针常量的声明相矛盾?

时间: 原作者:

粗体句不与作者声明 ((void*)0) 不是空指针常量的声明相矛盾?

不,它不是。( 我承认自己有点偏,因为这个博客是我的。)

粗体句表示它的类型和值与unparenthesized表达式的those相同。 这不足以表示它是一个空指针常量。

请考虑:


void *var = 0;



(void*)0 是空指针常量。 ((void*)0) 具有与 (void*)0 相同的类型和值。 var 也有与 (void*)0 相同的类型和值,但 var 显然不是一个空指针常量。

,99 +%肯定 intent intent intent是一个空指针常量,更一般的说,任何圆括号空指针常量是空指针常量。 这个标准的作者只是忽略了这么说。 由于 6.5.1中括号表达式的描述特别列举了由括号表达式继承的几个它的他特性:

括号式表达式是主要表达式。 它的类型和值与unparenthesized表达式的类型相同。 它是左值,函数指示符,或者如果unparenthesized表达式分别是左值。函数指示符或者void表达式,则为void表达式。

省略是麻烦的( 但只是轻微的如此) 。

但是让我们假设,为了参数,((void*)0) 不是一个空指针常数。 上帝知道你没有宗教信仰

(void*)0 是一个空指针常数,它的值为 void* 类型的空指针,因这里括号表达式 ((void*)0)的值为 void*(void*)0((void*)0) 都是地址常量。 在contexts中,contexts pointer指针常量,并且不接受地址常量? 只有少数几个。

6.5.9 相等运算符

函数指针类型的表达式可以比较为与空指针常量相等。 ( 对象指针可以与 void* 类型的表达式相比,但函数指针可以能不是,除非它是空指针常量) 。


void func(void);


if (func == ((void*)0)) {/*.. . */}



是违反约束的。

6.5.16.1 简单赋值

在赋值中,可以将空指针常量分配给pointer-to-function类型的对象,并将隐式转换为。 不是为空指针常量的类型 void*的表达式不能指定给函数指针。 同样的约束同样适用于传递和初始化。 这就是:


void (*fp)(void) = ((void*)0);



如果 ((void*)0) 不是空指针常量,则为约束冲突。 感谢评论hvd找到这个。

7.19 通用定义 <stddef.h>

NULL 扩展到"一个实现定义了空指针常量"。 如果 ((void*)0) 不是空指针常量,那么:


#define NULL ((void*)0)



将是无效的。这将是对实现的限制,而不是对程序员。 请注意:


#define NULL (void*)0



确定是无效的,因为标准标头中的宏定义必须是完全 protected的,必须在必要的时候括号。 如果没有括号,有效的表达式 sizeof NULL 将是一个语法错误,然后扩展到 sizeof (void*),后面是一个。

原作者:
...