音视频C语言基础快速复习

Posted 后端码匠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了音视频C语言基础快速复习相关的知识,希望对你有一定的参考价值。


C语言基础快速复习

认识C文件的代码结构

//
// Created by Neo on 2022/8/30.
//

#include <stdio.h>

//声明文件 .h .hpp
//<> 表示寻找系统的资源
//"" 表示寻找开发者定义的声明文件
//.c .cpp 实现文件
//代码结构
//main 函数只能存在一个
int main() //函数的入口
printf("你好,Hello, World!\\n");
// getchar();// 阻塞 用户输入

return 0;

基本数据类型

//
// Created by Neo on 2022/8/30.
// 基本数据类型
//
#include <stdio.h>

int main()
int i = 100;
double d = 200;
float f = 200;
long l = 100;
short s = 100;
char c = d;
// 字符串
char *str = "Neo";

//打印需要占位
printf("i的值是%d\\n", i); // d == 整形
printf("d的值是%lf\\n", d); // lf == long float 双精度
printf("f的值是%f\\n", f); // f == float
printf("l的值是%d\\n", l); // d == 整形
printf("s的值是%d\\n", s); // s == short
printf("c的值是%c\\n", c); // c == char

printf("字符串:%s\\n", str); // Neo

return 0;
i的值是100
d的值是200.000000
f的值是200.000000
l的值是100
s的值是100
c的值是d
字符串:Neo

占用字节数

//
// Created by Neo on 2022/8/30.
// 占用的字节数
//
#include <stdio.h>

//基本类型占用的字节数 sizeof 判断占用的字节数
int main()
printf("int 占用的字节数:%lu\\n", sizeof(int));//4
printf("double 占用的字节数:%lu\\n", sizeof(double));//8
printf("char 占用的字节数:%lu\\n", sizeof(char));//1
return 0;//NULL == 0
int 占用的字节数:4
double 占用的字节数:8
char 占用的字节数:1

初识指针

指针存储的永远都是内存地址

//
// Created by Neo on 2022/8/30.
//
#include <stdio.h> //stdio 标准库

// C 万物皆指针
// Linux 万物皆文件
int main()
//指针 == 地址

//例如 基本变量存储在栈中,栈也会由编译器分配一个地址来存储变量的值
int number = 10000;
// %p 输出地址的占位
// & == 取址
printf("number在内存中的地址:%p\\n", &number);//0x16ce46fb8

//任何变量都是地址 使用地址获取值
// * == 取出地址存储的值
printf("获取number地址的值:%d\\n", *(&number));//10000

//指针永远存放的是内存地址
int *intp = &number;
printf("获取指针变量:%p\\n", intp);//指针变量 存储的永远是内存地址 0x16ce46fb8
printf("获取指针变量内存地址的值:%d\\n", *intp);//获取地址的值 10000

//int * 表示int类型的指针
//内存地址就是指针,指针就是内存地址
//intp 指针别名、指针变量
*intp = 300;//修改了&number地址存储的值,那么number的值也会修改
printf("number:%d\\n", number);//300

return 0;
number在内存中的地址:0x16ce46fb8
获取number地址的值:10000
获取指针变量:0x16ce46fb8
获取指针变量内存地址的值:10000
number:300

声明函数

函数不能写在main()的下面

//
// Created by Neo on 2022/8/30.
//
#include <stdio.h> //stdio 标准库

//函数 在C语言中函数必须放在main函数的前面
//void change()
// printf("123");
//
// 或者先声明在使用
void change(int i);

//C语言不允许函数重载的 Java和C++是可以的
void change2(int *i);

/**
* 交换两个变量的值
* @param a
* @param b
*/
void swap(int *a, int *b)
int temp = *a;
*a = *b;
*b = temp;


int main()
int i = 100;
change(i);
printf("%d,地址:%p\\n", i, &i);//100 0x16f916fb8 i的值并没有改变 因为和change的形参i的地址是不一样的
change2(&i);
printf("%d,地址:%p\\n", i, &i);//100 0x16f916fb8 i的值改变了
int a = 10;
int b = 11;
swap(&a, &b);
printf("交换后的结果:%d,%d\\n", a, b);//11,10
return 0;


//根据声明实现函数
void change(int i)
printf("change->i:%p\\n", &i); //0x16f916f6c
i = 200;


//使用指针
void change2(int *i)
printf("change2->i:%p\\n", i); //0x16f916fb8 传入的是main中i的地址
*i = 200;//修改地址中的值
change->i:0x16f916f6c
100,地址:0x16f916fb8
change2->i:0x16f916fb8
200,地址:0x16f916fb8
交换后的结果:11,10

多级指针

//
// Created by Neo on 2022/8/30.
//
#include <stdio.h> //stdio 标准库

//多级指针
int main()
int num = 100;

