用C定义字符串的细节是什么?


10

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

我的主要困扰是询问如下数组的问题:

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

显然这是一个字符数组,末尾有一个空终止符。但是,由于它的中间也有一个空终止符,它是否仍被认为是字符串?这将如何影响字符串?

编辑:根据评论,我提供了问题的实际措辞:

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

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


4
您可能会说这是"CS"附加了几字节垃圾的字符串(在这种情况下,最后的 NUL字符无关紧要)。但这不是一个“整体”字符串。-尽管如此,将其馈入strcpy等不会使您的PC爆炸,因为这些功能只会“看到” "CS"零件。
哈根·冯·埃岑

2
c1 绝对可以用作的参数strcmp()。是否可以将其用作更改字符串函数的参数取决于未提供的其他因素。
EOF,

2
的内容c1是可变的,所以我不明白为什么它不能成为有效的目标参数strcpy或类似参数,除非它的大小不足以容纳源字符串。那不会使它不是字符串,只是不是给定目的的合适字符串。
John Bollinger

1
总体而言,我同意这个问题的措词含糊。该表达式c1将满足所有标准库(窄)字符串函数(包括所有专门命名的字符串函数)的字符串参数的基本要求,但该行为可能不是调用者期望或想要的(甚至忽略了可能引发的未定义行为)。
John Bollinger

1
请注意,类型不必为char。任何字符类型都可以。
chux-恢复莫妮卡

Answers:


8

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

那里还有第二个字符串"324",从&c1[3]- 开始,但是只要您访问c1as c1,该字符串"CS"就是所有函数strcpy()等。会看到。


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


那么,c1strcpy()命令中用作目标字符串是否合适?这个问题是模棱两可的-充其量是。
Andrew Henle

1
当然,您可以将c1用作任一参数strcpy()。从各个方面来看,它都是一个完美的普通字符串。普通字符串通常在终止符之后包含剩余的垃圾。这个垃圾被硬编码到程序中的事实给人一种印象,即作者打算以c1非字符串方式使用它,但这不是问题的一部分。
李丹尼尔·克罗克

c1等同于&c1[0]”误导。 c1是一个数组。 &c1[0]是一个指针。
chux-恢复莫妮卡

2

如果您想了解C语言中字符串定义的细节,请转到源代码。

根据C90标准

7图书馆

7.1简介

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

(以后的标准没有相关更改。)

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

如果我们将数组传递给函数,则它会衰减为指向其第一个元素的指针,从而+c1指向一个字符串(第一个元素),这对于任何期望指向字符串的指针的函数都足够了。它没有指向字符串“ CS \ 0324”,但是对于您的讲师问题(可能是模棱两可的)而言,这可能已经足够了。


4
我认为即使按此定义,c1显然也是字符串“ CS”。期。终止符之后它可能包含非零字节的事实是无关紧要的-许多字符串在其生命周期中都会像这样。
Lee Daniel Crocker

+c1指向字符串,因为c1它以字符串开头。但是,这绝不会以任何方式,形状或形式构成c1字符串。
重复数据删除器

2
它是一段内存的地址,其中包含一些以零字节结尾的字符。如果将printf()与%s一起使用就可以了,那么将其传递给strlen()会给出一个很好的数字,如果传递给strcpy()则会起作用,等等。听起来像是一个字符串。
Lee Daniel Crocker


当然。但是数组当然可以是字符串。
Lee Daniel Crocker

0

添加到@DevSolar的答案中,是在弄弄给定的字符串后发现的,如果是这样的话:

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

如果输出此字符串,将得到CS03240且该字符串的大小为7。据我所知,\\0它用于表示空字符( \0)。如果您这样做:

printf("\0");

您不会在输出日志上看到任何内容,但是如果您这样做:

printf("\\0");

您会看到一个\0,这是预期的,因为要输出特殊字符(例如反斜杠或引号),您需要将其\与一起使用。

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

因此,也许可以跟进这个问题,这是怎么回事?


1
'\\0'不是空字符。它是一个多字符常量。它具有的实现定义值肯定不在的范围内charc1[]不是字符串,因为它缺少空字符。“您输出此字符串”可能导致未定义的行为
chux-恢复莫妮卡

尽管我查找了多字符常量,但我并没有完全理解您。如果c1 []不是字符串,因为它的末尾没有空字符,那么为什么在OP最初发布的情况下大小为7?
rasengan__

char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };大小为7,因为它使用7个值进行了初始化。它的大小字符串无关。char c1[] = { 1, 2, 3, 4, 5, 6, 7 };仍然使它大小7
chux -恢复莫妮卡

至于数组是否c1包含刺痛?那是一个单独的问题。见
chux -恢复莫妮卡
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.