C 如何将字符数组用作字符串?
我知道C中的字符串只是字符数组。因此,我尝试了以下代码,但它给出了奇怪的结果,例如垃圾输出或程序崩溃:C 如何将字符数组用作字符串?,c,string,c-strings,string-literals,nul,C,String,C Strings,String Literals,Nul,我知道C中的字符串只是字符数组。因此,我尝试了以下代码,但它给出了奇怪的结果,例如垃圾输出或程序崩溃: #include <stdio.h> int main (void) { char str [5] = "hello"; puts(str); } #包括 内部主(空) { char str[5]=“你好”; put(str); } 为什么这样不行 它使用gcc-std=c17-pedanticerrors-Wall-Wextra干净地编译 注意:这篇文章旨在作为一
#include <stdio.h>
int main (void)
{
char str [5] = "hello";
puts(str);
}
#包括
内部主(空)
{
char str[5]=“你好”;
put(str);
}
为什么这样不行
它使用gcc-std=c17-pedanticerrors-Wall-Wextra
干净地编译
注意:这篇文章旨在作为一个标准的常见问题解答,解答由于声明字符串时未能为NUL终止符分配空间而导致的问题。C字符串是以空终止符结尾的字符数组。 所有字符都有一个符号表值。空终止符是符号值
0
(零)。它用于标记字符串的结尾。这是必要的,因为字符串的大小不存储在任何位置
因此,每次为字符串分配空间时,必须为空终止符字符包含足够的空间。您的示例没有这样做,它只为“hello”
的5个字符分配空间。正确的代码应为:
char str[6] = "hello";
或者,您可以编写5个字符加1个空终止符的自文档代码:
char str[5+1] = "hello";
char input[n] = ... ;
...
char* str = malloc(strlen(input) + 1);
但您也可以使用它,让编译器进行计数并选择大小:
char str[] = "hello"; // Will allocate 6 bytes automatically
在运行时为字符串动态分配内存时,还需要为空终止符分配空间:
char str[5+1] = "hello";
char input[n] = ... ;
...
char* str = malloc(strlen(input) + 1);
如果不在字符串末尾附加null终止符,则期望字符串的库函数将无法正常工作,并且会出现“未定义的行为”错误,例如垃圾输出或程序崩溃
在C中编写空终止符字符最常见的方法是使用所谓的“八进制转义序列”,如下所示:'\0'
。这100%等同于写入0
,但\
用作自文档代码,以声明零明确表示为空终止符。诸如if(str[i]='\0')
之类的代码将检查特定字符是否为空终止符
请注意,术语null终止符与null指针或null
宏无关!这可能会让人困惑——名称非常相似,但含义却非常不同。这就是为什么空终止符有时被称为带有一个L的NUL
,不要与null
或空指针混淆。有关更多详细信息,请参见的答案
代码中的“hello”称为字符串文字。这将被视为只读字符串。”
语法意味着编译器将自动在字符串文本的末尾附加一个空终止符。因此,如果您打印出sizeof(“hello”)
,您将得到6,而不是5,因为您得到的是包含空终止符的数组大小
它使用gcc干净地编译 事实上,甚至连警告都没有。这是因为C语言中存在一个微妙的细节/缺陷,该缺陷允许使用字符串文字对字符数组进行初始化,该字符串文字包含的字符数与数组中的空间完全相同,然后静默地丢弃空终止符(C17 6.7.9/15)。出于历史原因,该语言故意表现为这样,有关详细信息,请参阅。还要注意,C++在这里是不同的,不允许使用这个技巧/缺陷。 < P>从C标准(7.1.1术语定义) 1字符串是以和结尾的连续字符序列 包括第一个空字符。术语多字节字符串 有时用来强调给予的特殊处理 字符串或中包含的多字节字符,以避免混淆 用一根宽大的绳子。指向字符串的指针是指向其首字母的指针 (最低地址)字符。字符串的长度是 空字符前面的字节和字符串的值是 所包含字符的值的顺序(按顺序) 在本声明中
char str [5] = "hello";
字符串literal“hello”
的内部表示形式如下
{ 'h', 'e', 'l', 'l', 'o', '\0' }
所以它有6个字符,包括终止零。它的元素用于初始化字符数组str
,该数组只为5个字符保留空间
C标准(与C++标准相反)允许在字符串文字的终止零点不作为初始化器时初始化字符数组。 但是,因此字符数组
str
不包含字符串
如果希望数组包含字符串,可以编写
char str [6] = "hello";
或者只是
char str [] = "hello";
在最后一种情况下,字符数组的大小由等于6的字符串文本的初始值设定项的数量确定。是否可以将所有字符串视为字符数组(是),是否可以将所有字符数组视为字符串(否)
为什么不呢?为什么这很重要?
除了解释字符串长度不作为字符串的一部分存储在任何地方以及对定义字符串的标准的引用之外,另一方面是“C库函数如何处理字符串?”
虽然字符数组可以包含相同的字符,但它只是一个字符数组,除非最后一个字符后跟nul终止字符。nul终止字符允许将字符数组视为(处理为)字符串
C中所有希望字符串作为参数的函数都希望字符序列以nul结尾。为什么?
这与所有字符串函数的工作方式有关。由于长度不包括在数组中,字符串函数在数组中向前扫描,直到找到nul字符(例如'\0'
--相当于十进制0
)。看见无论您是否使用strcpy