在C中,指针的地址可以是0吗?

我正在阅读Cracking the Coding访谈 (Q 1.2)一书中的问题解决方案。 目标是在C中实现一个反转空终止字符串的函数void revers(char* str)

解决方案代码如下所示:

 void reverse(char *str) { char* end=str; char tmp; if(str) { while(*end) { end++; } end--; //code to reverse } } 

这里, str包含一个地址吧? 如果str0if(str)只会评估为false ,对吗?

所以我所说的是, str是否有可能包含地址0x0000 ,从而评估if(str)false

str确实包含一个地址(它是一个指向char的指针), if(str) str等于空指针if(str)将计算为false。

注意,标准不要求空指针引用地址0 ; 但是,标准要求在指针上下文中使用的字面值 0必须由编译器解释为空指针的地址 – 无论可能是什么。

这意味着测试if(p == 0)保证始终与if(p == NULL) 。 此外,条件if(p)保证始终与if(p != 0)

结论:您的代码将始终检测到空指针, 但这在技​​术上与指向零地址的指针不同(即使在实践中您会发现它通常是)。

 if(str) 

相当于

 if(str != NULL) 

要么

 if(str != 0) 

此测试不是测试str是否具有地址0 ,而是测试str是否为空指针。

请注意,空指针不必具有地址0 ,标准仅确保空指针不等于任何其他非空指针。

C11 6.3.2.3 指针

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

理论上0x0指针是有效的,但是现在所有编译器都不会给你虚拟地址0,因为它被保留来表示空指针(指向什么都没有)。

有些内核可能仍在使用它,但除非你在非常罕见的内核中编写非常低级别的内容,否则你可以假设0x0没有指向任何内存。

为指针未指向任何内容的值创建了NULL常量。 现在NULL始终为0。

所以我所说的是,str是否有可能包含地址0x0000,从而评估if(str)为false?

是的,有:如果您使用空指针调用reverse() ,它将评估为false。

这用作安全网,如果发生使用空指针调用reverse()则在实际反转字符串时代码不会访问无效内存。

除非您将NULL指针传递给函数, 否则没有这样的机会。

在C中,除非在C99中引入,否则没有布尔类型。 无论其实际类型如何,任何逻辑运算(包括条件)都会将值检查为零。

如果你问我应该测试在我的函数中传递NULL指针的人,那么答案是肯定的。

是的,如果str是任何为null pointer保留地址0x000架构上的NULL指针,则是可能的。

if(str)以检查str是否已分配内存。 最佳做法是在声明时初始化指向NULL的指针。

以上等于

 if(str != NULL) { } 

这里,str包含一个地址吧?

是。 这是一个char * 。 它的值代表char的地址。

如果str为0,那么(str)只会评估为false,对吗?

是。

str是否有可能包含地址0x0000,从而评估if(str)为false?

这是完全可能的。 只需使用此值调用该函数即可。

 char * myCharPointer = 0; reverse(myCharPointer); 

不过,我从不使用这种风格。 我更喜欢使用NULL,这与C标准保证是等价的。 我更喜欢NULL,因为它更具表现力,它有助于将普通整数值与地址分开。

 char * myCharPointer = NULL; reverse(myCharPointer); 

另见这些相关问题:

  • C:与NULL的比较
  • C中的NULL是否需要/定义为零? 。

该声明

 if (str) 

相当于

 if (str != 0) 

而编译器则将其解释为

 if (str != null-pointer-value-for-char-pointer-type) 

即它与“地址零”无关。 编译器需要识别指针上下文并执行与char *类型的依赖于实现的空指针值的比较。 后者将在物理上由依赖于实现的地址值表示,不一定是零地址。