c语言 全局字符串变量名,C语言全局变量的初始化和字符串常量

在C++中对于以下语句:

// 全局域

int i = 3;

int j = i;

编译时将i放入.data段,设置其值为3。而对于j,编译器遇到这种语句,只知道j = i,由于i是变量,不是常量,编译器无法在编译时直接得到它的值,编译器只会找到i的地址, 然后读取这个地址的内容,再把这个内容写入j的地址。编译器不能够直接用3来初始化j,因为计算机不是人,不懂简单的人类逻辑,我们想“因为i = 3,而j = i,所以j = 3",而计算机无法在逻辑上由i = 3和j = i来推出j = 3,就好像图灵机不可能证明某个论题的真伪一样。

计算机只会“取i的地址,把3放到i的地址中,取i的地址,读取这个地址中的内容,取j的地址,把这个内容 写入j的地址。它不会思考,不懂因果,只是机械地执行指令。编译器无法在编译时求得一个非常量的值,它只能在运行时通过读取变量地址来间接得到变量的值,而全局变量在编译时就必须确定其值,故C有静态存储区数据必须用常量初始化的规定。

在编译时只能用常量去初始化一个静态存储区的数据,而不能用“读取某个变量的内容”来初始化,所以编译器会将j放入.bss段,默认值为0,然后添加一条语句在运行时读取i的值,再赋给j。这条语句在调用main()之前完成。

一个对比:

对于语句:

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的数组,这不会导致此类问题,以为数组会从最初的字符串得到一个拷贝。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值