【问题标题】:C chars add themselves up for no reason [duplicate]C字符无缘无故地加起来[重复]
【发布时间】:2020-03-01 04:20:58
【问题描述】:

我想我要疯了,因为我找不到解释为什么 C 会组合我的字符。

我给你们做了一个测试程序...

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

int main()
{
    char alphabet_big[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    char alphabet_small[26] = "abcdefghijklmnopqrstuvwxyz";

    printf("%s\n", alphabet_small);
    return 0;
}

结果:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZV

为什么 C 结合了字母小和字母大?那没有意义。为什么字符末尾有一个“V”?

我希望有人可以为我提供这个“问题”的答案。

最好的问候。

【问题讨论】:

  • 使用 char alphabet_big[] = ... 。编译器会正确分配一个大小为 27 的数组。(不是 26)
  • 太短了一个错误...永远不要忘记将 array 视为 string 所需的'\0'。 (堆栈也变小了,ABC... 在顶部,然后是 abc...)当您打印 abc... no end-of-string 时,数组之间没有 nul-terminating 字符跟随'z'printf 愉快地继续打印字符,直到它不能再打印...
  • 未定义的行为,因为数组不是以 nul 结尾的,并且带有 %sprintf() 假定传递了一个以 nul 结尾的数组。一组 26 个字母加上一个 nul 终止符要求数组至少有 27 个字符。遗憾的是,如果提供的数组不足以容纳初始化程序,则标准允许截断。

标签: c char printf


【解决方案1】:

请记住,C String 被定义为 null 终止 char 数组。

在此处更改声明和初始化语句:(对于两个语句。)

char alphabet_big[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//forces compiler to use only 26 char
                                                     //regardless of the count of initializers
                                                     //(leaving no room for NULL terminator)

char alphabet_big[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//allows compiler to set aside
                 ^^                                 //the proper space, no matter how many initializers

第一个产生 undefined behavior 与任何字符串函数一起使用时,例如strcpystrcmp,在这种情况下printf"%s" 格式说明符一起使用。

第一个产生以下,不是不是 C 字符串:

|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|?|?|?|     

虽然第二个产生以下内容,这是一个 C 字符串:

|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|\0|?|?|   

注意 - 上图中使用的 ? 符号表示不属于程序的内存位置,其内容未知,甚至可能不存在。试图访问这些位置的程序将调用未定义的行为。

【讨论】:

  • 为什么字符串末尾有问号?您甚至无法确保编译器已在这些位置分配了任何内存。
  • 还是错了,因为那些内存位置不只是有未知的内容——你甚至不知道它们是否存在。
  • 如果一个糟糕的插图让人相信不真实的东西,那么它可能会造成严重的伤害。
  • 我并不声称它们不存在。我声称它们可能不存在,您或我都不能说一种或另一种方式,因为适用的标准不作任何保证。事实上,这些标准留下了很大的灵活性来适应在实践中通常不会看到的奇怪的 CPU 或内存架构。任何遇到这种情况的人都会被你的“插图”误导。
  • 只是一个插图
【解决方案2】:

通常,库函数希望在字符串的末尾找到一个 NUL 字节,编译器很乐意为您自动添加它除了您告诉它 alphabet_big 只有26 字节,基本上避免了额外的 NUL 字节,因此它与接下来的内容结合在一起。

删除26,让编译器为你计算。

【讨论】:

  • 请注意,它不能保证将它与任何东西结合起来,这就是在这种情况下使用此编译器会发生的情况。这里没有什么可依赖的。
  • 绝对:将不以 NUL 字节终止的字符串传递给需要一个字节的库函数是自找麻烦。
  • 哦。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2019-11-02
  • 1970-01-01
  • 1970-01-01
  • 2019-04-26
  • 2021-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多