int *num_p = &num;//num的内存地址

int **num_p_p = &num_p;//num_p的内存地址

int ***num_p_p_p = &num_p_p;//三级指针

printf("num_p:%p,num_p_p:%p\\n", num_p, num_p_p);//num_p:0x16d0befb8,num_p_p:0x16d0befb0

printf("num_p:%p\\n", *num_p_p);//取出num_p_p存储的值 num_p:0x16d0befb8

printf("num:%d\\n", **num_p_p);//num:100 *num_p_p == &num **num_p_p = num

//多级指针的意义

return 0;
num_p:0x16d0befb8,num_p_p:0x16d0befb0
num_p:0x16d0befb8
num:100

数组与指针

//
// Created by Neo on 2022/8/30.
//
#include <stdio.h> //stdio 标准库

//数组与指针
int main()

int arr[] = 1, 2, 3, 4;

//如下遍历数组在其他平台上会报错
// for (int i = 0; i < 4; ++i)
//
//

//规范的写法 在其他平台没有问题的
int i = 0;
for (i = 0; i < 4; i++)
printf("%d\\n", arr[i]);

//数组的内存地址 == 第一个元素的内存地址
printf("arr == %p\\n", arr);//arr == 0x16dda2fa0
printf("&arr == %p\\n", &arr);//&arr == 0x16dda2fa0
printf("&arr[0] == %p\\n", &arr[0]);//&arr[0] == 0x16dda2fa0
printf("%d\\n", *(arr));//1 第一个元素

//将数组的内存地址赋值给指针
int *arr_p = arr;

//使用指针遍历数组
for (i = 0; i < 4; i++)
printf("%d\\n", *(arr_p + i));
printf("%p\\n", arr_p + i);//内存地址会相差4,因为int占用4个字节

printf("*arr_p:%d\\n", *arr_p);//由于arr的内存地址指向了第一个元素,所以取值就是第一个元素 1
//指针位移,由于数组内存地址是连续的所以指针+1就是第二个元素
arr_p++;
printf("*arr_p:%d\\n", *arr_p);//取值就是第一个元素 2

return 0;
1
2
3
4
arr == 0x16dda2fa0
&arr == 0x16dda2fa0
&arr[0] == 0x16dda2fa0
1
1
0x16dda2fa0
2
0x16dda2fa4
3
0x16dda2fa8
4
//
// Created by Neo on 2022/8/30.
//
#include <stdio.h> //stdio 标准库

//数组与指针
int main()
int arr[4];

int *arr_p = arr;//指向数组元素的第一个元素的地址

for (int i = 0; i < sizeof arr / sizeof(int); ++i)
*(arr_p + i) = i + 1000;//通过指针给数组赋值


//sizeof arr = arr 是有4个int,也就是16个字节,所以计算数组的长度就是数组的字节数/类型的字节数
for (int i = 0; i < sizeof arr / sizeof(int); ++i)
//两种取数组值的方式
printf("%d\\n", *(arr_p + i));
printf("%d\\n", arr_p[i]);


//指针占用的内存大小是4个字节
printf("指针占用的字节大小:%d\\n", sizeof(arr_p));//64位:8字节 32位:4个字节
return 0;
1000
1000
1001
1001
1002
1002
1003
1003

函数指针

函数指针 - 相当于java接口的回调

//
// Created by Neo on 2022/8/30.
//
#include <stdio.h> //stdio 标准库

void add(int num1, int num2)
printf("num1 + num2 = %d\\n", (num1 + num2));


void sub(int num1, int num2)
printf("num1 - num2 = %d\\n", (num1 - num2));


//操作回调
//void(*method)(int, int) -> 声明的函数指针
//void -> 返回值
//(*method) -> 函数名
//(int,int) -> 两个参数
void operate(void(*method)(int, int), int num1, int num2)
method(num1, num2);


void callBackMethod(char *fileName, int current, int total)
printf("压缩的文件:%s,进度:%d/%d", fileName, current, total);


void compress(char *fileName, void(*callback)(char *, int, int))
//开始压缩图片 压缩进度回调
callback(fileName, 5, 100);


//函数指针 - 相当于java接口的回调
int main()
//函数add就是在内存中的地址 add和&add是一样的
printf("add的地址:%p\\n", add);//add的地址:0x1011a0be0
printf("&add的地址:%p\\n", &add);//&add的地址:0x1011a0be0

operate(add, 1, 2);//num1 + num2 = 3

operate(sub, 2, 1);//num1 - num2 = 1

// void (*call)(char *, int, int) = callBackMethod;

//兼容性问题,先声明在使用
void (*call)(char *, int, int);//定义函数指针
call = callBackMethod;//给函数指针赋值

compress("1.png", call);

return 0;

C 函数库

