指针
指针的引入
- 一般把内存中的一个字节称为一个内存单元
- 为了正确地访问这些内存单元,必须为每个内存单元编上号。根据一个内存单元的编号即可准确地找到该内存单元。内存单元的编号也叫做地址,通常也把这个地址称为指针
- 如果在程序中定义了一个变量,在对程序进行编译或运行时,系统就会给这个变量分配内存单元,并确定它的内存地址(编号)
- 变量的地址就是变量的指针,存放变量地址的变量是指针变量
- 内存单元的指针和内存单元的内容是两个不同的概念。可以用一个通俗的例子来说明它们之间的关系。我们到银行去存取款时,银行工作人员将根据我们的帐号去找我们的存款单,找到之后在存单上写入存款、取款的金额。在这里,帐号就是存单的指针,存款数是存单的内容。对于一个内存单元来说,单元的地址即为指针,其中存放的数据才是该单元的内容。
指针变量的定义和使用
指针变量定义语法
数据类型 *指针变量名;
注意:
1、数据类型为C语言支持的所有数据类型
2、指针变量名遵循C语言变量的命名规则
举例:
int *p; //定义了一个指针变量p,简称指针p,p是变量, int *是类型
char* p2;
我们也认为指针是一种数据类型。
指针变量的赋值
1)指针变量的值代表这个指针指向了以这个值为首地址的那块内存空间
2)指针变量赋值为其他变量的地址
指针变量 = &变量名;
&:取地址运算符
int a = 10;
int *p = &a;
3)指针变量操作指向的内存空间
可以通过指针变量访问和修改所指向的内存空间中的内容
*:指针运算符(或称“间接访问” 运算)。
int a = 10;
int *p;
p = &a;
printf("*p: %d\n", *p);
*p = 100;
printf("*p: %d\n", *p);
4)指针变量同普通变量一样,定义后如果不进行初始化指针变量的值是不确定的
5)野指针
因为指针变量的值是不确定的,所以这个指针我们称之为“野指针”。
野指针的危害:因为指针指向的空间是不确定的,所以指针可能会操作到非法的内存空间,导致程序
运行奔溃。
int a = 100;
int *p;
*p = 1000;
/因为p没有初始化/赋值,所以p的值是不确定的,如果此时p的值恰好等于a的地址(p == &a), 那么p=1000将a的值修改为1000
如果p的值恰好是内存上一块只读的内存空间,*p = 1000将导致程序异常退出,你可能会看到程序运行报错(段错误/核心内容以转储)
*/
6)空指针
为了标志指针变量没有指向任何变量(空闲可用),C语言中,可以把NULL赋值给此指针,这样就标志
此指针为空指针。
int *p = NULL;
NULL是一个值为0的宏常量:
#define NULL ((void *)0)
注意:空指针的作用是防止指针变量变成野指针。如果用*访问空指针所指向的内存空间也会程序报
错
7)笔试题:嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置
一绝对地址为 0x67a9 的整型变量的值为 0xaa66
方法1:
int *ptr;
ptr = (int *)0x67a9; //在内存地址编号的前面加上(int *)将地址编号这个无符号整型数据强制转换为
//(int*)指针类型,这样赋值符号左值和右值的数据类型一致
*ptr = 0xaa66;
方法2:
*(int *)(0x67a9) = 0xaa55;
注意:在实际工作中我们一般很少会将一个确定的内存地址赋值给一个指针变量,因为程序员一般不
知道哪个内存地址是可用的!!!
不同类型指针变量之间的区别
1、int *p1 和 char *p2 的相同点是什么?
int x = 100;
int *p1 = &x;
char y = 'A';
char *p2 = &y;
相同点:
都是指针变量
都是用来保存一个内存地址编号
占用的内存空间大小一样
int *p1;
char *p2;
printf("%d %d\n", sizeof(p1), sizeof(p2));
我们发现p1和p2占用的内存空间为4/8,在32位机器上结果为4, 64位机器上结果为8。
思考:为什么指针变量占用的内存空间是 4 或者 8个字节呢?
因为指针变量保存的是一个内存地址的编号!
32位机器内存地址编号最大值为 2^32-1,可以用一个4字节的变量保存
64位机器内存地址编号最大值为 2^64-1,可以用一个8字节的变量保存
2、int *p1 和 char *p2 的不同点是什么?
首先我们应该知道:内存中存储的只是二进制而已
之所以有 int float char 等数据类型是程序员希望将存储在内存中的二进制当作某种数据类型来处理而已
int x = 65;
printf("%c\n", x);
int *p1的作用就是指针变量p1将他所指向的内存空间中的二进制当作int类型来处理
char *p2的作用就是指针变量p2将他所指向的内存空间中的二进制当作char类型来处理
3、p1++ 和 p2++的区别
int main() {
int x = 10;
int *p1 = &x;
char y = 'A';
char *p2 = &y;
printf("p1: %p, p2: %p\n", p1, p2);
p1++;
p2++;
printf("p1: %p, p2: %p\n", p1, p2);
return 0;
}
p1自增后和自增前值相差4
p2自增后和自增前值相差1
指针变量+n,不是指针往后偏移n个字节,而是指针变量往后偏移n个数据类型,例如:p1+3, 表示指针p1往后偏移3个int类型的数据,指针变量p1的值+12 (3*sizeof(int))
评论区