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

C语言模块化概述

一、函数名的意义

1.c语言是一门面向过程的语言:所谓的过程就是动词,动作。

功能块=动词1+动词2+……+动词

2.功能块:就是一堆动词(动作)的组合,动作通过函数来实现。

3.函数的功能:承上启下

承上启下,空间和空间的传递
 a.看 看一下 具有数据类型的空间 传递这个空间的变量名 拷贝值
      看,上层把我的空间传递给了下层,根本不用担心下层把我的空间改了

 b.改 如果让子函数修改上层空间
       a1.上层空间,必须把这个空间的首地址交给子函数
       a2.子函数拿到这个地址后,必须使用 *addr=

c.具有连续数据类型的空间,指针只标记了首地址,没有标记结束标志
   子函数就能够拿着这个指针,不受访问的限制了,这个肯定不是空间传递的方法
 空间: 首地址,结束标志[个数]

  • 值传递
void t01(int b){
    b=20;
    printf("Inside t01, b = %d\n", b); // 打印t01函数内部的b的值
}

void fun1(){
    int a=10;
    printf("Inside fun1, a = %d\n", a); // 打印fun1函数内部的a的值
    t01(a);
}
  • 地址传递
// 修改t01函数,使其接收一个整数的指针
void t01(int *b){
    *b = 20; // 通过解引用指针来修改b指向的值
}

void fun1(){
    int a = 10;
    printf("Inside fun1, before calling t01, a = %d\n", a); // 打印a的初始值
    t01(&a); // 将a的地址传递给t01函数
    printf("Inside fun1, after calling t01, a = %d\n", a); // 打印a被修改后的值

}

4.如何实现承上启下的功能?封装和调用

5.函数名的意义:标识一段空间的首地址

6.标识符:

  • 在C语言中,标识符(Identifier)是用来标识变量名、函数名、数组名、宏名等的符号。
    它们是编程语言中用于表示数据对象和函数的名称。
    以下是关于C语言中标识符的一些规则和特点:
    
    1.字母开头:标识符必须以字母(A-Z或a-z)或下划线(_)开头。
    
    2.后续字符:在第一个字符之后,标识符可以包含字母、数字(0-9)和下划线。
    
    3.大小写敏感:C语言是大小写敏感的,
    这意味着Variable和variable被视为两个不同的标识符。
    
    4.保留字:不能使用C语言的保留字作为标识符,
    例如int、if、return等。
    
    5.长度限制:标识符的长度通常有限制,虽然这个限制由编译器决定,
    但标准C语言规定前31个字符是保证有效的。
    
    6.可见性:标识符的可见性取决于它们的作用域,
    例如全局变量名在整个程序中都是可见的,而局部变量名只在定义它们的函数或代码块中可见。
    
    7.命名约定:虽然不是强制的,但通常有命名约定,
    比如驼峰命名法(camelCase)和下划线命名法(snake_case),这些约定有助于提高代码的可读性。
    
    

7.函数指针和指针函数:

  • 函数指针:存储函数地址的容器
  • 指针函数:返回地址的函数
  • //函数指针
    int (*func)(int *,...)
    
    //指针函数
    int *func(int xxx,...)

8.函数要考虑的两个问题:输入和返回

返回值 函数(输入值)

9.数组要考虑的两个问题:大小和多大的步长来访问,类比一下

10.标签:标识一段空间的首地址,就是常量指针

11.数组名和函数名,就是常量指针

12.()是运算符

13.仿函数:C语言中可以通过函数指针来实现类似仿函数的功能。函数指针可以指向不同的函数,从而在运行时根据需要调用不同的函数,这在某种程度上模拟了仿函数的行为。

14.把函数和括号看成一个整体,再向右或向左看

15.存printf

//printf是常量指针,本质上地址,可以被调用

#include<stdio.h>
void test01(){

printf("printf1 =%p\n",printf);
int (*my_show)(const char*,...)=(int (*)(const char*,...))(printf);
my_show("printf2 =%p\n",printf);
my_show("printf3 =%s\n","hello world");
}
int main(){
    test01();
}

16.数据区和代码区:基本数据类型负责数据区,函数负责代码区

17.强制类型转换:把函数声明的函数名删掉就行