//
// Created by Neo on 2022/8/30.
//
#include <stdio.h> //stdio 标准库
#include <stdlib.h>
#include <time.h>
#include <string.h>

//C函数的使用
int main()
//初始化随机数发生器函数
srand((unsigned) time(NULL));

int i;
for (i = 0; i < 10; ++i)
printf("随机数:%d\\n", rand() % 100);//rand()获取随机数


//字符串拷贝函数
char str_arr[10];
char *str = "abcdefg";
strcpy(str_arr, str);// 将str拷贝到str_arr中
printf("%s\\n", str_arr);//abcdefg

return (0);//== return 0
随机数:45
随机数:91
随机数:83
随机数:29
随机数:20
随机数:72
随机数:11
随机数:57
随机数:49
随机数:97
abcdefg

静态/动态开辟内存

//
// Created by Neo on 2022/8/30.
//
#include <stdio.h> //stdio 标准库
// 动态开辟: malloc 在堆区开辟 内存空间 动态范畴
#include <stdlib.h>

//C 语言在开发中不能出现野指针和悬空指针
void dynamicAction()
int *p;//野指针 没有具体的指向

//申请在堆中开辟一段内存区域 返回void *:表示可以转换成任意类型int * double *....
int *arr = (int *) malloc(1 * 1024 * 1024);//申请堆区大小是1M

printf("arr自己的内存地址:%p,堆区的内存地址:%p\\n", &arr, arr);//arr自己的内存地址:0x16f16ef40,堆区的内存地址:0x160008000
free(arr);//释放申请的堆区
//释放堆区后,arr还是指向了堆区的内存地址,这就会有悬空指针的问题
printf("arr自己的内存地址:%p\\n", arr);//arr自己的内存地址:0x160008000
arr = NULL;//不设置null会可能为悬空指针 ,需要重新指向一块内存地址,因为free,arr还是指向了堆区的地址
printf("arr自己的内存地址:%p\\n", arr);//arr自己的内存地址:0x0
//malloc 申请堆区内存 free释放堆区
//函数弹栈后 不会自动释放堆区 如果不及时释放 会导致越来越大

/**
* 什么时候才会使用动态开辟呢?使用场景?
* 静态开辟的内存空间大小是不能改变的
*/
int main()
for (int i = 0; i < 2; ++i)
dynamicAction();
//arr自己的内存地址:0x16f16ef40,堆区的内存地址:0x160008000


int arr[6];//静态开辟 空间大小是不能改变的,静态开辟会自动回收安全可靠

//开辟的空间想要变化 需要使用动态开辟
int num;
printf("请输入个数:");
//获取用户输入的值
scanf("%d", &num);
//动态开辟
int *arr2 = (int *) malloc(sizeof(int) * num);

int result;
for (int i = 0; i < num; ++i)
printf("请输入第%d\\n", i);
scanf("%d", &result);
arr2[i] = result;


//改变内存的大小
int *new_arr = (int *) realloc(arr2, num * 2);
//new_arr != null 表示开辟成功
if (new_arr) // == new_arr != NULL
for (int i = 0; i < num; ++i)
printf("得到新的内存:%d\\n", new_arr[i]);



//改变内存大小的地址:0x15b004080,原有的内存地址:0x15b004080 是同一个地址
printf("改变内存大小的地址:%p,原有的内存地址:%p\\n", new_arr, arr2);


if (new_arr)
free(new_arr);
new_arr = NULL;

//原有的指针也需要置为NULL 否则成为悬空指针
//改变内存大小的地址:0x0,原有的内存地址:0x15b004080
printf("改变内存大小的地址:%p,原有的内存地址:%p\\n", new_arr, arr2);

return 0;
arr自己的内存地址:0x16f16ef40,堆区的内存地址:0x160008000
arr自己的内存地址:0x160008000
arr自己的内存地址:0x0
arr自己的内存地址:0x16f16ef40,堆区的内存地址:0x160008000
arr自己的内存地址:0x160008000
arr自己的内存地址:0x0
请输入个数:3
请输入第0
12
请输入第1
22
请输入第2
23

字符串常见操作

int main() 
//通过数组创建字符串
char str[] = H, e, l, l, o, \\0;
str[2] = r;
//注意printf 必须遇到\\0才会结束否则会有乱码问题,在数组的末尾加上\\0
printf("第一种方式:%s\\n", str);//第一种方式:Hello烫烫烫蹄鼭L?╔s?

//通过指针创建字符串
char *str2 = "Hello";// 默认会在末尾加上\\0结束符号
printf("第二种方式:%s\\n", str2);
str2[2] = r;//这里会崩溃?? 不允许访问 但是IDE没有问题呢? 因为str2指向的是一个地址
printf("第二种方式:%s\\n", str2);

return 0;
第一种方式:Herlo
第二种方式:Hello

