这可以被认为是这个问题的扩展(我只对C感兴趣,但添加C++来完成扩展)
6.3.2.3.3中的C11标准说:
值为0的整型常量表达式或此类表达式转换为类型
void *称为空指针常量.
我个人对此的看法是0并且(void *)0表示空指针,其整数值实际上可能不是0,但是不包括0强制转换为任何其他类型.
但是,标准然后继续:
如果将空指针常量转换为指针类型,则生成的指针称为空指针,...
它包含(int *)0为空指针,因为强制转换是一种显式转换(C11,6.3),它在转换方法下列出.
然而,令我惊讶的是以下短语
...或者这样的表达式转换为
void *...
有了上面的语义,这句话似乎完全没用.问题是,这句话完全没用吗?如果没有,它有什么影响?因此,是否(int *)0为空指针?
另一个可以帮助讨论的问题如下.被(long long)123视为"123转换为long long",或"123与类型long long".换句话说,有没有转换(long long)123?如果没有,则上面的第二个引用不包括(int *)0为空指针.
我一直在使用C语言hack来检测使用宏的整数常量表达式 - Martin Uecker的Idea. https://lkml.org/lkml/2018/3/20/805
当我开始使用代码时,我通过交换三元运算符的表达式找到了一种奇怪的行为.
见下面的代码,
#include <stdio.h>
#include <stdlib.h>
// https://lkml.org/lkml/2018/3/20/805
#define ICE_P(x) (sizeof(int) == sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1)))
//Why is this working?
#define ICE_P2(x) (sizeof(int) == sizeof(*(1 ? (int*)1 : ((void*)((x) * 0l)))))
int main() {
int a = 5;
int b = ICE_P(a);
int c = ICE_P2(a);
int d = ICE_P(5);
int e = ICE_P2(5);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
ICE_P(x)完美地工作,如上面的链接所述.但是,当我互换三元运算符的左右表达式时,程序仍然表现得与我没想到的相同.
当调用ICE_P2时,1 ? (int*)1 : ((void*)((x) * 0l))将对其进行评估.