【问题标题】:Different string initialization yields different behavior?不同的字符串初始化会产生不同的行为?
【发布时间】:2009-10-30 00:04:22
【问题描述】:

我怎么用下面的方法,把字符串中的所有字符都转成大写,

while (*postcode) {
    *postcode = toupper(*postcode);

    postcode++;
}

使用以下参数有效,

char wrong[20];
strcpy(wrong, "la1 4yt");

但以下不是,尽管它们是相同的?

char* wrong = "la1 4yt";

我的程序在尝试写入非法地址时崩溃(我猜是段错误)。不是mallocing 有问题吗?不是零极限?不应该……

通过调试,我注意到它在尝试将第一个字符分配为大写时崩溃。

任何帮助表示赞赏!

【问题讨论】:

  • +1 用于避免*postcode = toupper(*postcode++); 或同样糟糕的*postcode++ = toupper(*postcode); :)
  • 为了大声哭泣......这个完全相同的问题每周至少出现两次。
  • 你曾经是个新手,也是个短暂的人
  • 是的,但仅在 Stack Overflow 上搜索“c segfault”就可以在前 5 名中找到答案。新手并不排斥您自行搜索和阅读文档。

标签: c


【解决方案1】:
char* wrong = "la1 4yt";

这声明了一个指向字符串常量的指针。该常量无法修改,这就是您的代码崩溃的原因。如果你写的比较迂腐

const char* wrong = "la1 4yt"; // Better

那么编译器就会发现错误。每当您声明指向字符串文字的指针而不是创建数组时,您都应该这样做。

另一方面,这会为 20 个字符分配读/写存储空间,因此可以写入空间。

char wrong[20];

如果您想将其初始化为上面的字符串,您可以这样做,然后将被允许更改它。

char wrong[20] = "la1 4yt"; // Can be modified
char wrong[]   = "la1 4yt"; // Can be modified; only as large as required

【讨论】:

  • 在初始化 [mutable] 字符串时,是否只分配保存“la1 4yt”所需的内存?在数组中声明它对我来说太冗长了。
  • 当然可以,可以省略大小,让编译器自己计算。
【解决方案2】:
char * whatever = "some cont string";

是只读的。

【讨论】:

    【解决方案3】:

    在第二个变体中,"la1 4yt" 是一个常量,因此位于只读段中。只有指向常量的指针 (wrong) 是可写的。这就是你得到段错误的原因。然而,在第一个示例中,所有内容都是可写的。

    这个可能很有趣:http://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c/

    【解决方案4】:

    请参阅 C 常见问题列表中的 Question 8.5

    【讨论】:

      【解决方案5】:

      当你这样做时

      char wrong[20] = "la1 4yt";
      

      编译器复制字符串文字{'l', 'a', '1', ' ', '4', 'y', 't', '\0'}的元素到wrong数组的对应元素;当你这样做时

      char *wrong = "la1 4yt";
      

      编译器将字符串文字的地址分配给wrong

      字符串字面量是char[](字符数组),而不是const char[] ...但您不能更改它们!!

      引自标准:

      6.4.5 String literals
      6   It is unspecified whether these arrays are distinct provided
          their elements have the appropriate values. If the program
          attempts to modify such an array, the behavior is undefined.
      

      当我使用字符串文字来初始化 char * 时,我通常还会告诉编译器我不会通过在定义中添加 const 来更改该字符串文字的内容。

      const char *wrong = "la1 4yt";
      

      编辑

      假设你有

      char *test1 = "example test";
      char *test2 = "test";
      

      编译器创建了 1 个单字符串文字并使用该单字符串文字来初始化 test1 和 test2。如果您被允许更改字符串文字...

      test1[10] = 'x';       /* attempt to change the 's' */
      printf("%s\n", test2); /* print "text", not "test"! */
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-08
        • 2016-08-17
        • 2019-09-28
        • 2020-02-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多