为什么前者不可以修改,后者可以修改,是因为存储区域的问题吗?
1
huang119412 237 天前 2
因为 char s[] = "0123",是语法糖。"0123"是常量字符串,不能修改。但是使用字符数组编译器会把"0123"在栈上复制一份,并把首地址赋值给数组名。
|
2
tuwulin365 237 天前
|
4
throcean 237 天前
前面在编译的时候就会生成字符串常量在静态常量区(好像是这个区,有点忘了),后者是栈上的一个字符数组
|
5
tzxxxx 237 天前
https://www.gnu.org/software/c-intro-and-ref/manual/html_node/String-Constants.html
这个链接中说:The string constant is probably stored in a read-only area of memory. 似乎还没有说字符串常量一定在只读内存中,不清楚什么场景下会出现。 |
6
qq135449773 237 天前 7
|
7
leonshaw 237 天前
两个都可以修改,一个是指针,一个是数组。
|
8
liuidetmks 237 天前 2
|
10
oIMOo 237 天前
@liuidetmks #8 这个网站好哎 不过汇编都还给老师了哈哈哈
|
11
hefish 237 天前
我写 c 的时候,一直是认为一样的,不同写法而已。
不过那已经是三十年前的事儿了。 |
12
outgoing4443 237 天前
第一种指针 s 指向一个字符串常量"0123",第二种方法定义了一个字符数组 s ,初始化为字符串"0123"
|
13
Nosub 237 天前 via iPhone
你需要的是一本《 c primer plus 》,更进一步如果你要搞清楚作用域和内存分配的问题,可以看看《征服 c 指针》,少问人,多读书
|
14
MrKrabs 237 天前
一个栈上放指针,一个直接放数据
|
15
lff0305 236 天前
十多年以前仔细研究过这个 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 文件只有一个段,这个段可读可写可执行。 总之这个问题和系统的段页式内存管理,以及编译器连接器都有关系 |
16
FaiChou 236 天前 via iPhone
新手确实要过这一关,一楼解释的就很好。
|
17
jaycelhz 236 天前
我之前也被还有 char **s 和 char *[]s 搞晕
|
18
xuanbg 236 天前
指针怎么就不能修改了?
|
19
zooo 236 天前
插个题外话,不喜勿喷
都 2024 年,C 语言这套古怪遗留语言表达该扔垃圾箱了 |
20
Inn0Vat10n 236 天前 1
@qq135449773 可这个问题,确实百度都能直接找到答案
|
21
wkla 236 天前
C++会提示"const char *" 类型的值不能用于初始化 "char *" 类型的实体。C 不会。
不过 C 会把这个字符串存只读段里,所以写的话会报段错误。 我说怎么怪怪的,越看越不对劲。只能说这套该扔就扔吧。 |
22
arloor 236 天前 via Android
//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"优化成一个地方。 } |