字符指针和字符数组
2007-02-13 18:21
134 查看
字符指针和字符数组
char* s1="hello";
char s2[]="world";
两个表达式的含义是一样的.
如果讲不同之处的话,VC6中编译时,对这两种定义进行了不同的处理;
char *s1 = "hello"; 中的"hello",编译时指针指向的区域位于PE文件的.rdata节中,是只读的.
不信的话,你可以试试:
main()
{
char *s1="hello";
char s2[]="world";
*(s2+2)='x'; //正确
*(s1+2)='x'; //执行时出错.
}
1.严格的说两个表达的意思是不完全一样的,因为前者是个字符串指针,这个指针S1所存的地址就是存储字符串前8个字节即hello/n/n/n的那个地址。
2.而后者是字符数组。每个字符都有一个独立的地址。
见图示。
此问题代码中,"hello"是一个常量,由于c/c++定义中常量是不能被修改的。所以尽管飞翔将存储常量的地址赋给了一个指针,指针可以获得这个常量的值,但是对它进行修改却是非法的。
根据c/c++语法,当你声明该量为常量,即告诉程序和编译器,你不希望此量被修改。
程序的实现,为了保护常量,特将常量都放在受保护的静态存储区内。凡是试图修改这个区域内的值,都将被视为非法,并报错。
这不能理解为凡是字符串都是放在静态存储区域的。这个跟数据类型没有关系,而是这个量是变量还是常量的问题。例如,一个字符串变量就是可以被修改的。
这种静态存储区域的保护机制是由编译器实现的,而非存储该值的内存的电器属性。换言之,实质上内存永远都可以被用户随意修改,只是编译器给用户的代码注入了一些自己的保护代码,通过软件手段将这段内存软保护起来。这种保护在汇编级别可以轻松突破,其保护也就无效了。
vc6的debug模式编译结果给程序添加了这样的保护,帮助用户尽早发现程序错误,而非此保护不可或缺。而release模式下对程序针对运行效率进行了优化,这样的保护显然是要消耗系统资源的,不利于提高效率。而且编译器假定,一个要发布的想要在release模式下编译的程序必然经过了debug模式的调试,已经处理了这样的错误。所以此时在审查就是冗余的了,vc6的release模式下放弃了对常量的保护。因此如果你的代码没有经过debug模式的编译而直接release,就没有人去检查你是否修改了常量,也没有人去禁止这个操作。
这并非说release模式下承认对常量修改的合法性,仅仅是不去管理罢了。vc6的release模式下放弃了对常量的保护,但是其他的实现未必这样做,这要具体看你的实现环境了。
从本质上说,对于机器,对于硬件是不存在常量与变量的区别的。它们都是内存中被分配了的一段内存空间罢了。甚至不存在数据类型上的区别。对所有的数据来说,内存都是一样的。数据之间的相互区别也是通过存在内存中的数据实现的。
对于这方面,学习过汇编的朋友会比较清楚。
char* s1="hello";
char s2[]="world";
两个表达式的含义是一样的.
如果讲不同之处的话,VC6中编译时,对这两种定义进行了不同的处理;
char *s1 = "hello"; 中的"hello",编译时指针指向的区域位于PE文件的.rdata节中,是只读的.
不信的话,你可以试试:
main()
{
char *s1="hello";
char s2[]="world";
*(s2+2)='x'; //正确
*(s1+2)='x'; //执行时出错.
}
1.严格的说两个表达的意思是不完全一样的,因为前者是个字符串指针,这个指针S1所存的地址就是存储字符串前8个字节即hello/n/n/n的那个地址。
2.而后者是字符数组。每个字符都有一个独立的地址。
见图示。
此问题代码中,"hello"是一个常量,由于c/c++定义中常量是不能被修改的。所以尽管飞翔将存储常量的地址赋给了一个指针,指针可以获得这个常量的值,但是对它进行修改却是非法的。
根据c/c++语法,当你声明该量为常量,即告诉程序和编译器,你不希望此量被修改。
程序的实现,为了保护常量,特将常量都放在受保护的静态存储区内。凡是试图修改这个区域内的值,都将被视为非法,并报错。
这不能理解为凡是字符串都是放在静态存储区域的。这个跟数据类型没有关系,而是这个量是变量还是常量的问题。例如,一个字符串变量就是可以被修改的。
这种静态存储区域的保护机制是由编译器实现的,而非存储该值的内存的电器属性。换言之,实质上内存永远都可以被用户随意修改,只是编译器给用户的代码注入了一些自己的保护代码,通过软件手段将这段内存软保护起来。这种保护在汇编级别可以轻松突破,其保护也就无效了。
vc6的debug模式编译结果给程序添加了这样的保护,帮助用户尽早发现程序错误,而非此保护不可或缺。而release模式下对程序针对运行效率进行了优化,这样的保护显然是要消耗系统资源的,不利于提高效率。而且编译器假定,一个要发布的想要在release模式下编译的程序必然经过了debug模式的调试,已经处理了这样的错误。所以此时在审查就是冗余的了,vc6的release模式下放弃了对常量的保护。因此如果你的代码没有经过debug模式的编译而直接release,就没有人去检查你是否修改了常量,也没有人去禁止这个操作。
这并非说release模式下承认对常量修改的合法性,仅仅是不去管理罢了。vc6的release模式下放弃了对常量的保护,但是其他的实现未必这样做,这要具体看你的实现环境了。
从本质上说,对于机器,对于硬件是不存在常量与变量的区别的。它们都是内存中被分配了的一段内存空间罢了。甚至不存在数据类型上的区别。对所有的数据来说,内存都是一样的。数据之间的相互区别也是通过存在内存中的数据实现的。
对于这方面,学习过汇编的朋友会比较清楚。
相关文章推荐
- 指针的相关运算,包括一维数组、二维数组、字符数组的sizeof、strlen运算
- 字符数组与字符指针的区别。
- 字符数组和字符串指针在内存中存储
- 字符数组与字符指针的区别。
- C/C++——声明一个到字符的指针,包含10个整数的数组,到包含10个整数的数组的引用,到字符串的数组的指针,到字符的指针的指针...
- 字符数组,字符指针
- 字符常量,字符变量,字符数组,字符串常量,字符串指针
- 字符数组指针
- 字符数组,字符指针,sizeof,strlen总结
- 字符数组和字符串指针,指针和引用,指针和多维数组
- C语言中字符数组和字符串指针分析
- 有一段文本,将文本中的所有单词,存放到一个字符指针数组中(要求每个单词内存恰好)。
- 3、有一段文本,将文本中的所有单词,存放到一个字符指针数组中(要求每个单词内存恰好)
- 有一段文本,将文本中的所有单词,存放到一个字符指针数组中。
- 字符指针和字符数组
- 关于c语言中的字符数组和字符串指针
- 内存的堆分配和栈分配 & 字符数组,字符指针,Sizeof总结
- 字符数组和字符串指针的区别
- 一维数组、二维数组、字符数组、指针 相关的 sizeof 计算
- 关于各种字符数组及指针的小研究