本文主要是介绍指针 C programming,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
”许久未曾提笔,心湖泛起涟漪。“
概念:指针是一种将另一个变量的内存地址存储 为其值的变量。
int a = 1;
printf("%d", a); // 打印的是 变量a 的 存储地址 位置上 存储的 值
printf("%p", (void*)&a); // 打印的是 变量a 本身的 地址值
int *p = &a; // & 符号是取地址符 所以这行代码的意思是取变量a的本身存储地址 给 指针p存储
printf("%p", (void*)&p); // &p 就代表是指针p的本身存储地址
printf("%p", (void*)p); // 打印的是 指针p指向的地址 (即变量a的地址)
综上所述:
1.当我们定义变量a的时候,相当于告诉编译器,变量a需要一个地址代替,且里面的存储值是1
2.当我们用指针p指向变量a时,是说需要新申请一个地址(即&p),然后在这个地址下存储变量a的地址
栗子1
void exchange_value(int a, int b) { // 形参a、b (这里会临时创建形参变量a、b出来,用来储存传入的实参a1、b1的值,本函数结束后,会释放着临时的所有东西)a = a + b;b = a - b;a = a - b;// 所以,这函数只是交换了形参a、b的值,而不是传入的实参的a1、b1的值
}
void main(void) {int a1 = 1, b1 = 2;exchange(a1, b1); // 这就是玩指针的新手常犯的错误(这根本不会交换变量a、b的值,原因详见exchange_value函数内)
}
所以,我们如果想要交换a1、b1的值,就需要使用指针
栗子2:一级指针
void exchange_address_value(int* a, int* b) { // 临时创建形参a,b指针,用于存储传入的实参指针的指向地址int* temp = *a;*b = *a;*a = *temp;
}
void main(void) {int a1 = 1, b1 = 2;int* a = &a1, b = &b1;exchange_address_value(a, b);
}
其余更多,请详看以下内容
/*本篇章主要介绍指针,指针是C语言中一个非常重要的概念,也是C语言中一个比较难理解的概念。玩转 -> 指针重点:1.传递给函数的参数都是值的副本 2.指针解引用既可以提取值,也可以修改值从交换值中学习指针无论是几级指针 只要*写全了 都是既是地址改变值,又是提取值(数*号,少了几个就少几级) 简单说 定义的 int ****ptr; 是4级指针 那么 *ptr 就是3级指针,**ptr 就是2级指针,***ptr 就是1级指针,****ptr 就是0级指针,也就是变量。
*/
/*
参数传递的两种情况值传递:开一个副本,存储值指针传递:同样是开一个副本指针 用于存储传入指针指向的地址
变量名 也会 与一个地址绑定
不看定义的时候是几级指针,只看传入的时候是几级指针int a = 1, b = 2;
int *a1 = &a, *b1 = &b; // 一级指针是指向变量地址的指针
int **a2 = &a1, **b2 = &b1; // 二级指针是指向指针本身地址的指针 所以 &a1 == a2,&b1 == b2
int ***a3 = &a2, ***b3 = &b2; // 三级指针是指向指针本身地址的指针 所以 &a2 == a3,&b2 == b3高级指针 加* 与低级指针 --> 等效 *a3 与 a2 完全等效**a3 与 a1 完全等效***a3 与 a 完全等效
0级别指针 可以说就是变量本身
变量名和内存地址是如何对应的? 编译后的机器代码中,变量名已经被替换为其对应的内存地址*/
#include <stdio.h>typedef unsigned int uint;
// 虽然传入的是形参 但是都是指针 同一个地址
void exchange(uint *a, uint *b)
{printf("%p %p\n", (void *)a, (void *)b); // 0x7ffeedd7c8d0 0x7ffeedd7c8d4uint temp = *a; // *a表示解引用,即获取指针a指向的变量的值(同时是从地址上获取的)*a = *b;*b = temp;
}void exchange2(uint **a, uint **b) // 一直找到最底层的变量
{uint temp = **a;**a = **b;**b = temp;
}
// 这里 a1 和 b1 的 地址交换了
void exchange2_1(uint **a, uint **b) // 这里是调换指针的地址
{uint *temp = *a; *a = *b;*b = temp;
}
// 同级别不解引用 就是局部变量(传递给函数的参数都是值的副本)
void exchange2_2(uint **a, uint **b) // 这里调换二级指针的地址
{printf("%p %p\n", (void *)a, (void *)b); // 0x7ffeedd7c8d4 0x7ffeedd7c8d8uint **temp = a; // 需要提别敏感 这里是改变的 副本的地址a = b;b = temp;printf("%p %p\n", (void *)a, (void *)b); // 0x7ffeedd7c8d4 0x7ffeedd7c8d8//printf("%u %u\n", **a, **b); // 1 2 交换了 成 2 1
}
// 将二级指针 本身的地址 给调换了
void exchange2_3(uint ***a, uint ***b) // 这里调换三级指针的地址
{uint temp = *a; // 指向指针的指针 看*是反的看 原本三级,加一个*,就是二级指针的地址*a = *b;*b = temp;
}// 看清函数参数 需要几级指针
int main(void)
{uint a = 1, b = 2;uint *a1 = &a, *b1 = &b;uint **a2 = &a1, **b2 = &b1;printf("%p %p\n", (void *)a1, (void *)b1); //printf("%p %p\n", &a, &b); // exchange(a1, b1);// printf("%p %p\n", (void *)a1, (void *)b1); // 存储指针的地址没有变//printf("%p %p\n", &a, &b); // 存储变量a 变量b 的地址没有变//printf("%p %p\n", (void *)&*a1, (void *)&*b1); // 就是变量a 变量b 的地址// printf("%u %u\n", a, b); // 2 1 交换了 变得是地址内存储的值//exchange(*a2, *b2); // **a2是二级指针 *a2 是 一级指针 // exchange2(a2, b2);// printf("%u %u\n", a, b); // 2 1 交换了 变得是地址内存储的值// printf("%u %u\n", **a2, **b2); // 2 1 交换了 变得是地址内存储的值// printf("%u %u\n", *a1, *b1); // 2 1 交换了 变得是地址内存储的值// exchange2(a2, b2); // 这样即可 别写什么解引用 看清函数需要的参数/***a2 = a1 是定义的二级指针 *a2 是一级指针,a1 是一级指针,所以 *a2 = a1 是将一级指针a1赋值给一级指针 *a2*/// printf("%p %p\n", (void *)a1, (void *)b1); // 0x7ffeedd7c8cc 0x7ffeedd7c8d0// exchange2_1(a2, b2);// printf("%u %u\n", *a1, *b1); // 2 1 交换了 这里是调换了一级指针a1、b1的存储地址 (不是存储的值,是指针本身的地址)// printf("%p %p\n", (void *)a1, (void *)b1); // 0x7ffeedd7c8d0 0x7ffeedd7c8cc// printf("%u %u\n", a, b); // 1 2 交换了 这里是调换了一级指针a1、b1的存储地址 (不是存储的值,是指针本身的地址)// printf("%p %p\n", (void *)a2, (void *)b2); // 0x7ffeedd7c8d4 0x7ffeedd7c8d8// exchange2_2(a2, b2);// printf("%u %u\n", **a2, **b2); // 依旧是 1 2 这里改变的只是 二级指针本身的地址值(且还是改变的副本地址值)// printf("%p %p\n", (void *)a2, (void *)b2); // 0x7ffeedd7c8d4 0x7ffeedd7c8d8// uint ***a3 = &a2, ***b3 = &b2;// exchange2_3(a3, b3);// printf("%u %u\n", ***a3, ***b3); // 2 1 交换了 只是改变了 二级指针的地址值 // printf("%u %u\n", **a2, **b2);// 这里能看出来 再多级指针 一直追 也只是改变地址 真实的最原始的变量值并没有改变//printf("%u %u\n", a, b);//int i = 3;//int *p = &i; // &取地址符 (取得对方存储在内存的地址) 内存 不等于 寄存器 寄存器/*寄存器没有内存地址。寄存器是处理器内部的一种高速存储单元,用于存放临时的数据和指令执行过程中的中间结果。寄存器:位于 CPU 内部,是处理器的一部分。非常快 个位数纳秒级别 很小,通常只有几十个字节 用于临时存储数据和地址(想查看地址可以通过调试工具,编码人员无法直接获取寄存器地址)内存:位于 CPU 外部,通常指 RAM,是计算机的一部分。 相对较慢,需要几十纳秒到几百纳秒 很大,通常有几十 GB 到几百 GB 用于存储程序代码、全局变量、堆和栈等较大数据*///register int a = 2; // 寄存器变量 可以提高访问速度(只是对编译器的建议,即使没有写register,编译器认为该放也会放)//*p = 4; // 解引用的使用//printf("%d\n", i); // 输出 4return 0;
}/*int main(void)
{int a = 1;int *p = &a;printf("%p\n", (void *)p); // 变量a的地址printf("%p\n", (void *)&a); // 变量a的地址printf("%p\n", (void *)&p); // 变量p的地址 (指针变量的地址)return 0;
}*/// 一级指针交换地址存储值
/*int main(void)
{uint a = 1, b = 2;exchange(&a, &b);printf("%u %u\n", a, b);
}*/
别emo了,出去走走吧~
这篇关于指针 C programming的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!