指针 C programming

2024-09-02 00:12
文章标签 指针 programming

本文主要是介绍指针 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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1128448

相关文章

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个

C语言指针入门 《C语言非常道》

C语言指针入门 《C语言非常道》 作为一个程序员,我接触 C 语言有十年了。有的朋友让我推荐 C 语言的参考书,我不敢乱推荐,尤其是国内作者写的书,往往七拼八凑,漏洞百出。 但是,李忠老师的《C语言非常道》值得一读。对了,李老师有个官网,网址是: 李忠老师官网 最棒的是,有配套的教学视频,可以试看。 试看点这里 接下来言归正传,讲解指针。以下内容很多都参考了李忠老师的《C语言非

C和指针:字符串

字符串、字符和字节 字符串基础 字符串就是一串零个或多个字符,并且以一个位模式为全0的NUL字节结尾。 字符串长度就是字符串中字符数。 size_t strlen( char const *string ); string为指针常量(const修饰string),指向的string是常量不能修改。size_t是无符号数,定义在stddef.h。 #include <stddef.h>

【C++】作用域指针、智能指针、共享指针、弱指针

十、智能指针、共享指针 从上篇文章 【C++】如何用C++创建对象,理解作用域、堆栈、内存分配-CSDN博客 中我们知道,你的对象是创建在栈上还是在堆上,最大的区别就是对象的作用域不一样。所以在C++中,一旦程序进入另外一个作用域,那其他作用域的对象就自动销毁了。这种机制有好有坏。我们可以利用这个机制,比如可以自动化我们的代码,像智能指针、作用域锁(scoped_lock)等都是利用了这种机制。

MFC中App,Doc,MainFrame,View各指针的互相获取

纸上得来终觉浅,为了熟悉获取方法,我建了个SDI。 首先说明这四个类的执行顺序是App->Doc->Main->View 另外添加CDialog类获得各个指针的方法。 多文档的获取有点小区别,有时间也总结一下。 //  App void CSDIApp::OnApp() {      //  App      //  Doc     CDocument *pD

C和指针:结构体(struct)和联合(union)

结构体和联合 结构体 结构体包含一些数据成员,每个成员可能具有不同的类型。 数组的元素长度相同,可以通过下标访问(转换为指针)。但是结构体的成员可能长度不同,所以不能用下标来访问它们。成员有自己的名字,可以通过名字访问成员。 结构声明 在声明结构时,必须列出它包含的所有成员。 struct tag {member-list} variable-list ; 定义一个结构体变量x(包含

hot100刷题第1-9题,三个专题哈希,双指针,滑动窗口

求满足条件的子数组,一般是前缀和、滑动窗口,经常结合哈希表; 区间操作元素,一般是前缀和、差分数组 数组有序,更大概率会用到二分搜索 目前已经掌握一些基本套路,重零刷起leetcode hot 100, 套路题按套路来,非套路题适当参考gpt解法。 一、梦开始的地方, 两数之和 class Solution:#注意要返回的是数组下标def twoSum(self, nums: Lis

Qt: 详细理解delete与deleteLater (避免访问悬空指针导致程序异常终止)

前言 珍爱生命,远离悬空指针。 正文 delete 立即删除:调用 delete 后,对象会立即被销毁,其内存会立即被释放。调用顺序:对象的析构函数会被立即调用,销毁该对象及其子对象。无事件处理:如果在对象销毁过程中还涉及到信号和槽、事件处理等,直接 delete 可能会导致问题,尤其是在对象正在处理事件时。适用场景:适用于在确定对象已经不再被使用的情况下,并且不涉及异步处理或事件循环中的

C语言进阶版第8课—指针(2)

文章目录 1. 数组名的理解2. 指针访问数组3. 一维数组传参本质4. 冒泡排序5. 二级指针6. 指针数组7. 指针数组模拟二维数组 1. 数组名的理解 sizeof(数组名)— 这里的数组名代表整个数组,计算的也是整个数组的大小&数组名 — 这里的数组名代表是整个数组,取出的是整个数组的地址除了以上两种,其他任何地方使用数组名,数组名都表示首元素的地址 //数组名

有希带你深入理解指针(4)

目录 前言🥰1.回调函数😺1.1回调函数的概念😋 2.qsort使用🤯2.1什么是qsort👻2.2 qsort函数的使用🧐 3.模拟实现qsort😎 前言🥰 本篇文章是对指针知识的进一步讲解,如果对部分知识有不了解的地方可以移步前文进行学习!😶‍🌫️ 1.回调函数😺 1.1回调函数的概念😋 回调函数就是⼀个通过函数指针调用的函数。 如果你把函数的