一、引言:
日常开发中,我们经常遇到指针,同时指针也是C语言里极为重要的一个知识点,今天我们就来把它彻底弄明白。
二:正文
变量与变量值:
1 | //数据类型(int) 变量名(a) = 值(10) |
变量:变量是一个抽象概念,可以理解为允许存放数据的空间。当声明一个变量,计算机就会分配空间存放数据。变量可以通过变量名访问。
变量值:变量里面存储的数据即为变量值,变量值可以为数值、字符等类型。
指针:
指针:是一种变量,它的值是一个内存地址。(从三个方面分析指针:指针的类型、指针所指向的类型、指针的值)
指针类型:数据类型 *
,int *:整形数据类型的指针; char *: 字符数据类型的指针; void *:无数据类型的指针;等等…
取地址运算:&变量
,取得的结果是变量的首地址,是一个值(eg:x10db5640)。
取变量运算:*指针变量
,取得的结果是一个变量。
1.整形数据类型指针:
1 | - (void)testIntExample { |
解读:指针变量b的类型是:int *,指针变量b所指向的变量类型是int类型,b的值是一个地址:0x10db5641c。
2.字符数据类型指针:
1 | - (void)testCharExample { |
解读:char*类型指针 变量a 指向char类型变量blog,a的值是 变量blog的首地址0x10a951bfc。
3.指针与数组:
1 | - (void)testArrayExample { |
解读:
1)arr 表示arr[]数组的首地址
2)指针c - 指针a,能获取到两个指针之间有几个元素
3)指针变量加减一个整数,p(指针)(+/-)n(整数)计算方式为:指针地址 (+/-) n * 变量占有的字节数
4)sizeof的用法:
- 每种类型的数据在内存单元中占有的字节数是固定的,因此sizeof(arr)/sizeof(arr[0]) = 数组的元素的个数
- sizeof(arr):获取的是数组总共占有多少字节
- sizeof(arr[0]):获取的是数组中一个元素占有的字节数
5)数组变量保存的是地址,但数组变量中保存的地址是不能改变的,注意说的是指针地址不能变,但是指针指向的值是可以变的,因此数组变量应称为指针常量,可以改变数组中地址中存储的值。
OC 应用场景示例:
1 | //采用这种方式传参,可以获取到error的值 |
三、扩展
操作系统分为32位和64位,32位的最多只能支持4GB的内存,因为计算机底层并不使用十进制,使用的是二进制,32位的二进制只能支持4G个编号,这意味着操作系统只能为4GB的内存单元编号,因此32位的操作系统最多只能支持4GB的内存,多余的内存不会有编号,因此无法将数据存入这些内存单元中。
指针存储于栈区,不同数据类型的指针大小都相等,因为他们的值都是一个地址,并且长度也相同。32位操作系统中,指针大小是4个字节,64位操作系统中指针大小是8个字节。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20//下面代码是在64位操作系统演示
-(void)testGetPointerNum {
char *a = "myBlog";
int num1 = 1234325;
int *b = &num1;
double num2 = 3232.434;
double *c = &num2;
printf("char *类型指针变量a所占字节数:%ld",sizeof(a));
printf("int *类型指针变量b所占字节数:%ld",sizeof(b));
printf("double *类型指针变量c所占字节数:%ld",sizeof(c));
//打印结果
char *类型指针变量a所占字节数:8
int *类型指针变量b所占字节数:8
double *类型指针变量c所占字节数:8
}结构体数据类型变量的大小:
对于某个结构体类型而言,其存储单元大小,等于它当中占用空间最大的基础类型所占用的字节数量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31- (void)testStructExample {
struct Data1{
int a;
char b;
char c;
};
struct Data2{
char c;
int a;
char b;
};
struct Data1 p1;
p1.a = 1;
p1.b = 'd';
p1.c = 'f';
struct Data2 p2;
p2.a = 1;
p2.b = 'd';
p2.c = 'f';
printf("p1结构体占用的字节个数为:%ld",sizeof(p1));
printf("p2结构体占用的字节个数为:%ld",sizeof(p2));
//打印结果
p1结构体占用的字节个数为:8
p2结构体占用的字节个数为:12
}解读:
你可以看到,在 Data1 中,首先是 int 类型的 a 变量,占用了第一个存储单元,然后 b 和 c 占用了第二个存储单元的前两个字节。再看 Data2,由于 Data2 不同于 Data1 的字段顺序,b 占用了第一个存储单元的第一个字节,剩余的 3 个字节不够存放一个 int 类型变量的,所以按照上面我们讲的规则“当本存储单元不够安放的时候,就从下个存储单元的头部开始安放”, a 变量就单独占用了第二个存储单元,c 自己占用第三个存储单元的第一个字节。所以,虽然在数据表示上,Data1 和 Data2 是等价的,可 Data2 却占用了更多的存储空间,相比于 Data1 造成了 50% 的空间浪费。由此可见,在设计结构体的时候,不仅要设计新的结构体类型中所包含的数据字段,还需要关注各个字段之间的顺序排布。
32位操作系统内存与地址分布图:
64位操作系统常用数据类型占用的内存大小:
常用数据类型 占用内存大小(字节) char、unsigned char 1 bool 1 short、unsigned short 2 int、unsigned int 4 long、unsigned long 8 float 4 double 8 指针 8