在 C 的 char* 字符串中使用 NULL
Using NULL with C's char* strings
众所周知,C 语言中的字符串以 null 结尾。这是否意味着根据标准使用 NULL 常量作为终止符是合法的?还是字符串的 NULL 指针和空终止符的名称相似只是巧合?
考虑代码:
char str1[] = "abc";
char str2[] = "abc";
str1[3] = NULL;
str2[3] = '[=10=]';
这里,我们把str1
的结束符改成NULL。这是合法且格式正确的 C 代码并且 str1
遵守 C 对空终止字符串的定义吗?在 C++ 的情况下会一样吗?
在实践中,我一直在我的字符串代码中使用 NULL 而不是 '\0' 并且一切正常 - 但这种做法 100% 合法吗?
编辑:我知道这是非常糟糕的风格并且不认可它,现在理解 0、NULL 和 '\0' 之间的区别(如重复 What is the difference between NULL, '[=13=]' and 0)。我仍然很好奇这段代码的合法性 - 并且这里的声音似乎是混合的 - 在我看来,副本并没有给出权威的答案。
不,我认为这不完全合法。
NULL
指定为:
- 一个整型常量表达式,值为
0
- 一个整数常量表达式,其值
0
转换为类型 void*
在使用第一种格式的实现中,将其用作字符串终止符即可。
但在使用第二种格式的实现中,它不能保证有效。您正在将指针类型转换为整数类型,其结果取决于实现。它恰好可以在常见的实现中做你想做的事,但没有什么需要它。
如果您有第二种实施方式,您可能会收到如下警告:
warning: incompatible pointer to integer conversion assigning to 'char' from 'void *' [-Wint-conversion]
如果要使用宏,可以定义:
#define NUL '[=10=]'
然后使用 NUL
而不是 NULL
。这与 ASCII 空字符的正式名称匹配。
Does that mean that according to the standard it is legal to use the NULL constant as the terminator? (OP)
str1[3] = NULL;
。进一步:它 always 是否正确地导致 character 数组形成 string 而无需担心?
首先,它看起来不对。类似于 int z = 0.0;
。是的,它是合法的、定义明确的代码,但不必要地引起了对自身的注意。
In practice, I have always used NULL
instead of '[=15=]'
(OP)
我怀疑您会找到任何现代风格指南或编码员小组认可它。 NULL
最好保留给指针上下文。1
这是 2 个常见且易于理解的替代方法。
str1[3] = '[=11=]';
str1[3] = 0;
strings in C are null-terminated (OP)
C 规范始终使用 空字符,而不仅仅是 空。
The macros are NULL
which expands to an implementation-defined null pointer constant; and ... C11 §7.19 3
好的,现在什么是空指针常量?
An integer constant expression with the value 0, or such an expression cast to type
void *
, is called a null pointer constant. §6.3.2.3 5
如果空指针常量是一个void*
那么我们有类似
的东西
str1[3] = (void*) 0;
上面可以警告将指针转换为 char
。最好避免这种情况。
Will it be the same in case of C++? (OP)
是的,上述适用。 (另外:str1[3] = 0
可能会发出警告。)此外,NULL
不如 nullptr
受欢迎。所以 NULL
在任何情况下都很少是在 C++ 中使用的最佳选择。
1注意: 报告与 1995 Turbo C 4.5 中的 OP 相匹配的样式
最重要的是,在 C/C++ 中,NULL
用于 pointers,与 null 不同character,尽管两者都被定义为零。您可能会使用 NULL
作为空字符并根据上下文和平台摆脱它,但为了正确起见,请使用 '[=12=]'
。这在两个标准中都有描述:
C 指定宏 NULL
定义为 <stddef.h>
中的宏,其中 "expands to an implementation-defined null pointer constant"(第 7.17.3 节),它本身定义为 "an integer constant expression with the value 0, or such an expression cast to type void *
"(第 6.3.2.3.3 节)。
空字符 在第 5.2.1.2 节中定义:"A byte with all bits set to 0, called the null character, shall exist in the basic execution character set; it is used to terminate a character string." 同一节解释了 [=16=]
将是此空字符的表示。
C++ 也有同样的区别。来自 C++ 标准的第 4.10.1 节:"A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type std::nullptr_t
." 在第 2.3.3 节中,它描述为 "null character (respectively, null wide character), whose value is 0"。 C.5.2 节进一步确认 C++ 将 NULL
作为从 C 标准库导入的标准宏。
众所周知,C 语言中的字符串以 null 结尾。这是否意味着根据标准使用 NULL 常量作为终止符是合法的?还是字符串的 NULL 指针和空终止符的名称相似只是巧合?
考虑代码:
char str1[] = "abc";
char str2[] = "abc";
str1[3] = NULL;
str2[3] = '[=10=]';
这里,我们把str1
的结束符改成NULL。这是合法且格式正确的 C 代码并且 str1
遵守 C 对空终止字符串的定义吗?在 C++ 的情况下会一样吗?
在实践中,我一直在我的字符串代码中使用 NULL 而不是 '\0' 并且一切正常 - 但这种做法 100% 合法吗?
编辑:我知道这是非常糟糕的风格并且不认可它,现在理解 0、NULL 和 '\0' 之间的区别(如重复 What is the difference between NULL, '[=13=]' and 0)。我仍然很好奇这段代码的合法性 - 并且这里的声音似乎是混合的 - 在我看来,副本并没有给出权威的答案。
不,我认为这不完全合法。
NULL
指定为:
- 一个整型常量表达式,值为
0
- 一个整数常量表达式,其值
0
转换为类型void*
在使用第一种格式的实现中,将其用作字符串终止符即可。
但在使用第二种格式的实现中,它不能保证有效。您正在将指针类型转换为整数类型,其结果取决于实现。它恰好可以在常见的实现中做你想做的事,但没有什么需要它。
如果您有第二种实施方式,您可能会收到如下警告:
warning: incompatible pointer to integer conversion assigning to 'char' from 'void *' [-Wint-conversion]
如果要使用宏,可以定义:
#define NUL '[=10=]'
然后使用 NUL
而不是 NULL
。这与 ASCII 空字符的正式名称匹配。
Does that mean that according to the standard it is legal to use the NULL constant as the terminator? (OP)
str1[3] = NULL;
首先,它看起来不对。类似于 int z = 0.0;
。是的,它是合法的、定义明确的代码,但不必要地引起了对自身的注意。
In practice, I have always used
NULL
instead of'[=15=]'
(OP)
我怀疑您会找到任何现代风格指南或编码员小组认可它。 NULL
最好保留给指针上下文。1
这是 2 个常见且易于理解的替代方法。
str1[3] = '[=11=]';
str1[3] = 0;
strings in C are null-terminated (OP)
C 规范始终使用 空字符,而不仅仅是 空。
The macros are
NULL
which expands to an implementation-defined null pointer constant; and ... C11 §7.19 3
好的,现在什么是空指针常量?
An integer constant expression with the value 0, or such an expression cast to type
void *
, is called a null pointer constant. §6.3.2.3 5
如果空指针常量是一个void*
那么我们有类似
str1[3] = (void*) 0;
上面可以警告将指针转换为 char
。最好避免这种情况。
Will it be the same in case of C++? (OP)
是的,上述适用。 (另外:str1[3] = 0
可能会发出警告。)此外,NULL
不如 nullptr
受欢迎。所以 NULL
在任何情况下都很少是在 C++ 中使用的最佳选择。
1注意:
最重要的是,在 C/C++ 中,NULL
用于 pointers,与 null 不同character,尽管两者都被定义为零。您可能会使用 NULL
作为空字符并根据上下文和平台摆脱它,但为了正确起见,请使用 '[=12=]'
。这在两个标准中都有描述:
C 指定宏
NULL
定义为<stddef.h>
中的宏,其中 "expands to an implementation-defined null pointer constant"(第 7.17.3 节),它本身定义为 "an integer constant expression with the value 0, or such an expression cast to typevoid *
"(第 6.3.2.3.3 节)。空字符 在第 5.2.1.2 节中定义:"A byte with all bits set to 0, called the null character, shall exist in the basic execution character set; it is used to terminate a character string." 同一节解释了
[=16=]
将是此空字符的表示。C++ 也有同样的区别。来自 C++ 标准的第 4.10.1 节:"A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type
std::nullptr_t
." 在第 2.3.3 节中,它描述为 "null character (respectively, null wide character), whose value is 0"。 C.5.2 节进一步确认 C++ 将NULL
作为从 C 标准库导入的标准宏。