在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
包含一个地址吧? 如果str
为0
, if(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 *
类型的依赖于实现的空指针值的比较。 后者将在物理上由依赖于实现的地址值表示,不一定是零地址。