C语言 我可以信任(uintptr_t)NULL等于零吗?



我知道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_tintptr_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()的缓冲区内容。

相关内容

  • 没有找到相关文章

最新更新