为啥char *a[2],a[0]=\"good\";对a[0][1]赋值会出错

因为常量字符串是只读的。它不是在堆上新分配的,而是处于程序文件的数据段或者附加数据段,随文件一同加载进内存,默认只读。补充常见字符串常量的一些东西:const char* str = "abc"; // 只读char str = "abc"; // 会从一个只读字符串中将"abc"复制到str中,因此str可读写。char str = { \u0026#39;a\u0026#39;, \u0026#39;b\u0026#39;, \u0026#39;c\u0026#39;, \u0026#39;\\0\u0026#39; }; // 会先分配str的内存,然后逐个填充。2和3的写法在大多数情况是没有区别的,但是在写一些shellcode的时候,如果指令存在移动或者引用只读字串的行为,则3的写法能在这种情况下不出错。
■网友
a=(char*)manlloc(5*sizeof(char));strcpy(a,"good");这样
■网友
修改StringLiteral是无定义的行为(undefined behavior)
■网友
现在再看这个问题,其实里面犯了很多常识性错误,无奈当初学习的时候脑子不好使,弄混了很多概念,当时对于paintdream的回答,也是不全理解,在掌握了二进制逆向后,再看这个提问,就觉得简单的不行了。char *a;//这里声明了一个指针数组a,该数组有两个成员,在x64的操作系统里,一个指针占8字节,所以a所在地址包含了16字节的内存。a="good";//此处给第一个指针进行了赋值,将常量字符串good的地址赋值给了a所在的前8字节。在exe文件中,这个字符串是存储在.data段。a="nice";//同上,将nice的地址赋值给了后8字节char b;//这里声明了一个char类型的二维数组,一个char大小为1字节,因此b所在地址包含了4字节大小。b="good";//这个操作其实是错误的,b的成员是char,而不是char*指针,此处把字符串地址赋值给char类型是错误的操作,因为你没法让一个字节存下8字节。再说a,它其实代表两个操作。1,从a处取出指针地址,即"good"的存储地址;2,从good字符串中索引第2个字符"o"。所以这里的操作其实是从只读节区读取字符,如果赋值,就会触发异常,因为该字符串所在地址是只读的,不能写。这也解释了为什么它是个常量不是变量了。那如果想修改字符串怎么办?malloc一片内存,然后使用strcpy拷贝常量字符串到数组里。或者使用char str="good"来赋值,编译器会自动识别字符串长度并赋值给str指向的内存区域。因此修改str并不会修改到good的内存,而是str指向的内存。
■网友
你声明的时候直接定义,不要声明了再定义
■网友
不出錯的話, 你的代碼是C.但是你犯了一個錯誤。不同於C++, C中的string是依靠動態數組來定義和使用的。你的代碼可以說是全部錯誤的。 char* a;可以認爲是你聲明了一個數組的指針變量,數據類型爲字節。要知道,指針變量是用了存地址的一種變量類型,本身並不可以作爲容器也就是說不能存任何其他東西除了地址。你可以聲明一個變量,再將其地址附給你所聲明的指針變量。我寫了一些code, 希望可以幫助你理解string在C語言中是如何運用的。// copyright 2015 Zhexuan Yang#include \u0026lt;iostream\u0026gt;#include \u0026lt;string.h\u0026gt;int main() { /* char* a; a = "good"; // conversion string literal to char* which is illegal a = "nice"; char b; b = "good"; */ // assigning char from incompatible type const \u0026#39;char // The correct way is the Following const char* c; c = "good"; // c is read only char str = "good"; // using array to store string variable // this means the Following // str = \u0026#39;g\u0026#39; // str = \u0026#39;o\u0026#39; // str = \u0026#39;o\u0026#39; // str = \u0026#39;d\u0026#39; // str = \u0026#39;\\0\u0026#39; // we can cout it std::cout \u0026lt;\u0026lt; str \u0026lt;\u0026lt; std::endl; // use terminal g++ test2.cpp // and then enter ./a.out // the thing dispaly in screen is \u0026#39;d\u0026#39; char* a; a = str; std::cout \u0026lt;\u0026lt; *a \u0026lt;\u0026lt; std::endl; // output is just the first character of str // g std::cout \u0026lt;\u0026lt; a \u0026lt;\u0026lt; std::endl; // output is "good" std::cout \u0026lt;\u0026lt; a \u0026lt;\u0026lt; std::endl; // output is \u0026#39;o\u0026#39; std::cout \u0026lt;\u0026lt; *a \u0026lt;\u0026lt; std::endl; // output is the entire str // good return 0;}


推荐阅读