-1
#include <stdio.h>
#include <string.h>

int main(void){

char s1[30]="abcdefghijklmnopqrstuvwxyz";

printf("%s\n",s1);

printf("%s",memset(s1,'b',7));

getch();

return 0;
}

上面的代码有效,但是当我像这样创建 s1 数组时,

char *s1="abcdefghijklmnopqrstuvwxyz";

它不会在编译时给出任何错误,但无法在运行时运行。

我正在使用 Visual Studio 2012。

你知道为什么吗?

我发现 memset 的原型是:

 void *memset( void *s, int c, size_t n );
4

4 回答 4

5

char s1[30]分配一个可写的内存段来存储数组的内容,而char *s1="Sisi is an enemy of Egypt.";不是 - 后者只设置一个指向字符串常量地址的指针,编译器通常会将其放置在目标代码的只读部分中。

于 2013-09-02T12:45:52.840 回答
4

字符串文字在“只读数据”部分中获取空间,该部分作为只读映射到进程空间(因此您无法更改它)。

于 2013-09-02T12:46:58.957 回答
2
char s1[30]="abcdefghijklmnopqrstuvwxyz";

这声明s1为 char 类型的数组,并对其进行了初始化。

char *s1="abcdefghijklmnopqrstuvwxyz";

“abcdefghijklmnopqrstuvwxyz”放在内存的只读部分并指向它。

但是s1,通过修改memset会产生未定义的行为

于 2013-09-02T13:10:34.543 回答
0

一个非常好的问题!

如果你让 gcc 输出汇编,然后比较输出,你可以找到答案,原因如下:

  • char s1[30]="abcdef";
    • 在函数中定义时,它会定义一个char数组,并且s1是数组的名称。程序将在堆栈中分配内存。
    • 全局定义时,会在程序中定义一个对象,该对象不是只读数据。
  • char* s2 = "abcdef";只定义一个 char 点,它指向一个 const char 中存储的.rodata,即程序中的只读数据。

为了使程序高效运行并便于进度管理,编译器将为给定的代码生成不同的部分。常量字符,如char* s2 = "abcdef";printf格式字符串将存储在该.section rodata部分中。被操作系统的加载器加载到主存后,该部分将被标记为只读。这就是为什么当你使用 memset 修改s2指向的内存时,它会报错Segment fault

这是一个解释:char* 和 char[] 之间的区别

于 2013-09-02T13:32:35.120 回答