C程序设计——基本变量类型(指针杂谈)

瞎聊

本文后面的内容,可以暂时看不懂,以后如果从事这一行,慢慢会理解,但是这句话要记住:如果 piInt 是一个指向整型的指针变量,那么  *piInt 就是一个整型变量;类似的,如果pcChar是一个指向字符型的指针变量,那么 *pcChar 就是一个字符型的变量;……

其实这部分内容,也许放在 C程序设计——基本变量类型(指针0)的前面更合适,但是思来想去,还是先把指针讲个差不多,再讲这个。

我希望大家记住这句话,将来再慢慢理解:C语言把计算机所有的外设,都抽象为变量。

当你用C语言访问显示器、鼠标、键盘时,最终访问的是一个一个的变量。当然有些变量,被用函数给封装起来,看起来好像是通过调用函数,来控制屏幕显示、获取鼠标状态。

变量

当你入学报名的时候,如果你住校,学校会给你分配一个宿舍,比如你们学校的第14号楼,3层有一个编号360的宿舍刚搞还有一个床位,然后老师大笔一挥,你就住这间了。我们把你住的这个宿舍用一串数字来表示就是: 14360,14代表第14号楼,360代表3层第60号房间。在你们学校,一说14360,就能唯一的标识你们宿舍,你问任何一个同学,都可以告诉你怎么去14号楼,然后上3层找60号宿舍。

计算机的也是一样的,所有外设,包括内存、硬盘、鼠标等等,都分配了很多地址,就好像前面讲了每6个床位分配一个宿舍号,计算机也类似,按照目前的标准,每8位二进制数分配一个地址,通常这8位二进制数,被看做一个整体,叫做一个字节。

C语言下,当你定义一个变量,像下面这样:

    int iInt ;

编译器生成代码的时候,会按照既定的规则(算法)给变量 iInt 分配一片4字节(32bit)连续的内存空间,前面我说了,计算机给每个字节都分配的地址,这一个整形变量占连续4个字节,理论上就有四个地址,按那个算呢?C语言规定,地址中最小的一个,作为整形变量的地址。强调一下,当你定义一个变量是,无论这个变量占多少字节,计算机分配内存时,一定是分配一片地址连续的空间,来存储这个变量。

比如计算机给上述代码中的  iInt 分配了四个字节的空间,地址分别是 4、5、6、7,那么当你给 iInt 取地址(&iInt )时,得到地址将是4。比如下面这段代码:

int main(void)
{
    int iInt ;
    int *piInt ; // 定义指向整形的指针变量
    piInt = &iInt; // 将iInt 的地址,赋值给 piInt

    iInt = 100;

    printf("piInt %d\r\n", piInt); // 打印指针变量的值
    printf("&iInt %d\r\n", &iInt); // 打印 iInt 的地址值
    printf("iInt %d\r\n", iInt); // 打印 iInt 的值
}

编译后运行结果如下:

我们从打印结果上可以看到变量 iInt 的值是 100,变量 iInt 的地址值是: 6422036。按照前面的讲解,变量 iInt 占4个字节,每个字节都有地址,其中最小的一个是 6422036,另外三个字节的地址就是 6422037、6422038、6422039 。

指针变量,也是变量

我们还看这段代码(不用比较了,就是从上面复制、粘贴过来的)

int main(void)
{
    int iInt ;
    int *piInt ; // 定义指向整形的指针变量
    piInt = &iInt; // 将iInt 的地址,赋值给 piInt

    iInt = 100;

    printf("piInt %d\r\n", piInt); // 打印指针变量的值
    printf("&iInt %d\r\n", &iInt); // 打印 iInt 的地址值
    printf("iInt %d\r\n", iInt); // 打印 iInt 的值
}

piInt 是一个指针变量,它首先是一个变量,所以计算机也会给它分配地址连续的几个字节(有些计算机是4个字节,有些计算机是8个字节),所以从分配空间的角度,piInt 和 iInt,没有本质区别,如果硬要找区别,那就是分配的空间不一样,可能数量也不一样(当然数量也有可能一样)。既然 piInt 是变量,那就可以给它赋值,比如下面这样:

    piInt = &iInt; // 将iInt 的地址,赋值给 piInt

表示把 iInt的地址,赋值给 piInt。根据运行结果  iInt 的地址其实就是一个数字6422036 ,如果我们能未卜先知,这里直接把 6422036赋值给 piInt,效果是一样的:

    piInt = 6422036; // 如果能未卜先知,就可以用 6422036 来代替&iInt

