c基础(二)
指针:
含义:是一个值,一个值代表着一个内存地址,类似于存放路径
* 运算符 :
1 字符*
表示指针
作用:通常跟在类型关键字的后面,表示指针指向的是什么类型的值
int * foo, * bar;声明指针后会随机分配一个内存空间,指针指向的数据是随机的指针的初始化:
int* p;
int i;p = &i;
*p = 13;未初始化的指针数据最好这样定义:int* p = NULL;
2 运算符
作用:用来取出指针变量所指向的内存地址里面的值
* foo 取出定义的指针的值/*注意,数组名指向的地址是不能更改的*/
& 运算符:
作用:用来取出一个变量所在的内存地址int i = 5;if (i == *(&i)) // 正确,*(&i)含义:先取出i的内存地址,在获取内存地址对应的值
运算:
1 指针与整数值的加减运算
指针与整数值的运算,表示指针的移动。
2 指针与指针的加法运算
两个指针进行加法是非法的
3 指针与指针的减法
相同类型的指针允许进行减法运算,返回它们之间的距离,即相隔多少个数据单位。
高位地址减去低位地址,返回的是正值;低位地址减去高位地址,返回的是负值
返回值:ptrdiff_t
类型,一个带符号的整数类型别名
4 指针与指针的比较运算
比较的是各自的内存地址哪一个更大,返回值是整数1
(true)或0
(false)
函数:
基础结构:
#include <stdio.h>/* 基础结构*/int main(void)
{int m = addNum(3); /* 使用函数, 3 传递的参数*/printf("m=%d", m);
}int addNum(int a) /* int addNum 定义函数名称 (int a 传递参数,可以传递多个,使用逗号分开) */
{ /*{函数体:使用此方法需要执行的语句}*/return a; /* return a; return 返回值,返回计算之后的数据 */
}
参数:
传递的参数是拷贝的数据,非自身数据,不会实时更新数据;
除非1 函数返回最新的数据,才可以获取并赋值最新的数据2 直接修改自身的署,传入变量的地址(函数不要返回内部变量的指针)void Swap(int* x, int* y) {int temp;temp = *x;*x = *y;*y = temp;
}int a = 1;
int b = 2;
Swap(&a, &b);//参数为数组
int sum_array(int a[n], int n) {// ...
}int sum = sum_array(a, 4);
//等同于
int sum = sum_array((int []){3, 5, 7, 3}, 4);/*多维数组*/
int sum_array(int n, int m, int a[n][m]);
参数数量是不确定时,声明函数的时候,可以使用省略号...
表示可变数量的参数
注意:...
符号必须放在参数序列的结尾,否则会报错
#include<stdio.h> #include<stdarg.h> /* 可以操作可变参数的类*/double average(int i, ...);double average(int i, ...) {double total = 0;va_list ap; /*va_list 一个数据类型,用来定义一个可变参数对象*//* va_start(ap, i); 将参数i后面的参数统一放入ap*/va_start(ap, i); /*va_start 一个函数,用来初始化可变参数对象 va_start(可变参数对象,正常参数,用来为可变参数定位)*/printf("i=%d \n", i);for (int j = 1; j <= i; ++j) {/* va_arg(ap, double)用来从ap依次取出一个参数,并且指定该参数为 double 类型*/total += va_arg(ap, double); /* va_arg 一个函数,用来取出当前那个可变参数 va_arg(可变参数对象,当前可变参数的类型)*/printf("total=%d \n", total);}printf("ap=%d \n", ap);va_end(ap); /* va_end 一个函数,用来清理可变参数对象*/return total / i;
}int main(void)
{int total=average(0,8,10);printf("total=%d", total);
}
递归函数:
函数可以调用自身,这就叫做递归(recursion)例如:
#include <stdio.h>int main(void)
{int m = addNum(3);printf("m=%d", m);
}int addNum(int a)
{a++ ;if (a <= 5){addNum(a);}else{return a;}
}注意:在使用递归函数时,注意做好判断,不然容易出现死循环
入口函数:
main()是程序的入口函数,所有的程序必须要有
类似于页面加载方法,首先执行此方法
其他的方法需要通过main调用#include <stdio.h>int main(void)
{int m =3;printf("m=%d", m);return 0; /* 表示函数结束运行,返回0; 返回非零数据表示运行失败*/
}
函数指针:
调用函数的方法
// 写法一 常用的 函数名本身就是指向函数代码的指针,通过函数名就能获取函数地址
print(10)// 写法二
(*print)(10)// 写法三
(&print)(10)// 写法四
(*print_ptr)(10)// 写法五
print_ptr(10)#include<stdio.h> int addNum(int a)
{return a;
}int main(void) /*调用其他方法时,其他方法要么写在最前面, 或者使用函数原型*/
{// int m = addNum(3);// printf("m=%d", m);int m = (*addNum)(10);printf("m=%d", m);
}优点:
可以明确参数是一个函数参数一就是一个函数
int compute(int (*myfunc)(int), int, int);
函数原型:提前告诉编译器,每个函数的返回类型和参数类型int twice(int);int main(int num) {return twice(num);
}int twice(int num) {return 2 * num;
}注意,函数原型必须以分号结尾。一般来说,每个源码文件的头部,都会给出当前脚本使用的所有函数的原型。
exit函数:
作用:终止程序的运行
前提: #include<stdlib.h>
返回值(stdlib.h已定义,无需定义):EXIT_SUCCESS(相当于 0)表示程序运行成功EXIT_FAILURE(相当于 1)表示程序异常中止
atexit()函数:用来登记exit()执行时额外执行的函数,用来做一些退出程序时的收尾工作
说明符:
extern 说明符 :
extern int foo(int arg1, char arg2);
extern 表示:导入使用,声明此方法未在此文件定义,是从其他文件内引入使用的int main(void) {int a = foo(2, 3);// ...return 0;
}
static 说明符:
1 用于函数内部声明变量时,表示该变量只需要初始化一次,不需要在每次调用时都进行初始化
2 static
可以用来修饰函数本身,表示该函数只能在当前文件里使用,如果没有这个关键字,其他文件也可以使用这个函数(通过声明函数原型)
3 用在参数里面,修饰参数数组
int sum_array(int a[static 3], int n) { /* 数组长度至少为3*/}
注意:
static
修饰的变量初始化时,只能赋值为常量,不能赋值为变量
局部作用域中,static
声明的变量有默认值0
const 说明符:
1 函数内部不得修改该参数变量
void f(const int* p) {int x = 13;p = &x; // p本身的地址是允许修改的*p = 0; //const声明的* p 不能修改,修改之后报错
}
void f(int* const p) { //不允许修改p,就使用const定义int x = 13;p = &x; // 该行报错
}/* p和*p 都不允许修改 */
void f(const int* const p) {
}
内存管理:
分类:
系统管理:局部变量存放的内存区域(”栈“(stack)),运行结束后自动从内存卸载
用户手动管理:全局变量存放的内存区域(”堆“(heap)),运行结束后不会自动卸载,需要用户手动释放,此现象叫”内存泄漏“(memory leak)
void 指针:
void:不定类型的指针可以指向任意类型的数据,但是不能解读数据void 指针与其他所有类型指针之间是互相转换关系
注意,由于不知道 void 指针指向什么类型的值,所以不能用*运算符取出它指向的值
内存操作:
分配内存:
malloc:
#include <stdio.h>
#include <stdlib.h> /*内存管理的操作*/int main(){/* malloc(分配的内存字节数--非负整数) 任意类型的数据分配内存 返回值:无类型的 void 指针*///malloc不会对所分配的内存进行初始化,需要自行初始化后再使用,想要初始化为0,还要额外调用memset()函数int* p = malloc(sizeof(int));*p = 12;if (p == NULL) {// 内存分配失败}printf("%d\n", *p); int* n = (int*) malloc(sizeof(int)); //强制转换数据为整数类型printf("n=%d\n",*n);int* i = (int*) malloc(sizeof(*i));printf("i=%d\n",*i);//作用://1 为数组和自定义数据结构分配内存int* t = (int*) malloc(sizeof(int) * 10);for (int i = 0; i < 10; i++)t[i] = i * 5;printf("t==%d",t);//2 创建动态数组int m;int* a = (int*) malloc(m * sizeof(int)); //可以根据变量m的不同,动态为数组分配不同的大小}
calloc:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main(){// calloc(数据类型的值的数量,数据类型的单位字节长度) 分配内存, 返回值:无类型的 void 指针,分配失败时,返回 NULL//calloc所分配的内存全部初始化为0int* p = calloc(10, sizeof(int));printf("p==%d, %d \n",p,*p);// 等同于int* n = malloc(sizeof(int) * 10);memset(n, 0, sizeof(int) * 10);printf("n==%d, %d \n",n,*n);
}
释放内存:
free:
#include <stdio.h>
#include <stdlib.h>int main(){//free(malloc返回的内存地址) 释放malloc函数分配的内存//分配的地址释放之后,不可操作和再次释放// 注意:函数调用成功后,一定要释放内存,否则会导致多次调用函数所生成的内存下次无法访问int* p = (int*) malloc(sizeof(int));*p = 12;printf("address=%d",p);free(p);
}
修改内存:
realloc:
#include <stdio.h>
#include <stdlib.h>int main(){//realloc(已经分配好的内存块指针,内存块的新大小,单位为字节) 修改已经分配的内存块的大小,可以放大也可以缩小 , 返回新的内存块的指针,分配失败返回null// 已经分配好的内存块指针--参数设置为null或者不写,会创建一个新的指针// 内存块的新大小 --------参数设置为0,会释放内存块//realloc不会对内存块进行初始化int* p = calloc(10, sizeof(int));float* new_p = realloc(p, sizeof(*p * 40));if (new_p == NULL) {printf("Error reallocing\n");return 1;}else{printf("win--- \n");}
}
拷贝内存:
memcpy拷贝:
#include <stdio.h>
#include <string.h>//自定义复制内存函数:
void* my_memcpy(void* dest, void* src, int byte_count) {char* s = src;char* d = dest;while (byte_count--) {*d++ = *s++;}return dest;}int main(){//memcpy(拷贝地址,被拷贝地址,拷贝的字节数) 前两个参数:不限制指针类型,各种类型的内存数据都可以拷贝char s[] = "Goats!";char t[100];// memcpy(t, s, sizeof(s)); // 拷贝7个字节,包括终止符int m = my_memcpy(t, s, sizeof(s));printf("m=%s\n", m); // "Goats!"return 0;
}
memmove复制:
#include <stdio.h>
#include <string.h>int main(){//memmove(拷贝地址,被拷贝地址,移动的字节数) 允许目标区域与源区域有重叠。如果发生重叠,源区域的内容会被更改char x[] = "Home Sweet Home";printf("x=%s\n", (char *) memmove(x, &x[5], 10));
}
比较内存:
memcmp:
#include <stdio.h>
#include <string.h>int main(){//memcmp(比对者1,比对者2,比较的字节数) 返回值:整数 //相同时返回0,参数一大于参数二时返回大于0,参数一小于参数二返回小于0// char* s1 = "abc";// char* s2 = "acd";// int r = memcmp(s1, s2, 3); // 小于 0// printf("memcmp result=%d",r);//比较内部带有字符串终止符\0的内存区域char s1[] = {'b', 'i', 'g', '\0', 'c', 'a', 'r'};char s2[] = {'b', 'i', 'g', '\0', 'c', 'a', 't'};printf ("3=%d \n",memcmp(s1, s2, 3) == 0) ;// trueprintf ("4=%d \n",memcmp(s1, s2, 4) == 0) ;// trueprintf ("7=%d \n",memcmp(s1, s2, 7) == 0) ;// false}
restrict 说明符 :
restrict :内存区域只有当前指针一种访问方式,其他指针不能读写该内存,这种指针称为“受限指针”(restrict pointer)
相关文章:
c基础(二)
指针: 含义:是一个值,一个值代表着一个内存地址,类似于存放路径 * 运算符 : 1 字符*表示指针 作用:通常跟在类型关键字的后面,表示指针指向的是什么类型的值 int * foo, * bar;声明指针后会…...