在现代操作系统中,可以将一段内存空间设置为“读写数据”、“只读数据”等等多种属性,一般编译器会将"Hello"字面量放到像".rodata"这样的只读数据段中,修改只读段会触发 CPU 的保护机制(#GP)从而导致操作系统将程序干掉。

rodata的意义同样明显,ro代表read only,即只读数据(const)

字符串常见操作

#include <stdio.h> //stdio 标准库
#include <ctype.h>
/**
* 把字符串全部转换为小写
* @param dest
* @param name
*/
void lower(char *dest, char *name)
//不要破坏name指针的地址,否则外部的也会改变
char *temp = name;
while (*temp)
//一个个字符的转换
*dest = tolower(*temp);
//挪动指针
temp++;
dest++;

//dest指针的地址指向了最后
*dest = \\0;//避免打印系统值


/**
* 截取字符串
* @param result 截取的结果
* @param dest 目标字符串
* @param start 开始的位置
* @param end 结束的位置
*/
void cutout(char *result, char *dest, int start, int end)
if (start > end)
*result = \\0;

//不要破坏dest
char *temp = dest;
temp += start;
for (int i = start; i < end; ++i)
*result = *temp;
result++;
temp++;

*result = \\0;


/**
* 第三种方式
* @param result
* @param dest
* @param start
* @param end
*/
void cutout3(char *result,char *dest,int start,int end)
//简化写法
for (int i = start; i < end; ++i)
*(result++) = *(dest+i);



/**
* 截取字符串
* @param result 截取的结果
* @param dest 目标字符串
* @param start 开始的位置
* @param end 结束的位置
*/
void cutout(char *result,char *dest,int start,int end)
if (start > end)
*result = \\0;

//不要破坏dest
char * temp = dest;
temp+=start;//直接讲地址移动到开始的位置
for (int i = start; i < end; ++i)
*result = *temp;
result++;
temp++;

*result = \\0;


/**
* 第四种方式
*/
void cutout4(char *result,char *dest,int start,int end)
//参数1 赋值到容器中
//参数2 直接从start的位置开始
//参数3 copy的个数
strncpy(result,dest+start,(end-start));

结构体

声明结构体,及结构体赋值

//
// Created by Neo on 2022/8/30.
//
#include <stdio.h> //stdio 标准库
#include <string.h>

/**
* 结构体就相当于Java中的类的概念
* @return
*/
struct Dog
//定义成员
char name[10];
char *n;//可以直接赋值
int age;
char sex;
g1 = "gs", "g", 2, M, g2 = "g3", "g", 4, G, g3; //结尾必须有;结束符号


int main()
//使用结构体
struct Dog dog;//这样写完是没有任务初始化的 成员默认值是系统值(乱码)
//赋值操作
//注意数组赋值 需要使用strcpy api函数
strcpy(dog.name, "小龙");
dog.age = 3;
dog.sex = G;

printf("name:%s,age:%d,sex:%c\\n", dog.name, dog.age, dog.sex);//name:旺财,age:3,sex:G

//直接使用
g3.n = "123";//指针不用使用strcpy 进行赋值
printf("name:%s,age:%d,sex:%c\\n", g1.name, g1.age, g1.sex);//name:gs,age:2,sex:M

return 0;
name:小龙,age:3,sex:G
name:gs,age:2,sex:M

结构体嵌套

//
// Created by Neo on 2022/8/30.
//
#include <stdio.h> //stdio 标准库

struct Study
char *studyContent;//学习内容
;

//结构体嵌套
struct Student
char name[10];
int age;
char sex;
struct Study study;//Clion工具的写法
// Study st;vs的写法
struct Wan
char *wanContent;
wan;//定义结构体别名
;

int main()
//使用结构体
struct Student student = "hq", 18, N,
"学习C语言",
"游戏"
;
//获取嵌套的结构体
student.study.studyContent;
student.wan.wanContent;
printf("姓名:%s", student.name);
printf("爱好:%s", student.study.studyContent);
printf("爱好:%s", student.wan.wanContent);
return 0;
姓名:hq爱好:学习C语言爱好:游戏

结构体指针

//
// Created by Neo on 2022/8/30.
//
#include <stdio.h> //stdio 标准库
#include <string.h>
#include <stdlib.h>
//#include <malloc.h>

struct Cat
char name[10];
int age;
;

int main()
//栈区
//声明结构体
struct Cat cat = "猫马上", 2;
//结构体指针
//vs的写法:Cat *catp = &cat;
struct Cat *catp = &cat以上是关于音视频C语言基础快速复习的主要内容,如果未能解决你的问题,请参考以下文章

JavaSE复习基础巩固

C基础复习

Python基础语法复习

快速排序复习

51Nod 1046 A^B Mod C(日常复习快速幂)

如何快速学习Python?