首页
社区
课程
招聘
[求助]关于char *的一个问题
发表于: 2009-10-15 10:16 5831

[求助]关于char *的一个问题

2009-10-15 10:16
5831
有如下代码:

int main()
{
	char *c = "hello";

	*c = 't';

	return 0;
}


运行后程序崩溃。将char *c 改成char c[] 就没有问题了。
在网上搜索原因,char *定义的是全局区域的值 而char []定义的是局部区域的值

但是全局区域的值为什么就不能修改呢?

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (15)
雪    币: 615
活跃值: (1202)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
调试一下就知道问题所在
2009-10-15 10:25
0
雪    币: 18
活跃值: (80)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
汇编可能看到真相
         char *c = "hello";
  mov         dword ptr [c],offset string "hello" (41573Ch)

        *c = 0;
  mov         eax,dword ptr [c]
  mov         byte ptr [eax],0

        char c[] = "hello";
  mov         eax,dword ptr [string "hello" (41573Ch)]
  mov         dword ptr [ebp-10h],eax
  mov         cx,word ptr ds:[415740h]
  mov         word ptr [ebp-0Ch],cx

        *c = 0;
  mov         byte ptr [ebp-10h],0
2009-10-15 10:27
0
雪    币: 222
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
楼上还是没有说清楚
mov         eax,dword ptr [c]
mov         byte ptr [eax],0
这两句会崩溃啊?
2009-10-15 10:29
0
雪    币: 412
活跃值: (30)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
5
"hello"在只读节,不能修改
会造成Access Violation
2009-10-15 11:28
0
雪    币: 796
活跃值: (370)
能力值: ( LV9,RANK:380 )
在线值:
发帖
回帖
粉丝
6
你指针用不对而已。。

int main()
{
  char *c = "hello";

  c = (char *)'t';

  return 0;
}

char *c = "hello";
*c 其实就是 hello 这串字母,而不是一个有效地址,所以你把 't'放到一个不存在的地址里,当然出错了。

总的来说呢,就是你对指针的概念理解不好
2009-10-15 11:33
0
雪    币: 18
活跃值: (80)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
char *c = "hello";
等同于const char *c="hello"指向常量的指针。

确切的意思是:定义一个字符型指针c指向"hello"字符串的首字符,即'h';
因为“hello”是常量字符串,是不能被修改的,所以*c='t',试图想修改
"hello"字符串会出现错误;

而char c[]="hello";是定义一个C字符串数组,等同于下面:
char c[]={'h','e','l','l','o','\0'};
因此对*c='t',相当于 把这个字符数组的首字符'h'替换成了't';

这两个的区别楼主可以再好好理解一下~.

2009-10-15 11:45
0
雪    币: 347
活跃值: (25)
能力值: ( LV9,RANK:420 )
在线值:
发帖
回帖
粉丝
8
有指针就会有奇迹
2009-10-15 18:26
0
雪    币: 919
活跃值: (163)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
char *C定义为指针,而不是数组,因此char *c=“hello”只是将c指向常量“Hello”,而C为地址,当C=‘T’时就会向常量地址里写入。出现0x0005错误。
2009-10-15 19:12
0
雪    币: 202
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
看函数的堆栈就明白了。先看懂X86编码!
2009-10-15 20:38
0
雪    币: 287
活跃值: (102)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
11
加一行

#pragma comment(linker, "/section:.rdata,rw")
2009-10-15 21:38
0
雪    币: 276
活跃值: (34)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
呵呵,学习了。。。。
2009-10-16 08:01
0
雪    币: 486
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
也来学习了!
2009-10-16 08:44
0
雪    币: 367
活跃值: (20)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
14
/Gf /GF
VC6默认使用/Gf,这将字符串放入可写段
之后版本只能使用/GF,这将字符串放入只读段.
2009-10-16 09:14
0
雪    币: 636
活跃值: (174)
能力值: ( LV9,RANK:260 )
在线值:
发帖
回帖
粉丝
15
char *c = "hello";

意思是c指向字符串常量,c是指针,不是数组,这是c语言基础。
至于字符串常量到底是不是真的常量,就要看对应的页面属性了,这个依编译器高兴而定,如果被放到了只读区里,当然改不了了。

DWORD dwOldProtect;
VirtualProtect( c, 4096,PAGE_READWRITE ,&dwOldProtect )
*c = 't';

先把页面属性改掉,这样就可以改了
2009-10-16 09:56
0
雪    币: 367
活跃值: (20)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
16
不考虑编译器的实际行为(实际上,一般情况你不应针对特定的编译器写特殊代码),ayunaa 的答案就是你需要的.
2009-10-16 17:48
0
游客
登录 | 注册 方可回帖
返回
//