C语言入门课程学习笔记9:指针
C语言入门课程学习笔记9
- 第41课 - 指针:一种特殊的变量
- 实验-指针的使用
- 小结
- 第42课 - 深入理解指针与地址
- 实验-指针的类型
- 实验
- 实验
- 小结
- 第43课 - 指针与数组(上)
- 实验
- 小结
- 第44课 - 指针与数组(下)
- 实验
- 实验
- 小结
- 第45课 - 指针与函数
- 实验
- 实验
- 小结
- 第46课 - 指针与堆空间
- 实验
- 实验
- 小结
- 第47课 - 指针专题经典问题剖析
- 小结
第41课 - 指针:一种特殊的变量




实验-指针的使用
#include <stdio.h>int main()
{int var = 0;int another = 0;int* pVar = NULL;printf("1. var = %d\n", var);printf("1. pVar = %p\n", pVar);pVar = &var; // 使用指针保存变量的地址*pVar = 100; // *pVar 等价于 var , var = 100;printf("2. var = %d\n", var);printf("2. pVar = %p\n", pVar);pVar = &another; // 改变了 pVar 的指向,使得 pVar 保存 another 的地址*pVar = 1000; // another = 1000;printf("3. another = %d\n", another);printf("3. pVar = %p\n", pVar);printf("4. add ==> %d\n", var + another + *pVar); // 100 + 1000 + 1000 ==> 2100return 0;
}
/*
1. var = 0
1. pVar = 0000000000000000
2. var = 100
2. pVar = 000000000061FE14
3. another = 1000
3. pVar = 000000000061FE10
4. add ==> 2100
*/




小结

第42课 - 深入理解指针与地址



实验-指针的类型
#include <stdio.h>int main()
{int i = 10;float f = 10;int* pi = &f; // WARNING int* 指向了floatfloat* pf = &f; // OKprintf("pi = %p, pf = %p\n", pi, pf);printf("*pi = %d, *pf = %f\n", *pi, *pf);pi = i; // WARNING *pi = 110; // OOPSprintf("pi = %p, *pi = %d\n", pi, *pi);return 0;
}




实验
#include <stdio.h>int calculate(int n, long long* pa, long long* pm)
{int ret = 1;if( (1 <= n) && (n <= 20) ){int i = 0;*pa = 0;*pm = 1;for(i=1; i<=n; i++)// 0+1+...+n{ //1*1*...*n*pa = *pa + i;*pm = *pm * i;}}else{ret = 0;}return ret;
}int main()
{long long ar = 0;long long mr = 0;if( calculate(5, &ar, &mr) )printf("ar = %lld, mr = %lld\n", ar, mr);//15 1*2*3*4*5=120return 0;
}


实验
#include <stdio.h>void func(int* p)
{*p = 100; // 修改内存中 4 字节的数据,即:修改一个整型变量的值
}void swap(int* pa, int* pb)//通过指针交换变量
{int t = 0;t = *pa;*pa = *pb;*pb = t;
}int main()
{int var = 0;int a = 1, b = 2;printf("1. var = %d\n", var);func( &var );printf("2. var = %d\n", var);//100printf("3. a = %d, b = %d\n", a, b);swap(&a, &b);printf("4. a = %d, b = %d\n", a, b);return 0;
}
小结

第43课 - 指针与数组(上)





实验
#include <stdio.h>int main()
{int a[] = {1, 2, 3, 4, 0};int* p = a; // a 的类型为 int*, &a[0] ==> int*int (*pa) [5] = &a;//指向数组的指针 注意指针类型printf("%p, %p\n", p, a);p++;//p+1==== p+1*sizeof(p)*p = 100; // a[1] = 100;printf("%d, %d\n", *p, a[1]);printf("%p, %p\n", &a, a);//????值一样 但是意思不一样,数组的地址 数组首元素的地址p = pa; // WARNING !!!! warning: assignment to 'int *' from incompatible pointer type 'int (*)[5]' p = a;while( *p ){printf("%d\n", *p);p++;}return 0;
}
/*
000000000061FDF0, 000000000061FDF0
100, 100
000000000061FDF0, 000000000061FDF0
1
100
3
4
*/
小结

第44课 - 指针与数组(下)


实验
#include <stdio.h>int main()
{int a[] = {1, 2, 3, 4, 5};int* p = a;int i = 0;// a[i] <==> *(a+i) <==> *(p+i) <==> p[i]for(i=0; i<5; i++){printf("%d, %d\n", a[i], *(a + i));}for(i=0; i<5; i++){printf("%d, %d\n", a[i], p[i]);}for(i=0; i<5; i++){printf("%d, %d\n", p[i], *(p + i));}printf("a = %p, p = %p\n", a, p);//值相同printf("&a = %p, &p = %p\n", &a, &p);//值不同return 0;
}



实验
#include <stdio.h>int main()
{int a[] = {1, 2, 3};int* p = a;int v = *p++;//int v=*p,p++;char* s = NULL;printf("%p\n", "D.T.Software");printf("%p\n", "D.T.Software");printf("v = %d, *p = %d\n", v, *p);printf("First = %c\n", *"D.T.Software");s = "D.T.Software";while( *s ) printf("%c", *s++);printf("\n");return 0;
}
/*
0000000000404000
0000000000404000
v = 1, *p = 2
First = D
D.T.Software
*/
小结

第45课 - 指针与函数







实验
#include <stdio.h>int add(int a, int b)
{return a + b;
}int mul(int a, int b)
{return a * b;
}int calculate(int a[], int len, int(*cal)(int, int))
{int ret = a[0];int i = 0;for(i=1; i<len; i++){ret = cal(ret, a[i]);}return ret;
}int main()
{int a[] = {1, 2, 3, 4, 5};int (*pFunc) (int, int) = NULL;pFunc = add;printf("%d\n", pFunc(1, 2));//3printf("%d\n", (*pFunc)(3, 4));//7pFunc = &mul;printf("%d\n", pFunc(5, 6));//30printf("%d\n", (*pFunc)(7, 8));//56printf("1 + ... + 5 = %d\n", calculate(a, 5, add));//15printf("1 * ... * 5 = %d\n", calculate(a, 5, mul));//120return 0;
}


实验
#include <stdio.h>int demo(int arr[], int len) // int demo(int* arr, int len)//数组求和
{int ret = 0;int i = 0;printf("demo: sizeof(arr) = %d\n", sizeof(arr));// 8 退化为指针了while( i < len ){ret += *arr++;i++;}return ret;
}int main()
{int a[] = {1, 2, 3, 4, 5};// int v = *a++;printf("return value: %d\n", demo(a, 5));//return 0;
}
小结

第46课 - 指针与堆空间






实验
#include <stdio.h>int main()
{char c = 0;int i = 0;float f = 2.0f;double d = 3.0;void* p = NULL;double* pd = NULL;int* pi = NULL;/* void* 指针可以保存任意类型的地址 */p = &c;p = &i;p = &f;p = &d;printf("%p\n", p);// void* 类型的指针无法访问内存中的数据// printf("%f\n", *p);/* void* 类型的变量可以直接合法的赋值给其他具体数据类型的指针变量 */pd = p;pi = p;// void* 是例外,其他指针类型的变量不能相互赋值// pd = pi;return 0;
}



实验
#include <stdio.h>
#include <stdlib.h>int main()
{int* p = malloc(4); // 从堆空间申请 4 个字节当作 int 类型的变量使用if( p != NULL ) // 如果申请失败 p 为 0 ,即:空值{*p = 100;printf("%d\n", *p);//100free(p);}p = malloc(4 * sizeof(int));if( p != NULL ){int i = 0;for(i=0; i<4; i++){p[i] = i * 10;}for(i=0; i<4; i++){printf("%d\n", p[i]);}free(p);}return 0;
}
/*
100
0
10
20
30
*/
小结

第47课 - 指针专题经典问题剖析

#include <stdio.h>
#include <stdlib.h>int main()
{int a = 0;int b = 1;int* p = &a; //p指向aint** pp = &p;//pp指向p**pp = 2; // a = 2;*pp = &b; // p = &b; *p = 3; // b = 3;printf("a = %d, b = %d\n", a, b);return 0;
}



#include <stdio.h>
#include <stdlib.h>int main()
{int a[] = {1, 2, 3, 4};int* pa = a;int b[2][2] = {{1, 2}, {3, 4}};// int** pb = b; // b 的类型绝对不是 int** warning: initialization of 'int **' from incompatible pointer type 'int (*)[2]'int (*pnb) [2] = b; // b 的类型是 int(*)[2]printf("a = %p, pa = %p\n", a, pa);// printf("b = %p, pb = %p\n", b, pb);printf("b = %p, pnb = %p\n", b, pnb);return 0;
}
/*
a = 000000000061FE00, pa = 000000000061FE00
b = 000000000061FDF0, pnb = 000000000061FDF0
*/



#include <stdio.h>
#include <stdlib.h>int getDouble(double** pp, unsigned n)
{int ret = 0;double* pd = malloc(sizeof(double) * n);if( pd != NULL ){printf("pd = %p\n", pd);*pp = pd;ret = 1;}return ret;
}int main()
{double* p = NULL;if( getDouble(&p, 5) ){printf("p = %p\n", p);free(p);}return 0;
}
/*
pd = 00000000006E5CB0
p = 00000000006E5CB0
*/

#include <stdio.h>
#include <stdlib.h>int main()
{int b[2][2] = {{1, 2}, {3, 4}};int (*pnb) [2] = b; // b 的类型是 int(*)[2]*pnb[0] = 10;//*(pnb[0])*pnb[1] = 30;printf("b[0][0] = %d\n", b[0][0]);printf("b[0][1] = %d\n", b[0][1]);//30printf("b[1][0] = %d\n", b[1][0]);printf("b[1][1] = %d\n", b[1][1]);return 0;
}
/*
b[0][0] = 10
b[0][1] = 2
b[1][0] = 30
b[1][1] = 4
*/

#include <stdio.h>
#include <stdlib.h>int main()
{int b[2][2] = {{1, 2}, {3, 4}};int (*pnb) [2] = b; // b 的类型是 int(*)[2]*pnb[0] = 10;
int * k=pnb[0] +1;//?? pnb[0] +sizeof(*pnb[0])对了 *k= 20;// *pnb[1] = 30;
printf("sizeof(pnb) = %d\n", sizeof(pnb));
printf("sizeof(pnb[0]) = %d\n", sizeof(pnb[0]));
printf("sizeof(*pnb) = %d\n", sizeof(*pnb));
printf("sizeof(*pnb[0]) = %d\n", sizeof(*pnb[0]));
printf("pnb=%p\n",pnb);
printf("pnb[0]=%p\n",pnb[0]);
printf("pnb[0]+1=%p\n",pnb[0]+1);printf("sizeof(b) = %d\n", sizeof(b));
printf("sizeof(int[2]) = %d\n", sizeof(int[2]));printf("b[0][0] = %d\n", b[0][0]);printf("b[0][1] = %d\n", b[0][1]);//30printf("b[1][0] = %d\n", b[1][0]);printf("b[1][1] = %d\n", b[1][1]);return 0;
}
/*
sizeof(pnb) = 8
sizeof(pnb[0]) = 8
sizeof(*pnb) = 8
sizeof(*pnb[0]) = 4
pnb=000000000061FE00
pnb[0]=000000000061FE00
pnb[0]+1=000000000061FE04
sizeof(b) = 16
sizeof(int[2]) = 8
b[0][0] = 10
b[0][1] = 20
b[1][0] = 3
b[1][1] = 4
*/

#include <stdio.h>
#include <stdlib.h>int* func()
{int var = 100;return &var;
}int main()
{int* p = func(); // OOPS!!!!// p 指向了不合法的地址,这个地址处没有变量存在// p 是一个野指针,保存不合法地址的指针都是野指针printf("*p = %d\n", *p);*p = 200; // 改变 func 函数中局部变量 var 的值,是不是非常奇怪???printf("*p = %d\n", *p);return 0;
}
小结

相关文章:
C语言入门课程学习笔记9:指针
C语言入门课程学习笔记9 第41课 - 指针:一种特殊的变量实验-指针的使用小结 第42课 - 深入理解指针与地址实验-指针的类型实验实验小结 第43课 - 指针与数组(上)实验小结 第44课 - 指针与数组(下)实验实验小结 第45课 …...
借助 Cloudflare D1 和 Drizzle 在 Astro 上实现全栈
使用 Cloudflare D1 和 Drizzle ORM 将后端添加到 Astro 项目的分步指南 文章目录 安装 Astro添加 Cloudflare 适配器部署到 Pages安装 wrangler 并登录创建 D1 数据库创建 wrangler.toml 文件将 .wrangler 添加到 .gitignore更新 astro.config.ts安装 Drizzle 依赖项创建 driz…...
SUSE linux 15的网络管理
1 手工配置网络 wicked提供了一种新的网络配置框架。自SUSE 12起,SUSE使用了新的网络管理工具wicked,这个是区别与其他常见发行版的。常见的发行版目前大多使用的是NetworkManager服务进行网络管理。 1.1 wicked网络配置 传统网络接口管理面临的挑战之…...
海康威视-下载的录像视频浏览器播放问题
目录 1、播放异常比对 2、视频编码检查 2.1、正常视频解析 2.2、海康视频解析 2.3、比对工具 3、转码 3.1、maven依赖 3.2、实现代码 4、验证 在前面的文章(海康威视-按时间下载录像文件_海康威视 sdk 下载录像 大小0-CSDN博客)中,通…...
养殖自动化管理系统:开启智慧养殖新篇章
在现代农业的快速演进中,养殖业正经历一场前所未有的技术革命。养殖自动化管理系统,作为这场变革的前沿科技,正逐步成为推动行业高效、环保、可持续发展的关键力量。本文将深入探讨自动化养殖系统如何通过精准管理、智能监控、数据驱动决策&a…...
SmartEDA革新来袭:融合Multisim与Proteus精髓,引领电子设计新纪元!
在电子设计领域,每一次技术的革新都如同春风化雨,滋润着设计师们的心田。今天,我们迎来了一个划时代的电子设计自动化(EDA)工具——SmartEDA,它不仅融合了业界知名的Multisim和Proteus的精华,更…...
【FFmpeg】AVFormatContext结构体
【FFmpeg】AVFormatContext结构体 1.AVFormatContext结构体1.2 const struct AVInputFormat *iformat1.3 const struct AVOutputFormat *oformat 参考: FFMPEG结构体分析:AVFormatContext 示例工程: 【FFmpeg】调用ffmpeg库实现264软编 【FF…...
【SpringSecurity】认证与鉴权框架SpringSecurity——授权
目录 权限系统的必要性常见的权限管理框架SpringSecurity授权基本流程准备脚本限制访问资源所需权限菜单实体类和Mapper封装权限信息封装认证/鉴权失败处理认证失败封装鉴权失败封装配置SpringSecurity 过滤器跨域处理接口添加鉴权hasAuthority/hasAnyAuthorityhasRole/ hasA…...
深入解析FTP:原理、架构与搭建方式
在当今互联网世界中,文件传输是日常工作和生活中不可或缺的一部分。FTP(File Transfer Protocol,文件传输协议)作为一种老而弥坚的协议,一直在文件传输领域发挥着重要作用。本文将从技术人的角度,详细分析F…...
Springboot与RestTemplate
RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。 一、使用Get进行访问 1、获取json格式 使用 getForEntity() API 发起 GET 请求: RestTemplate restTemplate…...
端口发布与暴露
端口发布与暴露 目录 发布端口发布到临时端口发布所有端口试一试 使用 Docker CLI使用 Docker Compose 如果你一直在跟随本指南,你应该理解容器为应用程序的每个组件提供了隔离的进程。每个组件 - 如 React 前端、Python API 和 Postgres 数据库 - 都运行在自己的…...
Unity:使用Texture2D动态创建的图像无法正常显示 / 修改图像后未生效
开发中遇到需要动态绘制图像的需求,前后文代码如下所示: Texture2D newImageTexture new Texture2D(width, height); Color32[] newImagePixels new Color32[height * width];for (int y 0; y < height ; y) {for (int x 0; x < width; x){if…...
【LinuxC语言】详解TCP/IP
文章目录 前言TCP与UDP协议的介绍TCP协议流式传输TCP的三次握手连接TCP的四次挥手连接断开总结前言 在我们的日常生活中,无论是浏览网页,还是发送电子邮件,甚至是在线视频聊天,都离不开网络通信。而在网络通信中,TCP和UDP协议起着至关重要的作用。本文将以通俗易懂的语言…...
数字化转型下的企业人力资源信息系统研究
随着数字化转型的加速,企业人力资源管理面临着全新的挑战和机遇。传统的人力资源信息系统(HRIS)在新时代的要求下必须进行深刻的革新和升级,以更好地支持企业的发展战略和员工的需求。 数据驱动的决策支持 在当今这个信息化迅猛发…...
docker camunda 8.5 部署步骤
Camunda Platform 8 环境准备 Docker 版本要求 Docker 20.10.16 is required; docker compose version 1.27.0.;github 开源地址:https://github.com/camunda/camunda-platformcamunda7 文档地址:https://docs.camunda.org/manual/7.21/user-guide/process-engine/社区地址: …...
学懂C#编程:常用高级技术——委托(Delegate)应用场景——委托与Lambda表达式的结合使用详解
在C#中,委托与Lambda表达式的结合使用是现代编程实践中的一个重要且强大的特性,它极大地提高了代码的简洁性和可读性。下面将详细讲解这两个概念如何协同工作,以及如何在实际编程中有效利用它们。 委托基础 委托是C#中的一种引用类型&#x…...
05-java基础——循环习题
循环的选择:知道循环的次数或者知道循环的范围就使用for循环,其次再使用while循环 猜数字 程序自动生成一个1-100之间的随机数,在代码中使用键盘录入去猜出这个数字是多少? 要求:使用循环猜,一直猜中为止…...
网络安全等级保护测评
网络安全等级保护 《GB17859 计算机信息系统安全保护等级划分准则》 规定计算机信息系统安全保护等级共分五级 《中华人民共和国网络安全法》 “国家实行网络安全等级保护制度。 等级测评 测评机构依据国家网络安全等级保护制度规定,按照有关 管理规范和…...
真有被这套零售数据分析方案惊艳到
在数字化时代,零售行业的竞争愈发激烈,如何精准把握市场动态、优化业务流程、提升市场竞争力成为了每一家零售企业都面临的挑战。奥威BI零售数据分析方案,一款具备全面、高效、智能的数据分析能力的BI方案出现地恰到好处。 奥威BI零售数据分…...
亚马逊卖家为何需要自养账号?揭秘背后的原因
亚马逊是一家极为重视用户体验的国际电商平台,因此用户的评论和星级评价对店铺排名影响深远。平台审核评论非常严格,这些评价直接影响商品在平台上的生存和发展。 在亚马逊上,用户的评分和评论对商品的成功至关重要。好评多的商品通常被认为优…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...
数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...
