zoukankan      html  css  js  c++  java
  • 字符与字符串

    在C语言中,利用单引号和双引号分别表示字符和字符串,字符串是指一串以NUL字节结尾的零个或多个字符。因为字符串通常存储在字符数组中,所以C语言中不存在字符串类型。但在使用时,如果不能真正理解两者的本质区别,有可能会出现一些诡异的现象。下面我将通过实验,进行详细分析:

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

    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’和‘’五个字符的连续只读空间的首地址;‘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函数接收的形参也就是字符串首地址。

           其实,常量字符串在系统内部是存储到“只读数据段”(涉及到编译原理和操作系统的知识,这里不再展开。只需要知道,程序执行是会分出好几个“区”,不同的“区”存储不同的内容,例如:堆、栈、bss、只读数据段等等。可以参考:【1.7】系统漫游——操作系统管理硬件相关内容)中的,这个跟数组是不一样的,数组里边的内容可以修改,但是常量字符串里边的内容不能修改。而且当定义两个相同的常量字符串时,系统内部会优化成一个,因为不可修改,所以就只存储了一次。这就是为什么ch_ptr_1和ch_ptr_3的值是一样的。但是,ch_ptr_4代表的字符串没有被包含进去,尽管它是上一个字符串的子集,这是因为字符串内部是连续存储的,根据‘’来确定字符串长度。而系统只有首地址信息,并没有长度信息,如果ch_ptr_4也相同的话,就只能代表相同的字符串了,因为系统无法进行字符串子集的切断,也不知道从哪里切断。  

    综上所述:

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

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

    3、程序中使用字符串常量会生成一个“指向字符的常量指针”,当一个字符串常量出现在一个表达式中时,表达式使用的值就是这些字符所存储的地址,而不是这些字符本身。因此,可以把字符串常量赋值给一个“指向字符的指针”,该指针指向这些字符所存储的地址。但是,不能把字符串常量赋值给一个字符数组,因为字符串常量的直接值是一个指针,而不是这些字符本身。

    注意:

           在C语言中,字符串就是一串以NUL字节结尾的字符序列。NUL虽是字符串的终结符,但它本身并不是字符串的一部分。NUL是ASCII字符集中 ‘’ 字符的名字,是1个字节域的全0;NULL是一个数值为0的指针,通常是占用4个字节域的全0。虽然它们都是0,甚至某些场合可以互换使用(不考虑数据宽度),但实际工程中还是要使用适当的常量,因为它可以传递给读者更多信息。

  • 相关阅读:
    java处理高并发高负载类网站的优化方法
    谈谈Memcached与Redis
    php中const与define的使用区别 详解
    ecshop添加模板与库文件
    ECShop 2.5.1 的结构图及各文件相应功能介绍
    Uva10972(RevolC FaeLoN)
    交叉染色法判断二分图
    边双联通问题求解(构造边双连通图)POJ3352(Road Construction)
    POI1999(仓库管理员)
    ZOJ1311(Network)
  • 原文地址:https://www.cnblogs.com/wgang171412/p/4950932.html
Copyright © 2011-2022 走看看