你是如何处理NUL的
How do you deal with NUL?
当我们谈论NULL时,我不时会遇到与其他程序员的通信问题。现在NULL可能是
空指针
NUL字符
某种数据库中的空数据元素。
NUL似乎是最令人困惑的。它是ASCII字符0x00。
我倾向于在代码中使用"\0"来表示它。我所在小组的一些开发人员
倾向于简单地使用0,并让编译器隐式地将其转换为char。
你更喜欢用什么来表示NUL?为什么?
我将' '
用于nul字符,将NULL
用于指针,因为它在这两种情况下都是最清晰的。
BTW,0
和' '
都是C中的int
s,当存储在char
变量中时,其中任何一个都将转换为char
。
我喜欢预定义的NULL宏,因为它保留了语义,而不是数字0的其他用法。
有许多英语单词拼写或口语相似,但含义不同。就像在英语中一样,利用讨论的上下文来引导你达到预期的含义。
- 对于字符串,我总是将空字符表示为"\0"。
- 对于指针,我尝试使用隐式转换为布尔值(if(!myPtr)或if(myPtr))来表示指针无效。
- 如果我需要指针的默认值,它是NULL,例如struct-list_head={0.0,NULL};)。
END_OF_STRING很傻,因为它是一种额外的间接方式,只会让新的读者感到困惑(任何不能立即识别"\0"的人都应该离开键盘)。
还有一件事—我认为在谈论数据建模时,空值和空值之间的区别是非常重要的。在讨论C样式字符串或可为null的数据库字段时尤其如此。有人告诉你"我没有名字"answers"我的名字是"之间有很大的区别
@BKB:
我在他的建议中看到了这一点,但"NULL"使上下文更清楚地表明了它是指针。这就像对浮点值使用"0.0",在处理字符时使用"\0"。(同样,如果在算术上下文中使用char,我更喜欢看到0。)
Bjarne在这个常见问题解答中进一步指出,NULL无论如何都被#定义为0,所以标准代码应该不会有问题。我同意全大写表示法很难看,但我们必须等到0x(nullptr作为关键字可用)。
#define NULL ((void*)0)
这是为了确保NULL被解释为指针类型(在C中)。然而,这可能会在更严格的C++世界中引发问题。例如:
// Example taken from wikibooks.org
std::string * str = NULL; // Can't automatically cast void * to std::string *
void (C::*pmf) () = &C::func;
if (pmf == NULL) {} // Can't automatically cast from void * to pointer to member function.
因此,在当前的C++中,标准的空指针应该用文字0初始化。很明显,因为人们已经习惯了使用NULL定义,我认为很多C++编译器要么默默地忽略这个问题,要么在C++代码中将NULL重新定义为0。例如:
#ifdef __cplusplus
#define NULL (0)
#else
#define NULL ((void*)0)
#endif
C++x0标准现在定义了一个nullptr
关键字来表示空指针。Visual C++2005的CLI/C++编译器在将托管指针设置为null时也使用此关键字。在当前的编译器中,您可以创建一个模板来模拟这个新关键字。
wikibooks.org上有一篇更详细的文章讨论这个问题。
A one-L NUL, it ends a string.
A two-L NULL points to no thing.
And I will bet a golden bull
That there is no three-L NULLL.
(The name of the original author is, alas, lost to the sands of time.)
数据库为NULL,代码为NIL。
虽然总的来说,我建议使用命名常量,但这是一个例外。对我来说,定义:
#define NULL 0
#define END_OF_STRING ' '
与定义一样有意义
#define SEVEN 7
没有。是的,我知道编译器已经定义了NULL,但我从不使用它;对于字符,"\0"。更长并不总是意味着更有表现力。
我很喜欢
#define ASCII_NUL (' ')
我只是偶尔把"\0"误键入"0"。但当我这样做的时候,我发现代码检查很难发现错误,结果很搞笑。所以我不太喜欢"\0",更喜欢ASCII_NUL或0(当然后者在C++中有错误的类型)。显然,我在需要与现有代码或样式指南保持一致的地方使用"\0"。
谷歌C++风格的指南中包含了一些我喜欢的东西和一些我不喜欢的东西,但似乎大部分都是合理的,它更喜欢NULL而不是0作为指针。它指出,NULL可能不能简单地定义为0(或0L),尤其是在sizeof(void*)可能不是sizeof(int)(或sizeof(long int))的实现中。
0和NULL都被指定为整型,当转换为指针类型时,它们都必须产生一个NULL指针值。但它们不一定是相同的积分类型。因此,在某些情况下,使用NULL可能会得到一些有用的警告或错误。
对于通信,我使用NULL。如果我的开发人员不能理解不同数据类型的NULL概念,那么我会担心。
对于实施,它是针对具体情况的。数字为0(浮点为后置固定f),指针为NULL,字符串为0。
不使用二进制0表示NULL的系统越来越难找到。它们还往往存在各种可移植性问题。为什么?因为在这些系统上,memset和calloc都无法正确清除包含指针的结构。
const char END_OF_STRING = ' ';
所以当你说:
str[i] = END_OF_STRING;
或
if (*ptr == END_OF_STRING)
毫无疑问你的意思是什么。
我们使用NULL表示指针,使用NULLCHAR表示字符,使用
#define NULLCHAR ' '
有点相关:Slashdot最近在comp.lang.c
常见问题部分有一篇关于空指针的报道,我觉得很有趣。
- 警告处理为错误这里有什么问题
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 使用流处理接收到的数据
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 基于多个条件处理地图中的所有元素
- 如何用数字处理log(0)
- SSL上的`curl_easy_send`和`curl_asy_recv`:如何处理`CURLE_AGAIN`
- 错误处理.将系统错误代码映射到泛型
- 从文本文件中读取时钟时间和事件时间并进行处理
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 用于矢量处理的多个线程
- 对字符串进行排序时,在c++中处理sort()
- 如何处理linux终端中带有负号(-)的C++中的命令行参数
- 处理除以零会导致<csignal>意外行为
- 如何处理在某些元素中使用 nul char 的 CSV 行
- 你是如何处理NUL的