当前位置:编程学习 > C/C++ >>

玩儿转C语言:C语言中的字符和字符串

  在C语言中,利用单引号和双引号分别表示字符和字符串,但在使用时,如果不能真正理解两者的本质区别,有可能会出现一些诡异的现象。下面我将通过实验,进行详细分析:

1、字符特性试验,代码如下:


[cpp] 
char ch_1 = 'a'; 
char ch_2 = 'abcd'; 
 
int ch_value_1 = 'abcdef'; 
int ch_value_2 = 'abcd'; 
分析:
       编译器vs2010:第3行error C2015: 常量中的字符太多;第2行warning C4305: “初始化”: 从“int”到“char”截断。

当改为“int ch_value_1 = 'abc' ; ”后,系统错误消失。见下图:

 

       可以看到,ch_1的数值是0x61(a的ascii值),ch_2数值是0x64(d的ascii值),而且他们可以被当做整数进行运算。在给ch_2赋值的时候,编译器就会用后边字符数值替换前边的数值,直到最后一个。这只是vs2010的做法,其他编译器是进行替换还是取第一个有效字符,需要试验论证。同时,ch_value_1的值是“abc”的ascii值组合,最高字节用0填充;这就更能说明了字符本质是一个整数。

      但是也要看到第一次试验失败,编译器并没有把超过4个字节的字符常量进行截断处理(类似于处理0x1234567890一样),因为它的空间占用超过了整型数的空间(32位)。整型数(32位)的存储空间可以容纳多个字符(8位),一次有的C编译器允许一个字符常量(或字符串常量)中包括多个字符,故用‘abcd’代替“abcd”有时不会报错。“abcd”指:一个含‘a’、‘b’、‘c’、‘d’和‘\0’五个字符的连续只读空间的首地址;‘abcd’一般没有定义,大多数C编译器认为:一个整数值,由‘a’、‘b’、‘c’、‘d’所代表的ascii值按照编译器定义的方式组合得到。

2、字符串特性试验,代码如下:

 

分析:

      指针变量ch_ptr_1存储的是字符串“testchar”的首地址,如果在内存窗口输入这个地址,可以看到该字符串。

      指针变量ch_ptr_2的值就是人为给赋予的,是字符序列的ascii值,这再次印证了第一次试验的结论。

      指针变量ch_ptr_3内容与ch_ptr_1相同,ch_ptr_4与ch_ptr_1不同,这是为什么呢?

     该程序在编译时没有报错,但是当执行line 17或line 18代码之一时,就会出错,系统不允许改变字符串的内容。

 

       单独执行line 20没有问题,说明字符串在系统内部是以一小段空间存储,并且根据该空间地址来操作的,同时printf函数接收的形参也就是字符串首地址。

       其实,常量字符串在系统内部是存储到“只读数据段”中的,这个跟数组是不一样的,数组里边的内容可以修改,但是常量字符串里边的内容不能修改。而且当定义两个相同的常量字符串时,系统内部会优化成一个,因为不可修改,所以就只存储了一次。这就是为什么ch_ptr_1和ch_ptr_3的值是一样的。但是,ch_ptr_4代表的字符串没有被包含进去,尽管它是上一个字符串的子集,这是因为字符串内部是连续存储的,根据‘\0’来确定字符串长度。而系统只有首地址信息,并没有长度信息,如果ch_ptr_4也相同的话,就只能代表相同的字符串了,因为系统无法进行字符串子集的切断,也不知道从哪里切断。 

综上所述:

1、单引号括起来的字符:实际上代表一个整数,整数值就是这个字符的ASCII值大小,如‘a’跟97(十进制)的含义是严格一致的,甚至可以互换。 www.zzzyk.com

2、双引号括起来的字符串:实际上代表一个指向无名数组起始字符的指针,这个无名数组被双引号之间的字符串和一个字符‘\0’初始化,而且这个数组内部数据是只读的,无法修改。

补充:软件开发 , C语言 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,