人工智能趋势报告解读:ai野蛮式生长的背后是机遇还是危机?
近期,Enterprise WordPress发布了生成式人工智能在营销中的应用程度的报告,这是一个人工智能迅猛发展的时代,目前人工智能已经广泛运用到内容创作等领域,可以预见的是人工智能及其扩展应用还将延伸到我们工作与生活中的方方面面。…...
三、C语言中的分支与循环—goto语句 (10) (完)
在C语言中,goto语句允许程序无条件地跳转到同一函数内的标记位置。这个标记位置通过一个标签和冒号(:)来标示。goto语句可以用于从深层嵌套的循环或条件语句中直接跳出,或者跳过某些代码执行。尽管goto语句在某些情况下可以使程序逻辑变得清晰࿰…...
RabbitMQ 常见问题
1. 如何保证消息顺序消费 在RabbitMQ中,消息最终会保存在队列中,在同一个队列中,消息是顺序的,保持先进先出的原则,这个由Rabbitmq保证。而不同队列中的消息,RabbitMQ 是无法保证其顺序性。顺序消费主要是…...

阶段二-Day10-日期类
日期类结构: 1.java.util.Date是日期类 2.DateFormat是日期格式类、SimpleDateFormat是日期格式类的子类 Timezone代表时区 3.Calendar是日历类,GregorianCalendar是日历的子类 一. 常用类-Date 1.1 Date构造方法 Date(long date) 使用给定的毫秒时间价值构建…...

