关于指针类型和指针类型转换的理解

Posted chanabi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于指针类型和指针类型转换的理解相关的知识,希望对你有一定的参考价值。

前几天在判断  值相同的两个指针所指向的变量的值可以不同  这句话时,发现自己对指针类型一些概念仅仅是记住了结论。于是以理解这句话为出发点,查阅了一些资料,用这篇博客来记录一下一些与指针类型和指针类型转化相关的知识。

 

 一些用到的

在开始之前,先来复习一些下面会用到的知识。

1.内存地址,字节,位

  位(bit)是电子计算机中最小的数据单位。每一位的状态只能是0或1。

  字节(Byte)是用于计量存储容量的一种单位,每一个字节由8位组成(1Byte = 8bit)。

  内存地址是在一片内存中,每个一个字节的编号。

  他们在内存中的关系就好像,内存是一栋大楼,字节的大楼中的每一层,地址是楼层编号,位是每一层中的房间,每一层有8个房间。

   

技术分享图片

 

2.变量的内存

  编译器会根据变量的类型,在内存中申请一块空间。不同的编译环境中申请到的空间也不同。例如32位与64位中 int 类型申请到4字节的空间,可以理解为编译器申请了几层楼,作为”办公区域“。

3.指针变量

 

  指针是指程序数据在内存中的地址。在c语言当中,允许用一个变量来存放指针,这种变量称为指针变量。

 

 

指针变量只知道楼层号?

   存储在指针变量的值,是计算机中的内存地址,也就是“楼层号”。我们在写程序时候,想要让指针指向一个变量,会将一个变量的地址赋给一个指针:

  int a;
  int *p;
  p = &a;
  printf("%p %d ",p,*p);

  

  ”&“操作符取出了变量 a 在内存空间中的首地址(”办公区域“中第一层的编号),而后通过 “ * ”  操作符取出首地址所在内存空间的数据。

  在前面我们提到,存储变量的区域,是“几层楼”组合起来的空间。而指针变量在只知道首地址(第一层楼层号)的情况下,就能找到整个内存空间(工作区域)。它是怎么做到的?我们先来看看指针变量的声明。

 

  我们在声明一个指针变量的时候,会根据它将要指向的变量类型,声明对应的类型,例如:

    int a;
    long b;
    char c;

    int *pa = &a;
    long *pb = &b;
    char *pc = &c;

 

  不同类型指针的区别:

  不管是指向什么类型的指针变量,所存的值都是地址,在计算机都是一个int类型的值。到底声明不同类型的指针变量的背后是什么?答案是规定指针在内存中移动的最小字节数。

  例如定义“int *pa = &a”,当需要通过pa读取变量a的值时,由于int类型变量在内存中占4个字节,指针在内存中,会从首地址指向的字节开始移动,读取4个字节的内存数据。同理,当声明类型是char时,由于short类型变量占2个字节,指针从首地址指向的字节开始移动,读取2个字节的内存数据。我们通过声明指针所要指向的类型,告诉指针要从“工作区第一层楼”开始,往上走几层“楼”,来确定变量对应的内存空间。

  因此,指针变量不仅仅知道“楼层号”,它能根据对应的变量指向类型,找到对应变量的内存空间。

 

值相同的两个指针所指向的变量的值可以不同?

  从以上我们可以总结,指针变量指向的是某个内存空间的首地址。值相同的两个指针变量指向的首地址相同,但是如果指针变量的类型不同,指针移动的字节数量不同,就可能读取出不同的数据。因此“值相同的两个指针所指向的变量的值可以不同 ”。即用两个不同类型的指针指向同一个首地址,对应变量的值不同。

  而要实现不同类型指针变量指向同一个地址,需要使用指针类型强制转换

1     short a = 1;
2     short *p1 = &a;
3     int *p2 = (int *)p1;
4     printf("%d %d",*p1,*p2);

   以上例子将一个每次移动读取2字节内存的 short 类型指针变量,转化为一个每次读取4字节内存的int型指针变量。p1,p2从相同的地址开始读取,但是读取不同的位数.

   接下来,我们通过指针强制类型转换,用值相同的指针,取出不同变量的值。

   

 1 #include <stdio.h>
 2 int main()
 3 {
 4     short c[2];               //等价于申请2个连续的内存空间,每个空间2字节 
 5     c[0] = 1;                //为第一个short空间赋值为1 
 6     c[1] = 1;                //为第二个short空间赋值为1 
 7     short *p1 = c;            //p1指向c[]首地址 
 8     int *p2 = (int *)p1;      //p2指向c[]首地址,并强制转换类型为 int 
 9 
10     printf("p1指向:%p
p2指向:%p
",p1,p2);      
11     printf("p1取出:%d
p2取出:%d
",*p1,*p2);
12     return 0;
13 }
14         

  对应结果为: 

    p1指向:000000000062FE30
    p2指向:000000000062FE30
    p1取出:1
    p2取出:65537

  技术分享图片

    

    根据二进制转换得,10000000000000001 为 65537。由此可验证强制转换前指针读取2字节,转化后4字节。同时也证明值相同的两个指针所指向的变量的值可以不同





以上是关于关于指针类型和指针类型转换的理解的主要内容,如果未能解决你的问题,请参考以下文章

关于强制类型转换(c语言)

深入理解指针类型间的转换

指针强制类型转换的理解

delphi 怎么把任意类型的指针转换成integer??一个关于tag的问题,

C++中指针类型转换的解释

关于函数指针的注意事项