【问题标题】:Char String Assignment字符字符串赋值
【发布时间】:2011-12-27 13:45:06
【问题描述】:

我正在使用 Microsoft Visual Studio 环境。我遇到了一个奇怪的行为

 char *src ="123";
 char *des ="abc";
 printf("\nThe src string is %c", src[0]);
 printf("\tThe dest string is %c",dest[0]);

 des[0] = src[0];

 printf("\nThe src string is %c", src[0]);
 printf("\tThe dest string is %c",dest[0]);

结果是:

1 a
1 a   

这意味着des[0] 没有被初始化。因为 src 指向字符串的第一个元素。我想按照规则这应该可行。

【问题讨论】:

  • 请用语言标记问题,以便人们知道您在说什么。
  • 如果你使用的是 C++,那你到底为什么要使用 printf 和 C 风格的字符串?
  • @CodyGray:对不起。我使用 C 语言作为平台。我已经编辑了标签。

标签: c variable-assignment


【解决方案1】:

这是未定义的行为:

des[0] = src[0];

试试这个:

char des[] ="abc";

【讨论】:

  • 谢谢。是的,它确实有效。但不是在这两种情况下,des 都会指向同一个位置。最终'des[0]' 等价于'*(des+0)'。通过未定义的行为,您指的是 C 规范吗?
  • @vinaygarg 这不是一回事。是的,我说的是 C 标准,但我希望 C++ 标准在这方面是相似的。
【解决方案2】:

由于 src 和 des 是用字符串字面量初始化的,它们的类型实际上应该是const char *,而不是char *;像这样:

const char * src ="123";
const char * des ="abc";

从来没有为它们中的任何一个分配内存,它们只是指向预定义的常量。因此,声明des[0] = src[0] 是未定义的行为;您正在尝试更改那里的常量!

任何体面的编译器实际上都应该警告您从 const char *char * 的隐式转换...

如果使用 C++,请考虑使用std::string 代替char *,并使用std::cout 代替printf

【讨论】:

    【解决方案3】:

    ISO/IEC 14882(编程语言 - C++)第 2.13.4 节说:

    1. 字符串字面量是由双引号括起来的字符序列(定义见 2.13.2),可以选择以字母 L 开头,如 "..." 或 L"..."。不以 L 开头的字符串文字是普通字符串文字,也称为窄字符串文字。一个普通的字符串字面量具有“n const char 数组”类型和静态存储持续时间 (3.7),其中 n 是字符串的大小,定义如下,并使用给定的字符进行初始化。 ...

    2. 是否所有字符串文字都是不同的(即,存储在不重叠的对象中)是由实现定义的。尝试修改字符串文字的效果是undefined

    【讨论】:

      【解决方案4】:

      在 C 中,"123" 等字符串文字存储为 char 的数组(在 C++ 中为 const char)。这些数组存储在内存中,以便它们在程序的生命周期内可用。尝试修改字符串文字的内容会导致未定义的行为;有时它会“工作”,有时它不会,这取决于编译器和平台,所以最好将字符串文字视为不可写。

      请记住,在大多数情况下,“N-element array of T”类型的表达式将被转换为“pointer to T”类型的表达式,其值是数组中第一个元素的位置.

      因此,当你写作时

      char *src = "123";
      char *des = "abc";
      

      表达式"123""abc"从“char的三元素数组”转换为“指向char的指针”,src将指向@ "123" 中的 987654332@ 和 des 将指向 "abc" 中的 'a'

      同样,尝试修改字符串文字的内容会导致未定义的行为,所以当您编写时

      des[0] = src[0];
      

      编译器可以随意处理该语句,从完全忽略它到完全按照您的期望执行,再到介于两者之间的任何操作。这意味着字符串文字或指向它们的指针不能用作strcpystrcatmemcpy 等调用的目标参数,也不应将它们用作strtok 等调用的参数。

      【讨论】:

        【解决方案5】:

        vinaygarg:这意味着des[0] 没有被初始化。因为 src 指向字符串的第一个元素。我想按照规则这应该可行。

        首先你必须记住 *src 和 *dst 被定义为指针,仅此而已。

        所以你必须问自己“123”和“abc”到底是什么,为什么不能改变?长话短说,它存储在应用程序内存中,即read-only。为什么?字符串必须与程序一起存储,以便在运行时可供您的代码使用,理论上您应该得到一个编译器警告,用于将非 const char* 分配给const char *。为什么是read-only? exe和dll的内存需要保护不被覆盖,所以它必须是只读的,以防止错误和病毒修改执行代码。

        那么如何将这个字符串放入可修改的内存中呢?

        // Copying into an array.
        const size_t BUFFER_SIZE = 256;
        char buffer[BUFFER_SIZE];
        strcpy(buffer, "abc");
        strncpy(buffer, "abc", BUFFER_SIZE-1);
        

        【讨论】:

        • @pmg 很抱歉,在撰写本文时并未意识到仅 C 的要求。已更新,谢谢指出。
        猜你喜欢
        • 1970-01-01
        • 2015-07-23
        • 2012-11-04
        • 2012-05-24
        • 1970-01-01
        • 2016-04-01
        • 2010-12-17
        • 2010-12-11
        • 1970-01-01
        相关资源
        最近更新 更多