C语言学习笔记(四)

(一、)初识指针

指针是内存的地址,就像我们的家庭住址一样,朋友要找到你,就是通过你的家庭住址找到你的,同理,计算机要拿到某块内存里的数据,就要通过这块内存的地址找到这块内存。

 

要了解指针,首先得了解内存,内存中的地址是怎么产生的。

在32位操作系统中,有32根地址线/数据线,每一根地址线通电后就会产生正电和负电,用数字信号表示就是 1 和 0 ,32根电线出来的数字信号就是有32个 0 和 1 组成的二进制序列,一共有2的32次方种,用这些二进制序列作为内存的编号,这些编号就是内存地址

初识C指针、结构体_内存

像图里的长方格,一个长方格我们说是一个内存单元,那在32位的机器上,一个内存单元是多大,下面我们就来剖析。

 

计算机的存储单位

由小到大:bit、Byte、Word、KB、MB、GB、TB、PB 

我们假设一个空间给一个比特位,机器为32位,最终就只能访问2^32个比特位的空间,我们可以用计算器计算2^32个比特位是多大的空间

初识C指针、结构体_内存_02初识C指针、结构体_结构体_03

一个字节(Byte) = 8个比特位(bit)

所以 :4,294,967,296 ÷ 8 = 536,870,912(Byte)

一KB = 1024 Byte

所以 :536,870,912 ÷ 1024 = 524,288(KB)

一MB = 1024 KB

所以 :524,288 ÷ 1024 = 512(MB)

一GB = 1024 MB

所以 :512 ÷ 1024 = 0.5(GB)

这可以看出,这么多的地址最终只能访问 0.5GB ,内存太小了,所以一块内存给一个比特位的大小是不合适的,若果换成 字节 为单位,那最终就可以访问 0.5GB × 8 = 4GB 的内存空间,最终在设计的时候就规定了,一块内存单元以一个字节为单位

int a = 10;

向内存申请了 4个字节 的空间来存放变量 a 

初识C指针、结构体_结构体_04

既然为 a 申请了空间,那 a 所在的那块内存空间自然就有地址了,这里就要介绍一个新的操作符:&(取地址符)

初识C指针、结构体_指针_05

有人会说,那我们可不可以把这个地址存起来呢?当然可以

我们需要用到一种变量来存放地址,这种变量被称为指针变量。(指针变量就是专门用来存放地址的变量)

//语法格式:
int a = 10;
int* p = &a;

p 是指针名;int* 是类型;即指针变量 p

初识C指针、结构体_学习笔记_06

代码中的 *p 与 int* 的 * 不是同一个 * ,int* 的 * 无实际意义,它是一种语法形式,而 *p的 * 是一个操作符(解引用操作符),又被称为:间接访问操作符,*p 对 p 进行解引用操作找到 p 所指向的对象 a ;*p = 20;的意思是通过 p 的地址找到 a ,把 a 的值改成 20 。

double d = 3.14;
double* pd = &d;
printf("%d\n",sizeof(pd));

运行结果:8

上述代码的运行结果也可能是 4,这取决于你的操作平台是32位还是64位,32位的平台编译结果是 4 ;64位平台编译的结果是 8

有一些人会认为变量 d 的类型是 double 类型(8、4个字节),pd 存的是 b 的地址,所以 bp 也是 8 或 4 个字节,其实不是的,一个地址的大小与操作平台有关。(相同的平台不管什么样的指针类型,大小都一样)我们用代码来演示

printf("%d\n",sizeof(char*));
printf("%d\n",sizeof(short*));
printf("%d\n",sizeof(int*));
printf("%d\n",sizeof(double*));

运行结果:
8(4)
8(4)
8(4)
8(4)

 

(二、)初识结构体

①、在现实生活中,一个人,他有名字、身高、年龄、身份证号...... ; 书有书名、作者、出版社、定价、书号......,像人、书这样的我们称为复杂对象。C语言为我们提供了结构体,用来描述复杂对象(我们自己创造出来的类型)。

struct:结构体关键字

struct Book
{
       char name[20];//书的名字
       short price;//书的价格
};

上述代码的意思是,创建一个结构体类型,花括号 {} 内是 Book 的属性(书名、价格......)

初识C指针、结构体_指针_07

利用结构体类型创建一个该类型的结构体变量 b

struct Book b = {"C语言程序设计",55};//创建了一本书,书名叫“C语言程序设计”,书的价格是 55 元

(.)这个点是一个操作符,b.name 表示拿出书 b 的成员 name

初识C指针、结构体_指针_08

b.price = 20;//表示修改书的价格,改为 20

 

②、试着利用前面学的指针,把 b 的地址取出来,这里就遇到问题了,指针的类型是什么

struct Book* pb = &b; //struct Book* 就是指针的类型

初识C指针、结构体_指针_09初识C指针、结构体_C语言_10

再介绍一个操作符(->)

printf("%d\n",pb -> price);
//pb 是一个地址,-> 表示 pb 指向 b 的成员 price

初识C指针、结构体_结构体_11

(.):结构体变量 . 成员

(->):结构体指针 -> 成员

 

拓展:那可不可可以用同样的方法修改书的名字呢?答案是不行,price 是一个变量,而 name 是一个数组,想要改变 name 的内容需要用到一个函数:strcpy()【字符串拷贝】,它是一个库函数,对应的头文件:<string.h>

若果像改价格一样去改name的内容会报错:

初识C指针、结构体_指针_12

初识C指针、结构体_学习笔记_13