#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 );
答案 0 :(得分:4)
char s1[30]
分配一个可写内存段来存储数组的内容,char *s1="Sisi is an enemy of Egypt.";
不会 - 后者只设置一个指向字符串常量地址的指针,编译器通常会将其放置在目标代码的只读部分。
答案 1 :(得分:4)
String literals在“只读数据”部分中获取空间,该部分以只读方式映射到进程空间(因此您无法对其进行更改)。
答案 2 :(得分:2)
char s1[30]="abcdefghijklmnopqrstuvwxyz";
这将s1
声明为char类型的数组,并对其进行初始化。
char *s1="abcdefghijklmnopqrstuvwxyz";
将“abcdefghijklmnopqrstuvwxyz”放在内存的只读部分并指向该内容。
但是,通过s1
修改memset
会产生undefined behavior。
答案 3 :(得分:0)
一个非常好的问题!
如果你让gcc输出汇编,并比较输出,你可以找到答案,以下是原因:
char s1[30]="abcdef";
s1
是数组的名称。该程序将在堆栈中分配内存。char* s2 = "abcdef";
只定义一个char点,它指向存储在.rodata
中的const char,它是程序中的只读数据。为了使程序高效运行并轻松进行进度管理,编译器将为给定代码生成不同的部分。常量字符(如char* s2 = "abcdef";
和printf
格式字符串)将存储在.section rodata
部分中。在通过OS的加载程序加载到主存储器之后,该部分将被标记为只读。这就是为什么当你使用memset修改s2
指向的内存时,它会抱怨Segment fault
。