C语言指针基础 学习总结
目录
一.内存和地址
计算机内存是连续的存储空间,系统会为内存中每一个字节的空间分配唯一的编号,这个编号就是内存地址。
我们定义的普通变量(int、char、float等)都会占用对应的内存空间,变量的本质是内存中一块空间的别名,而变量的地址就是其占用内存空间的起始地址。地址是操作系统层面的数值标识,专门用于定位内存空间,也是指针所有操作的基础。
二.取地址操作符
& :是C语言中的取地址操作符,作用是取出变量在内存中的起始地址。
语法规则:&变量名,例如代码中&a 可以取出整型变量a的内存地址。
三.指针变量与解引用操作符
指针变量是专门用来存放内存地址的变量,区别于存放数值的普通变量。
定义语法:数据类型* 指针变量名。
例一:
int main()
{
int a = 10;
// &a :& 为取地址操作符,取出的是a的地址
int* p = &a;//p就是指针变量,指针变量就是存放地址的变量; int * :* 指p是指针变量,int表示为 p指向的对象为int类型
printf("%p\n", &a);
printf("%d\n", *p);//*是解引用操作符,*p的意思是通过p里边存放的地址,找到p指向的对象,也就是a,所以*p就是a;
printf("%p\n", p);//p 本身就是 &a,和第 1 行地址完全相等
//printf("%d\n", p);//p 是指针 int*(存地址,是长整型数值)% d 用于打印 int,指针宽度通常 4 / 8 字节,和 int 尺寸不一致
*p = 5;// 通过指针修改地址里的数据,等价于 a = 5;
printf("%d\n", *p);
printf("%d\n", a);
return 0;
}
代码运行结果:

四.指针变量的大小
例二:
/*结论
* 32位平台下地址是32个比特,指针变量大小就是4个字节;
* 64位平台下地址是64个比特,指针变量大小就是8个字节;
* 指针变量的大小和类型是无关的,只要是指针类型的变量,在相同平台下,大小都是相同的。
*/
/*这个代码是在64位平台下运行的*/
int main()
{
printf("%zu\n", sizeof(char*));//8
printf("%zu\n", sizeof(short*));//8
printf("%zu\n", sizeof(int*));//8
printf("%zu\n", sizeof(long*));//8
printf("%zu\n", sizeof(long long*));//8
printf("%zu\n", sizeof(float*));//8
printf("%zu\n", sizeof(double*));//8
return 0;
}
代码运行结果:

五.指针变量类型的意义
例三:
int main()
{
int a = 0x11223344;
//int* p = &a;
char* p = &a;
*p = 0;//指针的类型只决定解引用 *p 一次操作读写多少字节,
return 0;
}
这段代码主要是指针解引用时查看a的值在内存中的变化;若使用 int* 指针 接收a的地址并解引用赋值 *p = 0,会一次性修改4个字节,变量a的完整数值会变为0;若使用 char* 指针 接收a的地址并解引用赋值 *p = 0,仅会修改1个字节,只会改变变量a内存中最后一位字节的数据,其余高位字节数据保持不变。
例四:
//指针的类型决定了指针向前或者向后走一步多大(距离)
int main()
{
int a = 0x11223344;
int* pa = &a;
char* pc = &a;
printf("pa = %p\n", pa);
printf("pa + 1 = %p\n", pa + 1);
printf("pc = %p\n", pc);
printf("pc + 1 = %p\n", pc + 1);
return 0;
}
代码运行结果:

例五:
//void *指针
/*
* 在指针类型中有一种特殊的类型是void*类型的,可以理解为无具体类型的指针(或者叫泛型指针),这种类型的指针可以用来接受任意类型地址,
但也有局限性,void*类型的指针不能直接进行指针的+-整数和解引用的运算
void*类型指针到底有什么用呢?
一般void*类型的指针是使用在函数参数的部分,用来接收不同类型数据的地址,
这样的设计可以实现泛型编程效果。使得一个函数来处理多种类型的数据
*/
int main()
{
char a = 'w';
int b = 10;
//int* pa = &a;
void* pb1 = &a;
void* pb2 = &b;
return 0;
}
六.指针运算:指针+-整数,指针-指针,指针的关系运算符
例六:
//指针+-整数
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int* p = &arr[0];
int i = 0;
for (i = 0;i < 10;i++)
{
//printf("%d ",*(p+i));
printf("%d ", *p);
p++;
}
return 0;
}
代码运行结果:

在这个代码中指针向后/向前移动对应个数的元素,而非字节,步长由指针类型决定。
例七:
//指针 - 指针得到的是指针和指针之间的元素个数;前提,两个指针指向同一块空间;
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d\n", &arr[9] - &arr[0]);
return 0;
}
代码运行结果:

例八:
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int* p = arr;
while (p < &arr[10])
{
printf("%d ", *p);
p++;
}
return 0;
}
代码运行结果:

代码解释:数组遍历边界判断,例如 p < &arr[10],通过指针地址的大小关系,判断遍历是否结束,实现数组完整遍历。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)