首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >'\0‘和NULL可以互换使用吗?

'\0‘和NULL可以互换使用吗?
EN

Stack Overflow用户
提问于 2016-11-03 14:23:49
回答 6查看 6.4K关注 0票数 56

0通常用于指针上下文中,并通过多个标准库(如<iostream>)中的宏定义为整数NULL。'\0'是空字符,是8位零。顺便说一句,8位0相当于整数0

在某些情况下,尽管它被认为是可怕的风格,但这两种风格可以互换:

代码语言:javascript
复制
int *p='\0';
if (p==NULL) //evaluates to true
    cout << "equal\n";

代码语言:javascript
复制
char a=NULL;
char b='\0';
if (a==b) //evaluates to true
    cout << "equal again\n";

因此,已经有许多类似的问题;例如,这个问题的最高答案(What is the difference between NULL, '\0' and 0)说“它们实际上不是一回事”。

谁能提供一个NULL\0不能互换的例子(最好是一个实际的应用程序,而不是一个病态的案例)?

EN

回答 6

Stack Overflow用户

发布于 2016-11-03 15:01:44

谁能提供一个空值和\0不能互换的例子?

NULL'\0'之间的差异可能会影响重载解析。

示例(check it on Coliru):

代码语言:javascript
复制
#include <iostream>

// The overloaded function under question can be a constructor or 
// an overloaded operator, which would make this example less silly
void foo(char)   { std::cout << "foo(char)"  << std::endl; }
void foo(int)    { std::cout << "foo(int)"   << std::endl; }
void foo(long)   { std::cout << "foo(long)"  << std::endl; }
void foo(void*)  { std::cout << "foo(void*)" << std::endl; }

int main()
{
    foo('\0'); // this will definitely call foo(char)
    foo(NULL); // this, most probably, will not call foo(char)
}

请注意,Coliru使用的gcc编译器将NULL定义为0L,这在本例中意味着foo(NULL)解析为foo(long)而不是foo(void*)This answer详细讨论了这一方面。

票数 54
EN

Stack Overflow用户

发布于 2016-11-03 14:41:55

请不要这样做。这是一种反模式,实际上是错误的。NULL表示空指针,'\0'是空字符。它们在逻辑上是不同的东西。

我想我从来没有见过这样的情况:

代码语言:javascript
复制
int* pVal='\0';

但这是相当普遍的:

代码语言:javascript
复制
char a=NULL;

但这不是一种好的形式。它降低了代码的可移植性,在我看来也降低了可读性。它还可能在C/C++混合环境中引起问题。

它依赖于关于任何特定实现如何定义NULL的假设。例如,某些实现使用简单的

代码语言:javascript
复制
#define NULL 0

其他人可能会使用:

代码语言:javascript
复制
#define NULL ((void*) 0)

我见过其他人定义为整数,以及各种奇怪的处理方式。

在我看来,NULL应该仅用于指示无效地址。如果需要空字符,请使用'\0'。或者将其定义为NULLCHR。但这并不是那么干净。

这将使您的代码更可移植-如果您更改编译器/环境/compiler设置,您将不会收到有关类型等的警告。这在C或C/C++混合环境中可能更重要。

以下是可能出现的警告示例:请考虑以下代码:

代码语言:javascript
复制
#define NULL 0
char str[8];
str[0]=NULL;

这相当于:

代码语言:javascript
复制
#define NULL 0
char str[8];
str[0]=0;

我们将一个整数值赋值给char。这可能会导致编译器警告,如果这种情况出现的次数足够多,很快您就看不到任何重要的警告。对我来说,这才是真正的问题所在。在代码中包含警告有两个副作用:

  1. 给了足够多的警告,你不会发现新的警告。
  2. It给出了警告是可以接受的信号。

在这两种情况下,实际的bug都可能会漏掉,如果我们费心去读取警告(或者打开-Werror ),编译器就会捕捉到这些bug。

票数 8
EN

Stack Overflow用户

发布于 2016-11-03 14:53:23

是的,在解析重载函数时,它们可能表现出不同的行为。

func('\0')调用func(char)

func(NULL)调用func(integer_type)

您可以通过使用nullptr来消除混淆,它始终是一个指针类型,在赋值/比较值或函数重载解析时不会显示任何歧义。

代码语言:javascript
复制
char a = nullptr; //error : cannot convert 'std::nullptr_t' to 'char' in initialization
int x = nullptr;  //error : nullptr is a pointer not an integer

请注意,它仍然与NULL兼容:

代码语言:javascript
复制
int *p=nullptr;
if (p==NULL) //evaluates to true

摘自《C++编程入门》第四版:

在较早的代码中,通常使用0或NULL来代替

(§7.2.2)。但是,使用nullptr消除了整数(如0或NULL)和指针(如nullptr)之间的潜在混淆。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40395066

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档