多任务并行处理相关面试题
我自己面试时被问过两次多任务并行相关的问题: 假设现在有10个任务,要求同时处理,并且必须所有任务全部完成才返回结果 这个面试题的难点是: 既然要同时处理,那么肯定要用多线程。怎么设计多线程同时处理任务呢&…...

Shell脚本学习笔记
1. 写在前面 工作中,需要用到写一些shell脚本去完成一些简单的重复性工作, 于是就想系统的学习下shell脚本的相关知识, 本篇文章是学习shell脚本整理的学习笔记,内容参考主要来自C语言中文网, 学习过程中,…...

ROS-安装xacro
安装 运行下列命令进行安装,xxxxxx处更改为自己的版本 sudo apt-get install ros-xxxxxx-xacro运行 输入下列命令 roscd xacro如果没有报错,并且进入了xacro软件包的目录,则表示安装成功。 参考: [1]https://wenku.csdn.net/ans…...

为什么说 $mash 是 Solana 上最正统的铭文通证?
早在 2023 年的 11 月,包括 Solana、Avalanche、Polygon、Arbitrum、zkSync 等生态正在承接比特币铭文生态外溢的价值。当然,因铭文赛道过于火爆,当 Avalanche、BNB Chain 以及 Polygon 等链上 Gas 飙升至极值,Arbitrum、zkSync 等…...

