什么是字符串以及如何使用它们?

问题描述 投票:0回答:1

此帖子旨在作为规范的常见问题解答,用于以下问题:海报者在声明字符串时未能为空终止符分配空间。


有人告诉我,C语言中的字符串只是字符数组。因此,我尝试了以下操作,但它给出了奇怪的结果,例如垃圾输出或程序崩溃:

#include <stdio.h>

int main (void)
{
  char str [5] = "hello";
  puts(str);
}

为什么不起作用?

它以gcc -std=c17 -pedantic-errors -Wall -Wextra干净地编译。

c string c-strings string-literals nul
1个回答
1
投票

C字符串是一个以null终止符结尾的字符数组。

所有字符都有符号表值。空终止符是符号值0(零)。它用于标记字符串的结尾。这是必需的,因为字符串的大小不会存储在任何地方。

因此,每次为字符串分配空间时,必须为空终止符包含足够的空间。您的示例不执行此操作,它仅为"hello"的5个字符分配空间。正确的代码应为:

char str[6] = "hello";

或等效地,您可以编写5个字符加1个空终止符的自文档代码:

char str[5+1] = "hello";

在运行时为字符串动态分配内存时,您还需要为空终止符分配空间:

char input[n] = ... ;
...
char* str = malloc(strlen(input) + 1);

如果您没有在字符串的末尾附加一个空终止符,则期望该字符串的库函数将无法正常工作,并且您会收到“未定义行为”的错误,例如垃圾输出或程序崩溃。

在C中写空终止符的最常见方法是使用所谓的“八进制转义序列”,如下所示:'\0'。这相当于写0的100%,但是\用作自记录代码,指出零明确表示是空终止符。诸如if(str[i] == '\0')的代码将检查特定字符是否为空终止符。

[请注意,术语空终止符与空指针或NULL宏无关!这可能会令人困惑-名称非常相似,但含义却截然不同。这就是为什么空终止符有时被称为带有一个L的NUL,不要与NULL或空指针混淆的原因。

您代码中的"hello"被称为字符串文字。这将被视为只读字符串。 ""语法意味着编译器将自动在字符串文字的末尾附加一个空终止符。因此,如果您打印出sizeof("hello"),则将得到6,而不是5,因为您将获得包含空终止符的数组的大小。


它可以用gcc干净地编译

的确,甚至没有警告。这是由于C语言中的一个细微的细节/缺陷,它允许使用字符串文字初始化字符数组,该字符串文字包含的字符与数组中的空间一样多,然后静默丢弃空终止符(C17 6.7.9 / 15)。由于历史原因,该语言特意表现为这种行为,有关详细信息,请参见Inconsistent gcc diagnostic for string initialization。还请注意,C ++在这里有所不同,并且不允许使用此技巧/缺陷。

© www.soinside.com 2019 - 2024. All rights reserved.