将“NULL”分配给布尔数据类型是否可以接受?
13 回答
从理论上讲,是的。但这是一件可怕的事情。
NULL
是一个空指针常量,它被分配给一个指针以使其不指向任何内容。
...
ptr = NULL; // now it points to no object anymore
...
// or ptr == 0
if(ptr == NULL) {
...
}
如果您对任何情况感兴趣,这里是对标准的参考。首先,空指针常量是 ( 4.10/1
)
空指针常量是整数类型的整数常量表达式 (5.19) 右值,其计算结果为零。
那么,如果我们将空指针常量转换为 会发生什么bool
?解释4.12/1
如下:
算术、枚举、指针或指向成员类型的指针的右值可以转换为 bool 类型的右值。将零值、空指针值或空成员指针值转换为 false;一个
(当它谈到rvalue
它时,它本质上是一个简单的值,而不是那种类型的变量)。
现在,那实际上是什么NULL
?读取18.1/4
(请注意,在 C 中,空指针常量的定义不同。这可能是它显式引用 C++ 的原因)
宏 NULL 是本国际标准中实现定义的 C++ 空指针常量
该组合的重要部分是“ A zero value ... is converted to false
”部分。对 bool 变量的赋值NULL
将尝试转换NULL
为布尔值。正如上面的段落所说,这样的转换是存在的并且是可以做到的。
null pointer
另一个需要理解的关于空指针的重要事情是 a和 a之间的区别null pointer constant
。正如我们刚刚读到的,空指针常量是一些零的整数值。但是, anull pointer
及其值 anull pointer value
是指针,它们的类型是指针类型。以下具有 int 类型并且是一个空指针常量
#define NULL ('n'-'n') // looks suspicious, but conforms
因为它是一个整数常量表达式(本质上是一个在编译时已知的整数值),其值为零。下面是一个空指针值
(void*)NULL
但它不是空指针常量。但无论如何,空指针值也被转换为布尔值,正如上面的引用所说:“ A .. null pointer value .. is converted to false
”。所以你们都很好。
从我的 n2798 副本中:
18.1 类型
3 宏 NULL 是本国际标准 (4.10) 中实现定义的 C++ 空指针常量
和
4.12 布尔转换 [conv.bool]
1 算术右值、无作用域枚举、指针或指向成员类型的指针可以转换为 bool 类型的右值。将零值、空指针值或空成员指针值转换为 false;任何其他值都将转换为 true。std::nullptr_t 类型的右值可以转换为 bool 类型的右值;结果值为假。
所以,是的,你似乎可以做到这一点。
编译器不会拒绝它,因为 NULL 通常是 0 的预处理器 #define 并且 0 可以转换为 NULL 和 false 的指针表示。
我的观点是,这会降低代码的可读性,但如果您愿意,请确定。NULL 毕竟只是 0。
一般来说,它会起作用,因为指针被设计为可在布尔上下文中使用:
int *i = NULL;
if (i) // This is a pretty acceptable use of pointer conversions to bool
{
// never runs.
}
或者
int *i = NULL;
...
bool b = i; // Maybe not so terrible, but you're better off just assigning to a pointer.
这是故意完成的(请参阅标准参考的 dirkgently 答案)以允许这种用法。如果您使用此语法:
bool i = NULL; // Don't do this
bool i2 = 0; // better
bool i3 = false; // Best
那么你可能是在误导,但它会以一种可移植的、可预测的方式工作。要么 NULL 被定义为 0,在这种情况下,你将得到一个 false 值,或者如果 NULL 确实是一个 NULL 指针,那么它也将评估为 false。
即使这在技术上是可行的,我也会避免它。似乎如果您需要一个空值,您应该建模为与布尔值不同的数据类型。
如果您要使用布尔值,请正确设计您的模块和代码以按设计使用它:具有两个潜在值,而不是三个。如果您需要三个,请使用另一种数据类型,例如 int 或 string,并让这三个值中的每一个都表示某种含义(在字符串中,空字符串表示空值)。
不,您应该使用技术术语 - “找不到文件”
编辑:
参考:http ://thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx
正确答案是否定的。
我认为您正在尝试做的是使用 NULL 来表示“未初始化”或“不知道”。这通常适用于数据库,但并不总是适用于代码,因为 NULL 的定义因预处理器和语言而异。
根据定义,布尔值是两态值。尝试将它们用作三态值是错误的。充其量这是一个肮脏的 hack,会在未来给其他开发人员造成混乱,最坏的情况是它是一个破坏性错误,一旦你的构建链中的任何内容发生变化,它就会在背后咬你。
我不确定你为什么要这样做。如果您尝试初始化它,请使用 0。正如 MSN 所说,您的编译器不会拒绝它。也许您应该首先解释为什么要将 bool 设置为 NULL ?
你可以这样做,但我不明白这一点。假设你有:
void* p = NULL;
bool b = p;
为什么不直接写成:
void* p = NULL;
bool b = (p != NULL);
它更清晰,任何体面的编译器都会生成相同的代码。
NULL
在 C++ 中是指Empty pointer
或称它为\0
“零指针”、“无”等。
但所有这些:它是一个数字0
-“零”。
boolfalse
的 0 表示 - 所以可以接受。
但有时设置bool
可能NULL
不是你想要的:如果你想要一个特殊的 bool 包含值true
//称为false
.undefine
3-state Boolean
只要 false 仍然是 0 并且 NULL 仍然定义为 0 是的,但是这在未来可能会改变。我会说这是不好的做法,因为你混淆了概念并且失去了清晰度。
由于 NULL 通常不是 0 而是(void*)0
,它不像在 C++ 中那样工作,因为在这种情况下 NULL 是一个指针。你必须做一个明确的演员:reinterpret_cast<bool>(NULL)
,不,这不干净。你应该使用true
/1
和false
/0
根据定义,NULL 不是 0。我不知道,但可能有一些编译器对 NULL 使用非零值,或者甚至可能在其地址后面的 thunk 中设置一些标志。您的代码被移植到一个只是您的运气。我必须修复由此产生的错误只是我的运气。
所以我说,“不,这是不可接受的。”