安装elasticsearch、kibana、IK分词器、扩展IK词典
安装elasticsearch、kibana、IK分词器、扩展IK词典 后面还会安装kibana,这个会提供可视化界面方面学习。 需要注意的是elasticsearch和kibana版本一定要一样!!! 否则就像这样 elasticsearch 1、创建网络 因为我们还需要部署k…...

Spring中常见的BeanFactory后处理器
常见的BeanFacatory后处理器 先给出没有添加任何BeanFactory后处理器的测试代码 public class TestBeanFactoryPostProcessor {public static void main(String[] args) {GenericApplicationContext context new GenericApplicationContext();context.registerBean("co…...
FPGA LCD1602驱动代码 (已验证)
一.需求解读 1.需求 在液晶屏第一行显示“HELLO FPGA 1234!” 2. 知识背景 1602 液晶也叫 1602 字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵 型液晶模块。它由若干个 5X7 或者 5X11 等点阵字符位组成,每个点阵字符位都可以显示一 个字符,每位之间有一个点距的…...

c++编程要养成的好习惯
1、缩进 你说有缩进看的清楚还是没缩进看的清楚 2、i和i i运行起来和i更快 3、 n%20和n&1 不要再用n%20来判断n是不是偶数了,又慢又土,用n&10,如果n&10就说明n是偶数 同理,n&11说明n是奇数 4、*2和<<…...
后台管理项目的多数据源方案
引言 在互联网开发公司中,往往伴随着业务的快速迭代,程序员可能没有过多的时间去思考技术扩展的相关问题,长久下来导致技术过于单一。为此最近在学习互联网思维,从相对简单的功能开始做总结,比如非常常见的基础数据的…...

视频美颜SDK趋势畅想:未来发展方向与应用场景
当下,视频美颜SDK正不断演进,本文将深入探讨视频美颜SDK的发展趋势,探讨未来可能的方向和广泛的应用场景。 1.深度学习与视频美颜的融合 未来,我们可以期待看到更多基于深度学习算法的视频美颜SDK,为用户提供更高质量…...
C++ const 限定符的全面介绍
C const 限定符的全面介绍 1. const 修饰基本数据类型 定义 const 修饰的基本数据类型变量,值不可改变。 语法 const type variable value;特点 不可变性,增加代码可读性。 作用 定义不可修改的常量。 使用场景 全局常量、配置项。 注意事项…...

Vue 中的 ref 与 reactive:让你的应用更具响应性(上)
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…...

华为云CCE-集群内访问-根据ip访问同个pod
华为云CCE-集群内访问-根据ip访问同个pod 问题描述:架构如下:解决方法: 问题描述: 使用service集群内访问时,由于启用了两个pod,导致请求轮询在两个pod之间,无法返回正确的结果。 架构如下&am…...

Kasada p.js (x-kpsdk-cd、x-kpsdk-ct、integrity)
提供x-kpsdk-cd的API服务 详细请私信~ 可试用~ V:zhzhsgg 一、简述 integrity是通过身份验证Kasada检测机器人流量后获得的一个检测结果(数据完整性) x-kpsdk-cd 是经过编码计算等等获得。当你得到正确的解决验证码值之后,解码会看到如下图…...
Thinkphp 5框架学习
TP框架主要是通过URL实现操作 http://servername/index.php/模块/控制器/操作/参数/值.. index.php 为入口文件,在 public 目录内的 index.php 文件; 模块在 application 目录下默认有一个 index 目录,这就是一个模块; 而在 index 目录下有一个 contro…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
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方式进行封装,供调用如何按…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...