首页 /  技术专区  /  C 宽屏模式 >

指针类型

1 所有指针变量的大小(宽度)都是固定的


1.1 为什么指针变量的大小都是一样的?

因为存储空间所有字节的指针都是相同“宽度”的,

比如,如果地址宽度是32位的话,那么每个字节的地址都是32位的。

比如,如果地址宽度是64位的话,那么每个字节的地址都是64位的。


既然所有字节的指针宽度都是一样的,因此所有指针类型的宽度也都是一样的,

int *
float *
struct Student *
double *

以上所有指针类型所规定的“宽度”是相同的,使用这些类型所定义的指针变量,其宽度也都是一样的。

指针变量是用来存放指针的,既然所有指针的宽度都是一样,那么存放指针的指针变量的宽度必然也是一样。

测试自己Linux和Windows下地址的宽度。

#include <stdio.h>

int main(void)
{
    int *p = NULL;
    printf("%d\n", sizeof(p)); //或者sizeof(int *))
    return 0;
}

我这边的情况:

1)windows

        地址宽度为32位(4字节)。

2)Linux

        地址宽度为64位(8字节)。

2 指针类型

1.1 指针的类型长什么样子

指针类型由基本类型 + *组成。

int *
float *
...

1.2 定义指针变量

定义时,在指针类型*的后面加上变量名即可。

int *p;

int **p;

1.3 指针类型中基本类型的作用

在前面就说过,int */struct student *等指针类型的宽度都是固定的,既然“宽度”固定的,那么指针类型中区分int、struct Student等基本类型有什么意义呢?

其实意义就在于,正是由于有int、struct Student等基本类型,所以对指针进行解引用时,才能正确的解释指针所指向的空间,比如:

int a = 100;
int *p = &a;

*p = 10000;

a的空间有4个字节,访问a的空间,只需要知道如下三件事:

(1)知道a第一个字节的地址,即a指针

(2)知道访问哪一个字节时结束

(3)知道空间的存储结构

*p解引用时,很显然是能够知道以上三件事的

(1)p中放的就是a指针

(2)int *中的基本类型为int,所以访问指针所指向的空间时,需要访问的空间大小为四个字节

(3)int *中的int也指明了,在访问指针所指向的空间时,按照整形的存储结构来解析的

总之对指针进行解引用时,指针类型中基本类型的作用,就是用于决定对所指向空间的解释方式。

指针类型都是固定宽度的,指针类型中的基本类型,与指针本身宽度无关,只与指针所指向空间的宽度有关。

1.4 对指针进行强制转换

前面说过=两边的类型必须一致,自然也包括指针类型。

(1)天然的一致

int a = 100;
int *p = &a;

&a:a的指针,指针的数据类型为int *

p:指针变量,类型也为int *

(2)通过“强制转换”来保证类型一致

double a = 100.6;

float *p = &a;            //隐式强制转换
float *p = (float *)&a;   //显式强制转换

(3)强制转换时做了什么

强制转换时,&a本身的值不改变,变的只是对指针所指向空间的“解释方式”。

double a = 100.6;
float *p = (float *)&a;

*p = 12.6;

&a:指针类型为double *

p:float *

两边的类型不一致,因此需要做强制转换。

直接使用&a访问所指向的空间时,

*(&a) = 200.02;

是按照double类型来解释的,但是将指针强制转换为float *后,再使用该指针去访问时,就会以float的类型去访问。

struct Student
{
    int num;  
    char name; 
    float score;
};

struct Teacher
{
    char name; 
    int num; 
};

struct Student stu = {123, "zhangsan", 87.6};
			
struct Teacher *stup = (struct Teacher *)&stu; //&stu为结构体指针,即第一个字节的地址

指针类型被强转为struct Teacher *后,通过stup解引用访问stu的空间时,则会以struct Teacher类型来解析。

指针(地址)就是一个数,至于这个数应该如何解释,就看这个数的类型,比如:

int a = 0;

· &a:为int *的指针,解引用时按照整形来解释&a所指向的空间。

· (int)&a:此时这个数就只是一个普通的整形数,此时不再是一个指针,不能进行解引用

· (void *)&a:为void *指针,这是一个空类型指针

空类型指针仅仅就是一个指针,不能被直接解引用,如果要解引用的话,必须将指针强制转换为int *、float *等具体指针类型,然后才能进行解引用,后面还会再次介绍void *。

· (struct student *)&a:结构体指针,解引用时会按照student student结构来解释。

a的合法空间只有4个字节,但是由于struct student类型大小>4个字节,所以按照struct student进行解引用访问时,所访问的空间会超过4个字节,这样会访问到其它的非法空间。

所以在实际编程中进行强制转换时,我们必须慎重使用强制转换。



上一篇: 指针概述

头像
0/200
图片验证码