第三章 指针才是C语言的精髓(嵌入式Linux与物联网软件开发 C语言内核深度解析)

发布时间 2023-07-28 20:34:22作者: 領

这仅仅是读《嵌入式Linux与物联网软件开发:C语言内核深度解析》pdf的知识记录

 地址:指的都是某个字节的地址。比如int a 的空间大小有4个字节,每个字节都有一个地址(也就是有4个地址),但是只有首字节地址才能作为整个a空间的地址。也就是说,整个内存以1个字节为基本单位划分无数个地址,同时假设int是4个字节,那么首字节地址开始,往后再顺延3个字节,合计4个字节作为int的空间大小。

这就是变量空间的首字节地址,作为整个空间的地址。

 

int* p = &a;

p中只存放了a首字节地址,但是int说明了*p希望访问的空间有4个字节,所以从p所指a的第一个字节向后数3个字节空间,一共4个字节空间才是*p实际希望访问的完整空间。

 

再说一下类型:

类型实质上从两方面看,一方面空间大小,另一方面存储结构。

空间大小即不同的类型,在不同的机器上分配了不同的空间大小,比如32位操作系统,int类型分4个字节,double类型分8个字节等等

存储结构即声明了变量了,在类型开辟出了空间大小后,数据以什么结构存储。主要有两个存储结构方式:整数和浮点数

浮点数特殊一点,分成小数部分和指数部分存储,如果区分符号的话,第一位就是符号位,然后是小数部分,最后是指数部分

不同的类型,影响数据的读取解析方式,比如int a = 10; float* p = &a;假设编译器通过编译,那么对于*p解引用时,读取出来的数据就不是数值10.

 

地址可以让变量或者函数突破限制的作用域。

比如变量a在main函数中定义,其作用域限制在main函数内,当main函数调用fun函数时,将a的地址传给fun函数,那么fun函数就可以突破作用域限制修改a的内存数据。从作用域方面看,fun函数是看不见main函数中变量a的,但是地址突破了这层限制。至于突破函数,这就涉及到函数指针

 

 

 const修饰指针的三种形式

1、int const *p  等价于  const int* p

表示p指向的空间是“常量”,不能修改,但是p本身是可以修改的。

2、int* const p

表示指针变量p本身不能被修改,但是p所指向空间的内容可以被修改

3、int const* const p

表示p指向不能修改,p变量本身也不能修改。

 

const机制是通过编译器检查实现的,程序在真正运行的过程中,并不关心变量是不是const的,只要我们能够保证编译不出错,然后在程序运行的过程中去修改即可。

 int const a = 10;

int* p = &a;

*p = 100;

对这些变量加const修饰,只是利用编译器检查的方式实现的“伪”常量,并没有从根本上去关闭变量所在内存空间的写权限,所以只要能够骗过编译器,const修饰的变量的值可以修改的。

 

一维数组:

int buf[100] = {0};

buf有两层含义:1、表示数组名。2、等价于&buf[0]表示数组第一个元素的首地址,是一个常量值。

苦笑呀,当初学二维数组和指针结合运用时,这个数组名就是迟迟无法理解到位,迷惑性太强了,本质理解不到位真的容易稀里糊涂的。

&buf:也表示数组首地址

但是&buf和buf在指针运算时,意义差别很大。&buf + 1表示指针移动到数组最后一个元素的尾部地址,是整个数组空间大小+1,这个地址是有效的,但是不允许解引用。buf+1等价于&buf[0] +1 仅仅是数组的元素的空间大小+1。

 书中说int buf[5];  int* p = NULL;  p = &buf; 这个做法是不对的,但是仅仅不建议这样做而已,这个代码是正确的,之所以不提倡是因为p + 1 和&buf + 1,指针移动的空间大小不一致

p + 1 移动一个int类型空间大小,&buf + 1 则移动2个int类型大小。

 

强制类型转换:

普通变量的强制类型转换;指针变量的强制类型转换

 数据类型就是用于说明存储空间大小和数据存储结构的。

 

普通变量数据类型转换的实质是什么?

实质就是将数据的空间大小和数据的存储结构转变后,存入另一个变量空间,所以转换时可能会导致空间大小和数据存储结构的变化。同时普通变量存在隐式类型转换和显示类型转换的区别。比如赋值符号,int a = 10;  float b = a;  实质是将a进行强制类型转换(原变量空间不变,变量a的空间还是int型),第二个隐式类型转换就是函数的返回值。

 

指针强制类型转换:(明确一点,指针类型转换必须显示强制类型转换)

指针强制类型转换分成两种:

1、对指向空间的强制类型转换

int *a=NULL;

float *b = (float)*a;

指向空间的强制类型转换与普通变量的强制类型转换一样的。

2、对指针变量本身的强制类型转换

int a;

int *pa = &a;

float *pb = NULL;

pb = (float *)pa; 或者pb = (float *)&a;

将指针变量pa存放的地址转换为(float *)后,赋值给了pb。pb里面的地址与pa里面的地址值是相等的,但是pa放的是(int *),而pb放的是(float *)型。虽然它们都指向同一个空间a,但不同的是,当使用*pb去使用变量空间a的时候,会以float型的空间大小和数据存储结构使用a空间的值。因此总结起来就是,指针变量类型本身的强制转换,改变的是对其指向空间的引用方式。

 

 END