int (*my_show)(const char*,...)=(int (*)(const char*,...))(printf);

int a=int ;

18.函数名:本质上是地址。

  • 直接写函数名
#include<stdio.h>
void test01(){

printf("printf1 =%p\n",printf);
int (*my_show)(const char*,...)=(int (*)(const char*,...))(printf);
my_show("printf2 =%p\n",printf);
my_show("printf3 =%s\n","hello world");
}
int main(){
    test01();
}
  • 直接写函数地址
#include<stdio.h>
void test01(){

printf("printf1 =%p\n",0x00403AA0);//0x00403AA0是printf的地址
int (*my_show)(const char*,...)=(int (*)(const char*,...))(0x00403AA0);
my_show("printf2 =%p\n",0x00403AA0);
my_show("printf3 =%s\n","hello world");
}
int main(){
    test01();
}

19.推荐写法:typedef

typedef void(*xxx)(int); //把一个变量变为这个类型的别名

void(*xxx)(int);//定义一个叫xxx的函数指针变量,这个指针按照输入参数为int
返回值为void的函数行为来调用

typedef void(*xxx)(int);//定义一个叫xxx的函数指针类型的别名,这个指针按照输入参数为int
返回值为void的函数行为来调用

typedef int len_t;

xxx signal(int sig,xxx func);

二、函数的输入参数意义

1.一个函数就是一个独立空间,空间之间通过拷贝传递信息

2.核心就是拷贝

3.只读和可写区分开

连续空间为了避免二义性,只读和可写区分开
const int *key,int num   非字符的连续空间 只读
int *key,int num         非字符的连续空间 可写 可被修改

const char*              字符的连续空间 只读
char*                    字符的连续空间 可写  可被修改             

4.strcpy和buf

三、函数返回值注意事项

1.返回值的本质:拷贝

2.面试必考的错误:

void test()
{ 
  int a;
  return &a;//经典错误,a的空间还给系统了,现在&a取到的不是a的地址
}

3.函数的返回值一旦是指针,那么这个指针指向的空间绝对不是局部区域。(重要结论要记住)

4.设计接口或使用别人的接口,这个指针一定指向:

a.数据区  static  静态空间

b.堆区  malloc    动态空间 堆空间

四、多个.c的编程原理

1.工程=

A:  接口1  接口2
B:  调用接口1  调用接口2
每个接口单独编译 最后链接汇总成一个独立的可执行文件

2.如果调用不正确,会报错“undefined reference”未定义符号

3.为了方便调用,IDE(核心是工程管理器) 工程管理器(如cmake),负责:哪些文件编译,哪些不编。如果编译了,那么以什么形式编译。


http://www.kler.cn/a/397439.html

相关文章:

  • C:原反补码
  • Android笔记(三十七):封装一个RecyclerView Item曝光工具——用于埋点上报
  • 六自由度双足机器人运动控制
  • 【Linux:IO多路复用(select、poll函数)
  • Java基础——多线程
  • STM32 学习笔记-----STM32 的启动过程
  • LeetCode100之环形链表(141)--Java
  • HashMap源码分析上-红黑树
  • 「Mac玩转仓颉内测版7」入门篇7 - Cangjie控制结构(下)
  • [系统安全] PE文件知识在免杀中的应用
  • Spring:DI依赖注入的方式
  • Kafka 到 Kafka 数据同步
  • 牛客挑战赛77
  • PHP反序列化靶场(php-SER-libs-main 第一部分)
  • Servlet⾥面的doPost-doGet和路路径匹配讲解(笔记)
  • 第 11 章 - Go语言函数
  • Python爬虫下载新闻,Flask展现新闻(2)
  • JS学习日记(jQuery库)
  • webman使用中间件验证指定的控制器及方法[青锐CC]
  • ubuntu20.04安装FLIR灰点相机BFS-PGE-16S2C-CS的ROS驱动
  • Redisson 中开启看门狗(watchdog)机制
  • 不用来回切换,一个界面管理多个微信
  • FPGA使用Verilog实现CAN通信
  • “高级Java编程复习指南:深入理解并发编程、JVM优化与分布式系统架构“
  • OpenCV双目立体视觉重建
  • 在openi平台 基于华为顶级深度计算平台 openmind 动手实践