我知道NULL
不需要是全位零模式。但我想知道
uintptr_t x = (uintptr_t)NULL;
printf("%" PRIuPTR, x);
保证打印0
?我怀疑不是,但我只是想确定一下。
或者更切题。我能相信吗?
if( ((uintptr_t)f(x) | (uintptr_t)f(y)) != 0)
假设f
是一个返回指针的函数。我怀疑这段代码严重依赖于NULL
是一个全位零模式。我说的对吗?
我知道这被认为是不好的做法,我自己也不会写这样的东西,但我想知道它是否定义良好。
我在这个回答中偶然发现了这段代码,作者使用了
while ( ( (uintptr_t)fgets(a,100,fp1) | (uintptr_t)fgets (b,100,fp) ) != 0 ) {
printf("%s",a);
printf("%s",b);
}
理论上:没有
在实践中:probably.
在相关标准中,空指针的检查是"特殊的"。从某种意义上说,它们不是与值0的数值比较,因此在理论上,某些实现或平台可以为空指针赋不同的值。
不,没有这样的保证。根据7.19的规定,NULL是宏定义,扩展为实现定义的空指针常量。
但是如果p
不是NULL(其中p
是指针),则if(p)
保证为真。
因此,如果指针为NULL,printf("%dn", !!p)
保证打印0
,如果不是1
,
while ( fgets(a,100,fp1) || fgets (b,100,fp))
或
while ( fgets(a,100,fp1) != NULL || fgets (b,100,fp) != NULL)
或更变态的方式
while ( ((fgets(a,100,fp1) != NULL) | (fgets (b,100,fp) != NULL)) != 0)
while ( (!!fgets(a,100,fp1) | !!fgets (b,100,fp)) != 0)
但我想知道(下面)是否保证打印0?
uintptr_t x = (uintptr_t)NULL;
printf("%" PRIuPTR, x);
。它通常这样做,但不是指定这样做。
(uintptr)NULL
不是指定的转换为0。不过,这样做是相当普遍的做法。NULL
可以是整型或指针型。NULL
可以是一个不转换为整数0的指针。即使NULL
是一个全0位模式,它仍然没有被指定转换为整数0。uintptr_t
和intptr_t
为可选类型。它们通常存在,但不是必需的。考虑一个void *
大于64位的系统,但最宽的整数类型是64位。
我能相信这个吗?
if( ((uintptr_t)f(x) | (uintptr_t)f(y)) != 0)
它通常会工作,但它不是高度可移植性。
选择:
if( !!f(x) | !!f(y))
我怀疑这段代码严重依赖于NULL是一个全位零模式。我说的对吗?
。它依赖于(uintptr_t)NULL
转换为0。
除了转换问题之外,我发现下面的代码中有一个弱点,即由于输入错误或文件结束而导致fgets()
返回NULL
。
如果fgets(a,100,fp1)
由于文件结束而返回NULL
,缓冲区也不一定是_null字符终止(它也可能是过时的)-导致更多的UB或旧输出在打印中。
如果发生输入错误(流方向错误,文件未打开等),则a[]
不确定,导致使用printf("%s",a);
进行UB
while ( ( (uintptr_t)fgets(a,100,fp1) | (uintptr_t)fgets (b,100,fp) ) != 0 ) {
printf("%s",a);
printf("%s",b);
}
当函数返回NULL
时,最好不要读取fgets()
的缓冲区内容。