我正在阅读书Cracking the Coding interview(问题1)中的问题解决方案。目标是在C中实现一个反转空终止字符串的函数void revers(char* str)
。
解决方案代码如下所示:
void reverse(char *str)
{
char* end=str;
char tmp;
if(str)
{
while(*end)
{
end++;
}
end--;
//code to reverse
}
}
在这里,str
包含一个地址吗?如果if(str)
为false
,str
只评估为0
,对吗?
所以我要说的是,str
是否有可能包含地址0x0000
,从而评估if(str)
到false
?
答案 0 :(得分:13)
str
确实包含一个地址(它是指向char
的指针),如果if(str)
等于null,str
将评估为false 指针
请注意,标准不要求空指针引用地址0
;但是,标准要求在指针上下文中使用的{em>文字值时,必须由编译器将其解释为空指针的地址 - 无论可能是什么。
这意味着保证测试0
始终与if(p == 0)
相同。此外,条件if(p == NULL)
保证始终与if(p)
相同。
结论:你的代码总是会检测到一个空指针,但是在技术上与指向零地址的指针不同(即使在实践中你会发现它通常是)
答案 1 :(得分:5)
if(str)
等同于
if(str != NULL)
或
if(str != 0)
此测试不是测试str
是否具有0
的地址,而是测试str
是否为空指针。
请注意,空指针不必具有地址0
,标准只能确保空指针不等于任何其他非空指针。
C11 6.3.2.3 指针
一个整数常量表达式,其值为0,或者这样的表达式强制转换为类型 void *,被称为空指针常量.66)如果将空指针常量转换为a 指针类型,结果指针,称为空指针,保证比较不等于指向任何对象或函数的指针。
答案 2 :(得分:3)
理论上0x0指针是有效的,但是现在所有编译器都不会给你虚拟地址0,因为它被保留来表示空指针(指向什么都没有)。
某些内核可能仍在使用它,但除非你在非常罕见的内核中编写非常低级别的内容,否则可以假设0x0没有指向任何内存。
为指针未指向任何内容的值创建了NULL常量。现在NULL始终为0。
答案 3 :(得分:2)
除非你将NULL
指针传递给函数,否则没有这样的机会。
在C中,除非在C99中引入,否则没有布尔类型。无论其实际类型如何,任何逻辑运算(包括条件)都会将值检查为零。
答案 4 :(得分:2)
所以我所说的是,str是否有可能包含地址0x0000,从而评估if(str)是否为假?
是的,如果您使用空指针调用reverse()
,它将评估为false。
如果发生使用空指针调用reverse()
,则将其用作安全网,以便在实际反转字符串时代码不会访问无效内存。
答案 5 :(得分:1)
如果你问我应该测试在我的函数中传递NULL指针的人,那么答案是肯定的。
答案 6 :(得分:1)
是的,如果str
是任何为0x000
保留地址null pointer
的架构上的NULL指针,则可能。
答案 7 :(得分:1)
if(str)
以检查str是否已分配内存。最佳做法是在声明时初始化指向NULL
的指针。
以上等于
if(str != NULL)
{
}
答案 8 :(得分:1)
这里,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);
另见这些相关问题:
答案 9 :(得分:1)
声明
if (str)
相当于
if (str != 0)
又由编译器解释为
if (str != null-pointer-value-for-char-pointer-type)
即。它与“地址零”无关。编译器需要识别指针上下文,并与类型char *
的依赖于实现的空指针值进行比较。后者将通过依赖于实现的地址值进行物理表示,不一定是零地址。