【问题标题】:printf in C with strings that has shorter initializer behaves weirdC中的printf与具有较短初始化程序的字符串的行为很奇怪
【发布时间】:2020-08-01 13:39:45
【问题描述】:

所以我尝试制作字符数组并玩弄它。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char ** argv) {

    char str1[11] = "Yo! Angelo!~";  //total length of 12, initializer is shorter
    char str2[14] = "Yo! Angelo!233"; //total length of 14, initializer is same length
    char str3[60] = "Yo! Angelo!wwww"; //initializer is longer

    printf("%s"\n, str1);

}

编译器给了我initializer-string for array of chars is too long的警告

我预计它只会给我 str1 的前 11 个字符,即Yo! Angelo! 没有'~'

但这是我将所有三个数组排成一行(第一个是前 11 个字符)

Yo! Angelo!Yo! Angelo!233Yo! Angelo!wwww(三个字符串连在一起,没有空格)

当我将初始化器更改为长度为 12(与字符串长度相同)时,同样的问题仍然存在

另外,当我尝试printf("%s\n", str2) 时,它也有类似的问题——它在一行中打印第二个和第三个字符串,中间没有任何内容

但当我将其更改为 13 或更大时,它只会按预期打印 str1。

这不是紧急情况,我知道我必须将字符串声明的长度超过它的长度(在这种情况下超过 13),但我只是想知道为什么 printf 会做这样时髦的事情。

谢谢~

【问题讨论】:

  • 您不能使用%s 打印字符数组。 %s 格式说明符仅用于字符串。
  • @DavidSchwartz Errr... 抱歉,我是 C 语言的新手,但 char str_name[size]; 几乎所有教程都显示了如何定义字符串...所以你能告诉我什么是正确的吗?那怎么办? (我一直以为char数组和字符串是一回事)
  • 想想strlen 的工作原理。
  • 如果你使用char example[4] = "abcd";,C允许初始化(省略空字节——C11 §6.7.19 Initialization ¶14,但另见[¶2]((port70.net/~nsz/c/c11/n1570.html#6.7.9p2));结果是一个字节数组,而不是字符串。§7.1.1 Definitions of terms ¶1字符串是由第一个空字符终止并包括第一个空字符的连续字符序列。最好不要让编译器计数;使用 char str1[] = "Yo! Angelo!~"; — 它不会计数时不要出错。

标签: c arrays string printf initializer


【解决方案1】:

当您使用对数组来说太长的字符串初始值设定项时,您会丢失尾随字符,包括尾随 NUL 终止符。因此,您最终会得到不包含字符串(无 NUL 终止符)的数组(str1 和 str2),因此当您尝试将其打印为字符串时,您会得到未定义的行为。具体来说,它会打印内存中数组后面发生的任何事情,结果是其他数组。

【讨论】:

  • 如果你使用了太长的初始化器,编译器需要报错(C11 §6.7.9 Initialization ¶2: 没有初始化器应该尝试为不包含在被初始化实体中的对象提供值. 这是一个约束;诊断是强制性的。我想,一些编译器可能会继续截断初始化程序。这不是我费心研究的领域,因为代码显然存在缺陷。因为char str1[11] = "Yo! Angelo!~"; 试图在 11 个字节的数据空间中放置 12 个字符和一个空字节,这是伪造的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
  • 2014-08-26
  • 2011-02-22
  • 2021-06-16
  • 1970-01-01
相关资源
最近更新 更多