编程语言【C/C++】|C语言深度解剖——读书笔记-7、指针和数组

第四章指针和数组


4.1.1指针
指针示意图
编程语言【C/C++】|C语言深度解剖——读书笔记-7、指针和数组
文章图片


一个基本的数据类型加上“ * ”号就构成了一个指针类型的模子。这个模子的大小是一定的,与“ * ”前面的数据类型无关;“ * ”号前面的数据类型只说明指针所指向的内存数据的类型;
所以32位系统下,不管什么样的指针类型,其大小都为4个字节。可用sizeof(void *)来进行验证。

4.1.3int *p =NULL和 *p =NULL有什么区别


第一段代码: int*p=NULL;
这时候我们通过编译器查看p的值为0x00000000。

第二段代码:
int*p;
*p =NULL;
我们可以在编译器上调试这两行代码。
第一行代码,定义了一个指针变量p,其指向的内存里面保存的是int 类型的数据;
(但这时变量p本身的值是多少不得而知,这时变量p保存的有可能是一个非法的地址,由于p指向的内存可能是非法的,所以调试的时候编译器可能会报告一个内存访问错误。我们可以把上面的代码进行改写,使p指向一块合法的内存)。


inti=10;
int*p= &i;
*p =NULL;
在编译器上调试一下会发现p指向的内存由原来的10变成了0;而p本身的值,即内存地址并没有改变;
也就是 int *p =NULL 是初始化指针,把*p的值设置为0x0000 0000,这个过程在编译的时候进行;
而 *p = NULL; 是将p指向的值变为0。
[ 注意:NULL就是NULL,它被宏定义为0 ]

4.1.4.如何将数值存储到指定的内存地址



假设需要往内存地址0x12ff7c上存入一个整型数0x100,那么怎么才能做到呢?可以通过指针指向的内存地址写入数据,那么这个内存地址ox12ff7c其本质不就是一个指针嘛,所以我们用下面的方法:

int*p = (int *) 0x12ff7c;

*p = 0x100;

需要注意:将地址0x12ff7c赋值给指针变量p的时候,必须强制转换;

另外一种方法:*(int *)ox12ff7c = 0x100;

即:先将地址0x12ff7c强制转换,告诉编译器这个地址将存储一个int类型的数据,然后通过 “ * ”像这块内存写入一个数据。


跨过指针,直接去访问一块内存:

只要你能保证这个地址是有效的 ,就可以这样去访问一个地址的内存*((unsigned int *)(0x0022ff4c))=10; 但是前提是 0x0022ff4c是有效地址。对于不同的编译器这样的用法还不一样,一些严格的编译器,当你定义一个指针,把这个指针赋值为一个这样的地址的时候,当检测到地址无效,编译的时候就会报错!!!如果一些不太严格的编译器,不管地址有效无效都会编译通过,但是对于无效地址,当你访问这块地址的时候,程序就会运行停止!






4.2数组

4.2.1inta[5]; 数组示意图

定义一个数组a时,编译器根据指定的元素个数和元素类型分配确定大小的一块内存(大小为:元素类型大小*元素个数),并把这块内存的名字命名为a。名字a一旦与这块内存匹配就不能被改变。

看下第一章讲解sizeof关键字时的问题:

sizeof(a)的值 sizeof( int )*5,32位系统下为20

sizeof(a[0])的值 sizeof (int),32位系统下为4

sizeof (a[5])的值在32位系统下为4,并没有出错,为什么呢?

解析:关键字sizeof求值是在编译的时候,虽然并不存在a[5]这个元素,但是这里并没有去真正访问a[5],而是仅仅根据数组类型来确定其值。因此这里不会出错;


4.2.2&a[0]和&a的区别


首先看下&a[0]和&a的区别到底有什么?a[0]是一个元素,a是整个数组,虽然&a[0]和&a值一样,但其值意义不一样。

&a[0] 表示:数组首元素的首地址;&a 表示:数组的首地址;


4.2.3数组名 a 作为左值和右值的区别




x=y

左值:编译器认为x的含义是x代表地址,这个地址只有编译器才知道,编译在一个特定的区域保存这个地址,我们完全不必考虑这个地址保存在哪。

右值:编译器认为y的含义是y所代表的地址里面的内容,这个内容是什么,只有到运行时才知道。

a 作为右值时意义:与&a[0]是一样的,代表的是数组首元素的首地址,而不是数组的首地址;【注意的是:这仅仅是代表,并没有一个地方来存存储这个地址,也就是说编译器并没有为数组a分配一块内存来存储其地址,这一点就与指针有很大差别】

a不能作为左值!编译器会认为数组名作为左值代表的意思是a的首元素的首地址,但是这个地址开始的一块内存是一个总体,我们只能访问数组的某个元素,而无法把数组当一个总体进行访问。

【编程语言【C/C++】|C语言深度解剖——读书笔记-7、指针和数组】所以我们可以把a[i]当左值,而无法把a当左值,其实我们完全可以把a当做一个普通的变量来看,只不过这个变量内部分为很多小块,只能通过分别访问这些小块来达到访问整个变量a的目的。

    推荐阅读