【发布时间】:2016-01-11 02:34:11
【问题描述】:
我尝试将char *代表的句子中的大写改为小写。
我得到一个错误:当我取消引用指针时访问冲突。
// Uppercase to lowercase
char *str = "My sentence";
*str = 'm';
【问题讨论】:
-
为什么不标记一种语言?
标签: c dereference
我尝试将char *代表的句子中的大写改为小写。
我得到一个错误:当我取消引用指针时访问冲突。
// Uppercase to lowercase
char *str = "My sentence";
*str = 'm';
【问题讨论】:
标签: c dereference
原因是你使用了错误的格式来定义一个字符串。你想要:
char str[] = "My Sentence";
*str = 'm';
您所写的内容定义了一个指针,然后将“我的句子”分配给 指针 作为内存地址。您收到访问冲突,因为您不拥有“My Sente”的内存,这很可能是被引用的地址。
【讨论】:
代码"My sentence" 是一个“字符串文字”,系统有意将字符串文字放置在标记为只读的内存中,以帮助捕获错误。在 C 中,更改字符串文字中的字节是未定义的行为(即使字符没有 const 限定符!),而在 C++ 中,字符是 const 并且您可能无法编辑常量内存。这些规则的好处是,如果您在一个程序中有两次相同的字符串,则可以对它们进行重复数据删除,并且只保留一份副本。
您可能希望分配一些新内存并在那里编辑您的字符串。 @David Hoelzer 的回答显示了如何将副本放在堆栈内存上。以下是如何在堆上做到这一点:
char *str = calloc(200, 1);
strcpy(str, "My sentence");
*str = 'm';
/* ... */
free(str);
【讨论】:
是undefined behavior6.4.5p6 String literals, page 63对这样的字符串文字进行变异:
.... 如果程序试图修改这样的数组,行为是 未定义。
您可以使用字符串文字来初始化数组,而不是改变字符串文字的地址(地址由ptr 指向)。
在 ISO9899 的第 130 页上,您会看到:
声明
char s[] = "abc", t[3] = "abc";
定义“普通”字符数组对象 s 和 t,其元素用字符串字面量初始化。 该声明与
相同
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
数组的内容是可以修改的。另一方面,声明
char *p = "abc";
定义 p 类型为“pointer to char”,并将其初始化为指向类型为“array of char”的对象 长度为 4,其元素用字符串字面量初始化。 如果尝试使用 p 来 修改数组的内容,行为未定义。
【讨论】: