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零售数据分…...
亚马逊卖家为何需要自养账号?揭秘背后的原因
亚马逊是一家极为重视用户体验的国际电商平台,因此用户的评论和星级评价对店铺排名影响深远。平台审核评论非常严格,这些评价直接影响商品在平台上的生存和发展。 在亚马逊上,用户的评分和评论对商品的成功至关重要。好评多的商品通常被认为优…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
