char *s = "0123"和 char s[] = "0123"的区别

rookiemaster · 2024-3-29 16:39:15 · 271 次点击
为什么前者不可以修改,后者可以修改,是因为存储区域的问题吗?
举报· 271 次点击
登录 注册 站外分享
21 条回复  
arloor 小成 2024-3-30 22:26:19
//main.cpp  
int a = 0; 全局初始化区  
char *p1; 全局未初始化区  
main()  
{  
      int a = 4; 栈,4 也是存在栈上  
      char s[] = "abc"; 栈  "abc"也是存在栈上
      char *p2; 栈  
      char *p3 = "123456"; 123456\0 在常量区(是在 Data 段上),p3 在栈上。  
      static int c =0 ; 全局(静态)初始化为 0,就是放在 BSS 段   
      p1 = (char *)malloc(10);  
      p2 = (char *)malloc(20);  
      malloc 分配得来得 10 和 20 字节的区域就在堆区。因为属于动态申请分配内存空间  
      strcpy(p1, "123456"); 123456\0 放在常量区,编译器可能会将它与 p3 所指向的"123456"优化成一个地方。  
}
wkla 小成 2024-3-30 11:23:01
C++会提示"const char *" 类型的值不能用于初始化 "char *" 类型的实体。C 不会。
不过 C 会把这个字符串存只读段里,所以写的话会报段错误。

我说怎么怪怪的,越看越不对劲。只能说这套该扔就扔吧。
Inn0Vat10n 小成 2024-3-30 10:10:48
@qq135449773 可这个问题,确实百度都能直接找到答案
zooo 小成 2024-3-30 09:55:02
插个题外话,不喜勿喷

都 2024 年,C 语言这套古怪遗留语言表达该扔垃圾箱了
xuanbg 小成 2024-3-30 09:27:35
指针怎么就不能修改了?
jaycelhz 小成 2024-3-30 09:00:01
我之前也被还有 char **s 和 char *[]s 搞晕
FaiChou 初学 2024-3-30 08:08:31
新手确实要过这一关,一楼解释的就很好。
lff0305 小成 2024-3-30 00:18:28
十多年以前仔细研究过这个 char *s = "0123"。当时用的还是 VC6.
结果比较有意思(针对 VC6 ,之后的应该改进了)。

对于 Debug 版,“0123” 会被放到只读数据段里面(好像是叫.rdata). char* s 是个指向这个只读数据段中一小段数据的一个指针。任何对这个数据段的写操作都会引发段错误。

相应的这避免了两次调用相同的函数,结果不一致的问题。
比如下面的代码,假设可写,那么会有

test() {
   char*s = "123";
   printf("%s", s);
   s[1] = 'a';
}  

test();
test();  <---  这里打印出来 1a3 ,和程序的语义不一致。

有意思的是上面的代码在 Release 版是没有出错的,打印出来两行 123 和 1a3 。
当时看了下的结果是,
对于 Debug 版,生成的 exe 有三个段,代码段(可执行),只读数据段(只读),普通数据段(可读可写)。
而对于 Release 版,连接器把所有三个段捏到一起去了,整个 exe 文件只有一个段,这个段可读可写可执行。

总之这个问题和系统的段页式内存管理,以及编译器连接器都有关系
MrKrabs 小成 2024-3-29 21:20:47
一个栈上放指针,一个直接放数据
Nosub 小成 2024-3-29 19:58:38
你需要的是一本《 c primer plus 》,更进一步如果你要搞清楚作用域和内存分配的问题,可以看看《征服 c 指针》,少问人,多读书
123下一页
返回顶部