LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 636|回复: 5

请教一个关于指针和数组的问题

[复制链接]
发表于 2006-8-19 08:16:16 | 显示全部楼层 |阅读模式
今天遇到一个问题,向兄弟们请教:

  1. 1     #include <stdio.h>
  2. 2     int main()
  3. 3     {
  4. 4          char str[] = "ROOT";
  5. 5          str[0] = 'B';
  6. 6          return 0;
  7. 7     }
复制代码

这段代码没问题,但如果将程序的第4行改为:

  1. 4          char *str = "ROOT";
复制代码

就会出现段错误:Segmentationfault
请兄弟们指点,谢了。
发表于 2006-8-19 10:48:19 | 显示全部楼层
char str[] = "ROOT" 这是字符数组,数组中每一个元素都是一个字符变量。注意,变量是可以改变其值的。即:srt[0] = 'B'; 是合法的。

char *srt = "ROOT"; 定义的是一个指向字符串常量的字符指针,ROOT是常量,当然无法改变。
所以srt [0] = 'B'; 是非法的。
这并不是指针和数组的问题,楼主是没有弄清变量与常量的储存范围。如果知道一点汇编,你会知道像常量都是存放在只读内存区域中的,根本无法改变其值。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-8-19 11:07:44 | 显示全部楼层
Post by wsw
char str[] = "ROOT" 这是字符数组,数组中每一个元素都是一个字符变量。注意,变量是可以改变其值的。即:srt[0] = 'B'; 是合法的。

char *srt = "ROOT"; 定义的是一个指向字符串常量的字符指针,ROOT是常量,当然无法改变。
所以srt [0] = 'B'; 是非法的。
这并不是指针和数组的问题,楼主是没有弄清变量与常量的储存范围。如果知道一点汇编,你会知道像常量都是存放在只读内存区域中的,根本无法改变其值。

谢谢指点。
我知道一点汇编,但不多。"只读内存区域" 具体指的是内存的哪个部分?系统是如何标志这段内存(或变量)只读的呢?为什么编译器不能指出这个非法修改常量呢?
------------
我在网上搜索了一下,大部分的文章讲得都很浅显,没找到答案。
回复 支持 反对

使用道具 举报

发表于 2006-8-19 11:36:19 | 显示全部楼层
要了解深入一点的话,就要看看elf文件的格式了,坛子里有几篇文章介绍。我也写了一些,不是太好,姑且看一下吧!
http://www.linuxsir.cn/bbs/showthread.php?t=258981
关于“只读内存区域” 是elf文件格式中有几个区段中的内容是只读的,比如.text 区段是放的程序代码,当然是只读的。还有放常量的区段也是只读的等等。
回复 支持 反对

使用道具 举报

发表于 2006-8-19 11:39:35 | 显示全部楼层
char str[] = "ROOT"
char *srt = "ROOT";
这来两个的存放方式不一样
第一个是把字符串存放在一段数组内存,也就是放在可读写的内存str数组
第二个是指针,只是指向一个地址,指针本身只是存放一个地址.
你可能要问第二个的字符串存放在哪里?答案是存放在一个只读内存里的"字符串表”.C语言专门把常量的字符串存放在这个表里。第二个指针只是指向这个表的"root"一项。所以不能修改
如何标志只读,是关于CPU的一项功能。可以把不同的内存段分出等级和权限,只读等等。这是CPU保护模式的一个功能。是一个内存里固定格式的描述束缚决定的,CPU来执行。
这个没有语法错误,GCC不会报错。一般是调试的时候发现问题

如果要进一步看,请察看数据段描述符的TYPE字段(存储段描述符的第6个字节,0~3位),当1位(W位)=0的时候表示只读。。。当然,这只是x86的保护措施
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-8-19 12:01:09 | 显示全部楼层
谢谢两位兄弟的解释,现在明白了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表