目录
static静态变量
使用 static 修饰的变量就是静态变量, 静态局部变量 ,静态全局变量
1.静态局部变量 只能被初始化1次 ,存储在数据段,不会释放。
2.静态全局变量,只能在当前文件使用,无法跨文件使用,防止全局变量名冲突。
static静态函数
static 修饰函数只能在当前文件使用,防止与其他文件的函数名冲突
比如:
test.c文件
// 设置为静态函数,只能在当前文件调用,不会与 test1.c 里面的show名字冲突
static void show(){
printf("static 2024-7-23 14:30:59\n");
}
void test(){
printf("test 今日的时间:");
show();
}
test1.c
void show(){
printf("2024-7-23 14:30\n");
}
void test1(){
printf("test1 今日的时间:");
show();
}
test.c和test1.c文件中虽然都有show()函数,但是test.c中的是静态函数,所以最后在main函数中调用的时候,只会调用test1.c中的show函数
const常量
常量不能被修改,系统不会检查常量的变化
但是如果去修改常量所在地址的值,常量还是会被修改
如:
#include <stdio.h>
int main()
{
const int a = 100;
int *p = &a;
*p = 200;
printf("%d", a);
}
输出a等于200
所以引用常量指针的概念
int value = 10;
const int val = 100;
const int *p = &value; // 常量指针,无法修改地址上的内容
int const *p1 = &value; // 常量指针,无法修改地址上的内容
int *const p2 = &value; // 指针常量, 指针指向的地址无法修改
const int *const p3 = &value; // 常量指针常量,无法修改地址上的内容,无法修改指针指向的地址
//----修改地址上的内容----------
*p = 123; // 修改地址上的内容 ,错
*p1 = 123; // 修改地址上的内容,错
*p2 = 123; // 可以的
*p3 = 123; // 修改地址上的内容 ,错
//----修改指针的,指向---------
p = &val;
p1 = &val;
p2 = &val; // 不可以,指针常量,无法修改指向
p3 = &val; // 不可以
C语言其他关键字
声明value是一个自动变量,但是现在的编译自动会处理,不需要声明,在cpp中已经被废弃了,并修改了功能
auto int value = 100;
寄存器变量, 把tmp 存储到CPU寄存器中,而不是内存中。寄存器的访问效率比内存高!
所以一些经常访问的变量,可以设置为寄存器变量,提高访问效率。
现在的编译器,都会自动把访问频繁的变量放入寄存器中
register int tmp = 100;
不可忽略变量,易变变量。 如果在CPU 中做一些空循环,
编译器有可能会忽略,如果不想编译器忽略,则需要把变量声明,为volatil
在单片机中应用比较多
volatile int val = 100;
//例如
for (int val = 0; val < 100000; val++); // 该循环没有任何意义,某些编译器会直接忽略掉。
extern关键字
外部变量,多文件编写时能实现跨文件的访问
例如
xxxx.c
//声明全局变量a,b不在当前文件中
extern int a;
extern int b;
void swap()
{
temp = a;
a = b;
b = temp;
printf("a = %d, b = %d", a, b);
}
main.c
#include <stdio.h>
int a = 10, b = 20; //定义全局变量
void swap(); //声明
int main()
{
void swap(); //调用
}
inline 内联函数
如果用户不想一个函数发生进栈与出栈的操作,用户可以把一个函数设置为 inline 内联函数,这样代码就会直接内嵌到程序中,不发生任何的栈操作,提高执行效率。
函数封装使得我们的程序模块化,开发和维护都变得更简单,但是函数调用的一个代价是需要消耗一定的时间进行切换,这段时间用来保存现场和恢复现场,比如在执行函数A的时候,中途调用函数B,那么在调用前一刻必须将函数A的执行状态记录下来,包括些寄存器的值,当下的执行地址等,以便于将来执行完函数B返回之后,可以继续原来的状态执行下去。
#include <stdio.h>
//一定要先声明max内联函数,否则找不到该函数,已经内嵌到代码中。
int max(int x, int y);
// 声明并定义内联函数
inline int max(int x, int y){
int z = 0;
z = x > y ? x : y;
return z;
}
int main()
{
int x = 10, y = 20;
int tmp = max(x, y);
printf("tmp=%d\n", tmp);
}
递归函数
在函数中调用函数.
回调函数
用函数指针,指向一个函数,并调用该函数,这种设计方法是实现C 语言的多态
多态:一个函数接口拥有不同的功能状态。 一个接口实现多种功能,提高代码的复用性
多态是面向对象的基石
比如封装一个比较大小的函数
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
// bool (*cmp)(void *, void *) 指向一个比较两个数据的方法
bool big(bool (*cmp)(void *, void *), void *a, void *b) //调用某个函数的地址
{
if (cmp(a, b))
{
return true;
}
else
{
return false;
}
}
比较整形方法
bool cmp_int(void *a, void *b)
{
int *p = a;
int *q = b;
return *p > *q;
}
// 比较浮点
bool cmp_float(void *a, void *b)
{
float *p = a;
float *q = b;
return *p > *q;
}
// 比较字符串
bool cmp_string(void *a, void *b)
{
char *p = a;
char *q = b;
if (strcmp(p, q) == 0)
{
return true;
}
else
{
return false;
}
}
int main()
{
int a = 200, b = 100;
printf("%d\n", big(cmp_int, &a, &b)); // 修改比较方法 cmp_int
float f = 3.14;
float f1 = 2.33;
printf("%d\n", big(cmp_float, &f, &f1)); // 修改比较方法 cmp_float
char *s = "1234";
char *s1 = "12314";
printf("%d\n", big(cmp_string, s, s1)); // 修改比较方法 cmp_float
}
gcc定义编译多个文件
比如以下三个文件
xxxx.h
#ifndef STR
#define STR
{
//函数声明;
}
#endif
xxxx.c
#include "xxxx.h" //注意,一定要是双引号引用头文件,< >会报错
{
//函数的定义;
}
main.c
#include <stdio.h>
#include "xxxx.h"
int main()
{
函数的调用
}
编译方法:
gcc main.c xxxx.c -o main && ./main
字符串函数,数据转换函数.......更多函数,参见Linux-c函数库