在C++中对于以下语句:
一个对比:
对于语句: int i = 3
int main() { int j = i; ... }
在编译时不需要确定局部变量 j 的值,而是在运行时读取i 的值来赋给 j. 编译连接后的可执行文件中不会存放j 的值,只有相应的赋值语句的代码。与此相对的,由于i 是全局变量,存储在静态存储区,因此在编译时其值就需要确定其值,在目标文件中会分配空间来存放 i 的值,运行时不会有赋值语句来给 i 赋值, 没有对应的代码。
而对于语句: int i = 3; int j = i;
由于j 是全局变量,存储在静态存储区,因此也需要在编译时确定其值。而i 是变量,不是常量,i 的值无法在编译时确定,这就造成j 的值也无法在编译时确定,所以C对此就会报错,在gcc中报错为:initializer element is not constant,而C++采取了另外一种做法,在编译时简单的把 j 作为未初始化的全局变量放入.bss 区,其默认值为0,然后添加一条语句在运行时给 j 赋值,并保证这条语句在 main函数开始之前执行。因此j 的初始化实际上实在运行时完成的。 在C99标准中有如下的描述: All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals,既,所有用来初始化一个具有静态存储生命周期的对象的表达式应该是常量表达式或字符串字面值。
数组和指针的差别: char heart[] = "I love Tillie!"; char *head = "I love Millie!"; 差别在于:前者初始化一个字符数组的元素,既,将前者为定义一个数组,然后将数组的元素初始化为后面的字符串,而后者则是一个真正的字符串常量,这个指针被初始化为指向这个字符串常量的存储位置,而且数组名heart是个常量,而指针head是个变量。 在使用中都可以使用数组名或指针加法的形式将字符串输出。 但是 head = heart是可以的, heart = head 是不可以的,因为heart为常量,就像 3 = x是不可以的。 我们可以任意修改heart数组中的任何一个元素,但是不能修改head所指向的字符串,原因在于编译器可能选择内存中同一个内存单元的拷贝,来表示所有相同的字符串文字,既后者的实现方式不一定会分配一块内存存储字符串,head可能指向内存总已经有了相同字符串的内存的地址。例如,下面的语句都指向字符串“Klingon”的同一个单独的内存位置。 char *p1 = "Klingon"; p1[0] = 'F' //可以修改吗 printf("Klingon"); printf("be ware the %ss!\n","Klingon"); 这既是说,编译器可以用相同的地址来代替每一个"Klingon"的实例。如果编译器使用这种单个拷贝表示方法并且允许把p1[0] 修改为'F'的话,那么将影响到所有的对这个字符串的使用。于是,打印字符串"Klingon"的语句实际就会显示为"Flingon"。 实际上,有些个编译器确实是按照这种容易混淆的方式工作的,而其他一些这回产生异常的中断。因此建议的做法是初始化一个指向字符串文字的指针时使用const修饰符: const char *p1 = "Klingon" //推荐用法, 用一个字符串文字来初始化一个非const的数组,这不会导致此类问题,以为数组会从最初的字符串得到一个拷贝。 |
转载于:https://blog.51cto.com/assassinwu/987043