【问题标题】:What are the specifics of the definition of a string in C?在 C 中定义字符串的细节是什么?
【发布时间】:2020-06-06 08:43:42
【问题描述】:

我应该为我的一门课回答一个家庭作业问题。具体来说,我应该说 C 中的某些数组是否被视为字符串。根据这篇文章 (https://www.geeksforgeeks.org/strings-in-c-2/),我知道字符串是一个字符数组,末尾带有空终止符。

我的主要挂断是问题的一部分,该问题询问如下所示的数组:

char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };

这显然是一个以空结尾字符结尾的字符数组。但是,它是否仍然被视为字符串,因为它中间还有一个空终止字符?这将如何影响字符串?

编辑: 基于 cmets,我提供了问题的实际措辞:

“以下哪些数组可以被视为“字符串”,以便将它们用作 strcpy()、strncpy()、strcmp()、strncmp() 和类似字符串函数的参数(表示所有适用) ?”

编辑: 我给我的教授发了电子邮件,因为这个问题的措辞似乎含糊不清(正如几个人指出的那样)。如果有人好奇,他告诉我“是的,它是一个字符串。关键是有一个空字符。但这当然会影响任何字符串操作;字符串以空字符结尾。”

【问题讨论】:

  • 您可能会说它是字符串"CS",并附加了一些垃圾字节(在这种情况下,final NUL 字符无关紧要)。但它不是“作为一个整体”的字符串。 -- 尽管如此,将其提供给strcpy 等不会使您的电脑爆炸,因为这些功能只会“看到”"CS" 部分。
  • c1 可以绝对用作strcmp() 的参数。它是否可以用作变异字符串函数的参数取决于未提供的其他因素。
  • c1 的内容是可变的,所以我不明白为什么它不能成为 strcpy 或类似的有效目标参数,除非它不够大以容纳源字符串。这不会使它不是一个字符串,只是不适合给定目的。
  • 总的来说,我同意这个问题措辞含糊。表达式c1 将满足所有标准库的(窄)字符串函数的字符串参数的基本要求,包括所有特别命名的函数,但行为可能不是调用者期望或想要的(甚至忽略可能是未定义的行为)引出)。
  • 请注意,type 不必是char。任何字符类型都可以。

标签: c arrays string null-terminated


【解决方案1】:

c1 大部分 [1] 等价于 &c1[0],它包含一个字符串 "CS"

其中潜伏着第二个字符串"324",从&c1[3] 开始——但只要您以c1 访问c1,字符串"CS" 就是所有函数strcpy() 等.会看到的。


[1]:c1 是一个数组,&c1[0] 是一个指针。

【讨论】:

  • 那么,在strcpy() 命令中使用c1 作为目标字符串是否合适?这个问题是模棱两可的 - 充其量。
  • 当然您可以使用c1 作为strcpy() 的任一参数。从任何意义上来说,它都是一个非常普通的字符串。普通字符串通常在它们的终止符之后包含剩余的垃圾。这个垃圾被硬编码到程序中的事实给人的印象是作者打算以非字符串方式使用c1,但这不是问题的一部分。
  • "c1 等同于&c1[0]" 误导。 c1 是一个数组。 &c1[0] 是一个指针。
【解决方案2】:

如果你想知道 C 中字符串定义的具体细节,请去源码。

From the C90 standard:

7 库

7.1 简介

7.1.1 术语定义
string 是一个连续的字符序列,由第一个空字符终止并包括第一个空字符。指向字符串的“指针”是指向其初始(最低地址)字符的指针。字符串的“长度”是空字符之前的字符数,其“值”是所包含字符的值的顺序,按顺序排列。

(后来的标准没有相关的变化。)

因此,c1 包含两个连续的字符串,“CS”和“324”,但它本身不是字符串。

如果我们将数组传递给函数,它会衰减为指向其第一个元素的指针,因此+c1 指向一个字符串(第一个),这对于任何需要指向字符串的指针的函数来说已经足够了。它不指向字符串“CS\0324”,但这对于您的讲师问题可能已经足够了,这是模棱两可的。

【讨论】:

  • 我认为即使按照这个定义,c1 显然也是字符串“CS”。时期。它可能在终止符之后包含非零字节这一事实是无关紧要的——许多字符串在它们的生命周期中都是这样的。
  • +c1 指向一个字符串,因为c1 以字符串开头。不过,这绝不会使c1 成为字符串。
  • 这是一段内存的地址,其中包含一些以零字节结尾的字符。如果 printf() 与 %s 配合得很好,它会给出一个非常好的数字传递给 strlen(),如果传递给 strcpy() 等会工作。对我来说听起来像一个字符串。
  • 是的,但是这个是两个连续的字符串。不过,这可能算导师的问题,这有点太草率了。
【解决方案3】:

添加到@DevSolar 的答案,我在玩弄给定的字符串后发现的东西,如果是的话:

char c1[] = { 'C', 'S', '\\0', '3', '2', '4', '\\0' };

如果你输出这个字符串,你会得到CS03240,这个字符串的大小是7。据我的理解,\\0是用来表示空字符的(ie \0)。如果你这样做:

printf("\0");

您在输出日志中看不到任何内容,但如果您看到:

printf("\\0");

您会看到 \0,这是意料之中的,因为要输出反斜杠或引号等特殊字符,您需要与它们一起使用 \

让我感到困惑的是输出CS03240,它的大小为7。通常的理解是字符串的大小是其中的字符数加一(对于空字符)。此外,即使是字符串,大小也是 7, char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };.

所以也许可以跟进这个问题,这里发生了什么?

【讨论】:

  • '\\0' 不是 空字符。它是一个多字符常量。它的实现定义值肯定在char 的范围之外。 c1[] 不是 string,因为它缺少 null 字符。 “你输出这个字符串”可能会导致未定义的行为
  • 虽然我查了多字符常量,但我并没有完全理解你。如果 c1[] 不是字符串,因为它末尾没有空字符,那么为什么在 OP 发布的初始情况下大小为 7?
  • char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' }; 的大小为 7,因为它是用 7 个值初始化的。它的 sizestrings 无关。 char c1[] = { 1, 2, 3, 4, 5, 6, 7 }; 仍然会变成 7 号。
  • 至于数组c1 是否包含刺痛?那是一个单独的问题。见also
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-13
  • 2021-10-06
  • 2017-07-30
  • 2012-01-07
  • 2013-07-02
  • 1970-01-01
相关资源
最近更新 更多