当前位置: 首页 > ai >正文

嵌入式开发学习(第二阶段 C语言笔记)

指针

main函数原型

定义

main函数有多种定义格式,main函数也是函数,函数相关的结论对main函数野有效。

main函数完整写法:

int main(int argc,char *argv[]){...}
int main(int argc,char **argz){...}

扩展写法:

main ()   等价与  int main{}    //C11之后不再支持,省略返回类型
int main(void){}    等价 int main(){}
void main(void){}   等价 void main(){}
int main(int a){}  
int main(int a,int b,int c){}
...
说明

①argc,argv是形参,他们俩可以修改

②main函数的扩展写法有些编译器不支持,编译报警告

③argc和argv的常规写法

  • argc:存储了参数的个数,默认是1个,也就是运行程序的名字

  • argv:存储了所有参数的字符串形式

④main函数是系统通过函数指针的回调调用。

/*************************************************************************> File Name:    demo01.c> Author:       小刘> Description:  > Created Time: 2025年05月23日 星期五 09时19分38秒************************************************************************/#include <stdio.h>int main(int argc,char *argv[])
{//访问参数的个数printf("argc = %d\n",argc);// 遍历参数(每个参数都是字符串常量)for(int i = 0;i < argc ;i ++){printf("%s,%s\n",argv[i],*(argv + i));}printf("\n");return 0;
}

运行结果:

在这里插入图片描述

常量指针与指针变量

常量类型

①字面量:直接使用的固定值(如 12, hello, orange, 李双真帅 )符号常量在编译器转换为了字面量

②只读常量:用const 修饰的变量,初始化后不可修改。

const int a = 10;//只读常量
a = 21;   //编译报错
常量指针
  • 本质:指向常量数据的指针

  • 语法:

    const 数据类型 *变量名;
    const 数据类型* 变量名;
    
  • 举例

    const int *p;
    
  • 特性

    1. 指向的数据不可通过指针修改,指向对象的值不可变*p = x 非法);
    2. 指针本身可指向其他地址,指向可以变p = &b 合法)
  • 应用场景

    函数参数保护数据不被修改,使用率高

    // 遍历数组
    void print_array(const int *arr, int len);
    
  • 案例演示

    #include <stdio.h>int main(int argc,char *aegc[])
    {int a = 10;int *const p = &a;*p = 100;printf("%d\n",*p);int b = 20;p = &b;printf("%d\n");return 0;
    }
    
常量指针常量
  • **本质:**指针本身是常量,指向固定地址

  • 语法:

    数据类型* const 变量名;
    数据类型 *const 变量名;
    
  • 举例

    const int * const p;//p是指针常量
    
  • 特性

    1. 指向的数据可通过指针修改, 指向对象的值可变p= &合法)
    2. 指针本身不可指向其他地址, 指针的指向不变 p = &b 非法)
  • 注意:

    定义时必须初始化

    int a = 10;
    int *const p = &a; // 正确
    
  • 案例演示:

    #include <stdio.h>
    int main(int argc,char *argv[])
    {int a = 10; // 变量int *const p = &a; // 常量指针*p = 100; // 正确,指向对象的值可以改变printf("%d\n",*p); // 100int b = 20; // 变量p = &b; // 错误,指向不可以改变printf("%d\n",*p); return 0;
    }
    
常量指针常量
  • 本质:指针的指向和指向的数据均不可改变

  • 语法:

    const 数据类型* const 变量名;
    const 数据类型 *const 变量名;
    
  • 举例:

    const int* const p; // p是常量指针常量
    
  • 特性:

    1. 指针的指向不可变( p = &b 非法)
    2. 指针指向的数据不可变( *p = x; 非法)
  • 注意:

    定义时必须初始化

    int a = 10;
    const int *const p = &a; // 正确
    

简单理解,不管是常量指针、指针常量,还是常量指针常量,本质上都是一个赋值受到限制的指针变量。

总结对比

在这里插入图片描述

关键点
  1. const*左侧:修饰数据(常量指针)
  2. const*右侧:修饰(指针常量)
  3. 函数参数优先使用常量指针,提高代码安全性
  4. 指针常量必须初始化,且不可重新指向

野指针、空指针、悬空指针

野指针

**定义:**指向无效内存区域(如果未初始化、已释放或访问越界)的指针称为野指针。野指针会导致未定义行为。

危害:

  1. 访问野指针可能引发段错误(segmentation Fault)
  2. 可能破坏关键内存数据,导致程序崩溃。