获取指针指向的值

先明确一个概念,比如我定义一个整形变量 iInt,计算机给它分配的地址是 6422036,然后给 iInt 赋值 100,我们就说地址 6422036 指向的值是100,如果我们改变了 iInt 为 200,则我们说地址 6422036 指向的值是200 。

我们如果定义了一个指针变量  piInt,然后给它赋值 为 iInt 的地址(&iInt),给 iInt 赋值 100,我们就说指针变量 piInt 指向的值是100,如果我们改变了 iInt 为 200,则我们说指针变量 piInt 指向的值是200 。

那么我们如何获取指针 piInt 指向的值呢?像下面这样:

    *piInt ; 

请寻找下面两行的不同:

    int *piInt ; // 定义一个指针变量
    *piInt ; // 获取 piInt 指向的值

*piInt 左面有类型名,就是定义指针变量。没有类型名,就是获取指向的值。

指针指向的值还可以改变,像下面这样:

    *piInt = 200; // 改变 piInt 指向的值,使之为200

int main(void)
{
    int iInt ;
    int iValue ;
    int *piInt ; // 定义指向整形的指针变量
    piInt = &iInt; // 将iInt 的地址,赋值给 piInt

    iValue = *piInt ; // 获取 piInt 指向的值,并赋值给 iValue
    *piInt = 200; // 改变 piInt 指向的值,使之为200
}

指针变量类型的意义

我们现在知道,定义指针的时候,要声明指针指向什么类型的数据,比如下面这些:

int main(void)
{
    char *pcChar ; // 指向字符型变量的指针
    short int *psShort ; // 指向短整形变量的指针
    int *piInt ; // 指向整形变量的指针
    long int *plLong ; // 指向长正向变量的指针
    long long *pllLongLong; // 指向超长整型变量的指针
 
    unsigned char *pcChar ; // 指向无符号字符型变量的指针
    unsigned short int *psShort ; // 指向无符号短整型变量的指针
    unsigned int *piInt ; // 指向无符号整形变量的指针
    unsigned long int *plLong ; // 指向无符号长整型变量的指针
    unsigned long long *pllLongLong; // 指向无符号超长整形变量的指针
 
    float *pFloat ; // 指向单精度浮点数的指针
    double *pDouble ; // 指向双精度浮点数的指针
}

我再本节最开头说了,再强调一次:如果 piInt 是一个指向整型的指针变量,那么  *piInt 就是一个整型变量;类似的,如果pcChar是一个指向字符型的指针变量,那么 *pcChar 就是一个字符型的变量;……

因为不同类型的变量,计算机给分配的空间是不一样的,比如 char型就是1个字节,short int 就是2个字节 ……,指针变量指定的类型, 获取指针指向的值时,才能知道该取几个字节的数据。

指针变量 + 1 

先看下面这行代码:

    piInt = &iInt; // 将iInt 的地址,赋值给 piInt

经过前面的讲解,我们知道 piInt 中存放的地址,是  iInt 的4个字节中,地址最小的那个字节的。piInt 逻辑上,代表的是 4个字节的地址,因此 piInt + 1 ,逻辑上代表 iInt 后面的那个 整型数据,因此   piInt = piInt + 1 ,piInt的值加了4 。

同样的下面代码定义的指针中:

int main(void)
{
    char *pcChar ; // 指向字符型变量的指针
    short int *psShort ; // 指向短整形变量的指针
    int *piInt ; // 指向整形变量的指针
    long int *plLong ; // 指向长正向变量的指针
    long long *pllLongLong; // 指向超长整型变量的指针
 
    unsigned char *pcChar ; // 指向无符号字符型变量的指针
    unsigned short int *psShort ; // 指向无符号短整型变量的指针
    unsigned int *piInt ; // 指向无符号整形变量的指针
    unsigned long int *plLong ; // 指向无符号长整型变量的指针
    unsigned long long *pllLongLong; // 指向无符号超长整形变量的指针
 
    float *pFloat ; // 指向单精度浮点数的指针
    double *pDouble ; // 指向双精度浮点数的指针
}

如果 pcChar=  pcChar + 1,pcChar 加了 1;

如果 psShort = psShort + 1,psShort 加了2;

……

 

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十三香炖猪肉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值