产生场景

  1. 指针变量未初始化

    int *p;//p未初始化,是野指针
    printf("%d\n",*p); //危险操作
    
  2. 指向已经释放内存

    int fun(int a,int b)
    {int p = a+b;return &p;
    }int main()
    {int *p = fun(5,3);printf("%d\n",*p);//危险操作
    }
    -----------------------------------------------
    int *p = malloc(sizeof(int));
    free(p);
    printf("%d\n",*p);// p称为野指针
    
  3. 返回局部变量的地址

    int *fun(int a,int b)
    {int p = a + b;return &p;
    }
    int main()
    {int *p = fun(5,3);printf("%d\n",*p);//危险操作
    }
    

如何避免野指针

  1. 初始化指针为NULL。
  2. 释放内存后立即置指针NULL。
  3. 避免返回局部变量地址。
  4. 使用前检查指针有效性。
int fun()
{int *p = pt;//校验指针if(p == NUll){printf("错误!");return -1;}printf("%d\n",*p);
}
空指针

定义:值为 NULL 的指针,指向地址0x0000 0000(系统保留,不可访问)

在这里插入图片描述

**作用:**明确表示指针当前不指向有效内存。一般用作指针的初始化

示例:

int *p = NULL;//初始化为空指针free(p);//释放后置空
p = NULL;
空悬指针

定义:指针指向已被释放,但未重新赋值。空悬指针是野指针的一种特例。

示例:

char *p = malloc(100);
free(p);// 释放p指向的空间
// free(p) 一定要置空,否则会产生空悬指针现象,p = NULL
printf("%p\n",p); // p仍保留原地址,称为空悬指针

void 与void * 的区别

定义
  • void:表示“无类型”,用于函数返回类型或参数。

    void func(void );   //没有返回值也没有参数,一般简写,void func()
    
  • void* :通用指针类型(万能指针),可指针指向任意类型数据,但需要强制类型转换后才能解引用。

    void *ptr = mall0c(4);//ptr指向4个字节大小的内存空间
    //存放int
    //int *p (int *)ptr
    //*p = 10;//存放float
    float* p =(float *)ptr;
    *p = 21.5;
    

    注意:只能是具体的类型( int*,double*,float*,char*... )和 void* 之间转换

注意事项

void* 不能直接解引用(如: *ptr 会报错)
函数返回void*需要外部接收的时候明确类型(不明确类型,就无法解引用)

示例
/*************************************************************************> File Name:    demo02.c> Author:       小刘> Description:  > Created Time: 2025年05月23日 星期五 11时34分32秒************************************************************************/#include <stdio.h>
#include <stdlib.h>/*** 定义一个返回为void* 类型的指针函数*/ 
void* proces_data(void* p)
{return p;
}
int main(int argc,char *argv[])
{// int 类型int m = 10;int* p_int = &m;int* result_int = (int*)proces_data(p_int);printf("Integer value:%d\n", *result_int);// double类型double pi = 3.1415926;double* p_double = &pi;double* result_double = (double*)proces_data(p_double);printf("Double value:%.6f\n", *result_double);// void* generic_ptr = process_data(p_int);// *generic_ptr = 30; // 错误:void*不能直接解引用(必须明确类型,才能解引用)return 0;
}
http://www.xdnf.cn/news/9492.html

相关文章:

  • 电缆护层保护器的优势
  • OpenWrt 插件安装失败的常见问题和解决方法
  • sglang 部署Qwen/Qwen2.5-VL-7B-Instruct
  • JavaScript 性能优化:从入门到实战
  • 将文件夹中的未命名的文件类型或txt的文件类型改为dat类型
  • mybatis-plus实现增删改查(新手理解版)
  • 6.4.2_3最短路径问题_Floyd算法
  • 【连接器专题】案例:SD卡座规格书接触阻抗测试标准EIA-364-06B和EIA-364-23有什么区别?
  • day023-面试题总结
  • 【计算机网络】4网络层①
  • STM32学习笔记---时钟树
  • 易学探索助手-个人记录(十二)
  • 【ArcGIS Pro草履虫大师】空间地图系列
  • 数据结构之堆(topk问题、堆排序)
  • 功能测试向量是个什么概念
  • 开源架构在移动端开发中的卓越应用与深度解析
  • Java+POI+EXCEL导出柱形图
  • 小程序定制开发:从需求到落地,打造企业专属数字化入口
  • Android 13中 配置签名文件与内置相应的Apk
  • 解锁5月游戏新体验 高速电脑配置推荐
  • 本地部署RAGFlow
  • Flink CEP实践总结:使用方法、常见报错、优化与难点应对
  • 查看webpack版本的三种方式
  • JS逆向 QQ音乐sign签名|webpack实战 (上)
  • Unity UI设计优化与模式原则
  • 深度学习-PyTorch介绍
  • Linux环境搭建
  • CPO-BP+MOPSO,冠豪猪优化BP神经网络+多目标粒子群算法!(Matlab源码)
  • 【Qt开发】布局管理器
  • AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年5月28日第91弹