【FFmpeg 系列】 C 语言(四)

1、HelloWorld
<!-- 导包 -->
#include <stdio.h>

<!-- main函数,argc:输入的参数个数,argv:字符串数组,每一项都代表一个具体参数 -->
int main(int argc, char *argv[]){
  // 打印
	printf("Hello World!\n");
  return 0;
}
2、VIM编译运行C程序
<!-- 第一步:新建一个.c文件 -->
vi helloworld.c
<!-- 第二步:编译.c文件(mac下使用的是clang编译器,linux下使用的是gcc编译器) -->
-g:输出debug信息,-o:输出可执行程序
clang -g -o helloworld helloworld.c 
<!-- 第三步:编译成功后运行 -->
./helloworld
3、C语言中常用基本类型
类型说明
整型:short、int、long16位2字节、32位4字节、32位4字节
浮点型:float、double32位4字节、32位4字节
字符型:char8位1字节
无符号型:void一般情况下不使用,指针的时候才会使用
  • 示例代码
#include <stdio.h>

int main(int argc, char *argv[]) {
    int a = 100;
    float b = 5.98;
    char c = 'Y';
    printf("a=%d\n", a);
    printf("b=%f\n", a);
    printf("c=%c\n", a);
    return 0;
}
4、常量与变量
  • 变量:内存中分配一小段空间,这一小段空间可以根据我们需要随时发生变化。
  • 常量:内存中分配一小段空间,这一小段空间一旦赋值之后就不能再改变。
  • int a = 0; //变量,可以再赋值
  • const int len = 256; //常量定义
  • 内存管理:
c语言内容管理
5、指针与数组
  • 指针:就是内存地址:void*、char*
  • 数组:char c[2]、int arr[10]
  • 示例代码:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    int *a, *b;
    a = (int *) malloc(sizeof(int));
    b = (int *) malloc(sizeof(int));
    *a = 1;
    *b = 2;
    int c[3] = {1, 2, 3};

    printf("addr of a:%p, %p, %d\n", &a, a, *a);
    printf("addr of b:%p, %p, %d\n", &b, b, *b);
    printf("addr of c:%p, %p, %d, %d, %d\n", &c, c, c[0], c[1], c[2]);
    return 0;;
}
6、结构体
struct st{
	int a; //成员 a
	int b; //成员 b
};
  • 示例代码:
#include <stdio.h>

struct st {
    int a;
    int b;
};

int main(int argc, char *argv[]) {
    struct st sst1;
    struct st sst2;

    sst1.a = 10;
    sst1.b = 20;
    sst2.a = 30;
    sst2.b = 40;

    printf("struct content is :%d, %d\n", sst1.a, sst1.b);
    printf("struct content is :%d, %d\n", sst2.a, sst2.b);
    return 0;
}
7、枚举类型
enum em{
	red_color = 0,
	green_color,
	black_color
};
  • 示例代码:
#include <stdio.h>

enum e_type {
    red = 0,
    greed,
    blue
};

int main(int argc, char *argv[]) {
    enum e_type et;
    et = red;
    printf("the color is %d\n", et);
    et = blue;
    printf("the color is %d\n", et);
    return 0;
}
8、算术运算与比较运算
  • 算术运算:【+、-、*、/、%】
  • 比较运算:【>、==、<、>=、<=、!=】
  • if/else 语句
  • for 语句
  • while 语句
9、函数
void func(int a){
	...
}

代码示例:

#include <stdio.h>

int sum(int a, int b) {
    return a + b;
}

int main(int argc, char *argv[]) {
    int result = sum(3, 5);
    printf("3+5=%d\n", result);
    return 0;
}
10、文件操作
  • 文件类型:FILE* file;
  • 打开文件:FILE* fopen(path, mode);
  • 关闭文件:fclose(FILE*);
#include <stdio.h>

int main(int argc, char *argv[]) {
    FILE *file;
    char buf[1024] = {0,};
    
    file = fopen("1.text", "a+");
    fwrite("Hello, World!", 1, 13, file);
    
    // 将角标放到文件的开头
    rewind(file);
    // 将文件内容角标为1至26的内容读取到buf中
    fread(buf, 1, 26, file);
    
    fclose(file);
    printf("buf:%s\n", buf);
    return 0;
}
11、C语言中的指针
  • 指针的物理意义?

    • 它就是内存中的一个地址
    • 指针本身运算
    • 指针所指内容的操作
  • 操作系统是如何管理内存的?

    • 栈空间:每进入一个函数的时候,操作系统会帮我们分配一小段空间,当我们退出函数的时候,操作控件又会帮我们回收这一小段空间。(一般情况下大小为4M到8M左右)
    • 堆空间:一旦你在某个函数分配了堆的空间之后,只要你知道它的地址,你其它函数中依然可以访问它;并且堆空间的内存分配和释放由你自己来操作。(一般情况下大小为几个G)
    • 内存映射: 磁盘用的文件可以映射到内存里面,映射之后我们只要对内存中的文件进行修改,磁盘中的文件也会相应发生改变,从而大大提高我们访问IO的操作。(常用于数据库)
  • 内存的分配与释放?

    • 分配内存:void* mem = malloc(size);
    • 释放内存:free(mem);
    • 注意:上面两者都是在堆空间中去操作的。
  • 内存泄漏?

    • 不断的想系统申请内存。
    • 申请的内存不同,也不释放。
    • 避免:你申请了堆内存,一定要记得释放。
  • 野指针?

    • 占用别人的内存称为野指针。通俗来讲:这个指针已经被释放掉,被释放掉之后别人就会去申请内存,又将它拿到别人去使用,这个时候你又去拿这个指针去访问,其实这个指针已经是野指针了,不受你控制,是属于别人的了,而你还拿到这个指针去访问,这个时候就会导致程序carsh。
  • 函数指针?

    • 返回值类型 (*指针变量名)([形参列表]);
    int func(int x);/* 声明一个函数 */
    int (*f)(int x);/* 声明一个函数指针 */
    f = func;/* 将func函数的首地址赋值给指针f */
    
    • 示例代码:
    #include <stdio.h>
    
    sum(int a, int b) {
        return a + b;
    }
    
    sub(int a, int b) {
        return a - b;
    }
    
    int main(int argc, char *argv[]) {
        int sumResult;
        int subResult;
        int (*f)(int, int);
    
        f = sum;
        sumResult = sum(3, 5);
        f = sub;
        subResult = sub(sumResult, 5);
    
        printf("3+5=%d\n", sumResult);
        printf("8-5=%d\n", subResult);
        return 0;
    }
    
12、编译器
  • gcc/clang -g -O2 -o test test.c -I… -L… -l
    • -g:输出文件中的调试信息
    • -O:对输出文件做指令优化(O1:不做指令优化,O2:2级别的指令优化)
    • -o:输出文件
    • -c:不需要输出文件
    • -I:指定头文件
    • -L:指定库文件位置
    • -l:指定使用哪个库(注意这是个小写的L)
  • 编译过程?
    • 预编译
    • 编译
    • 链接,动态链接/静态链接
    • 示例代码:
    第一步:创建一个.c的文件
    vim add.c
    #ifndef __MY_LIBRARY__
    #define __MY_LIBRARY__
    
    int add(int a, int b){
    	return (a+b);
    }
    
    #endif // __MY_LIBRARY__
    
    第二步:编译但不需要生成删除文件
    clang -g -c add.c
      
    第三步:生成静态库
    libtool -static -o libmylib.a add.o
    注意:在linux下生成静态库用ar命令,动态库用gcc;Mac下用libtool
      
    第四步:编写.h头文件和调用的.c文件
    - .h头文件(add.h)
    #ifndef __MY_LIBRARY__
    #define __MY_LIBRARY__
    
    int add(int a, int b);
    
    #endif
    - 调用的.c文件(testlib.c)
    #include <stdio.h>
    
    // 双引号代表优先在本地目录进行查找,当然也可以用<>
    #include "add.h"
    
    int main(int argc, char* argv[]){
    	printf("add=%d\n", add(3, 3));
    	return 0;
    }
    
    第五步:编译并指定头文件和库文件位置等等
    clang -g -o testlib testlib.c -I . -L . -lmylib
    - 这里的.代表就是在当前文件路径
    - 另外一种分两步的执行方式,如下:(与上面一步到位同理)
    - clang -g -c testlib.c
    - clang -o testlib testlib.c -I . -L . -lmylib
    
    第六步:运行及结果
    - 运行:./testlib
    - 结果:add=6
    
13、调试器原理
  • Linux和Mac下所使用的调试器是不同的,Linux下使用的是GDB,在Mac下使用的是LLDB,虽然它们不同,但是基本原理是相通的。

  • 编译输出带调试信息的程序(-g)。

  • 调试信息包含:指令地址、对应源代码以及行号。

  • 指令完成后,回调调试器。

  • GDB/LLDB常用命令:
    命令 | GDB | LLDB
    —|---|—
    设置断点 | b | b
    运行程序 | r | r
    单步执行 | n | n
    全部执行 | c | c
    跳入函数 | s | s
    跳出函数 | finish | finish
    打印内容 | p | p
    查看当前已设置好的断点列表 | break list | break list
    退出 | quit | quit

  • 操作示例:

第一步:将testlib加载到调试器
lldb testlib
  
第二步:设置断点为main函数
b main
  
第三步:使用上述列表各种命令自行操作
r/s/finish/n/c/p等等...

第四步:查看生成的信息
ls testlib*
cd testlib.dSYM/Contents/Resources/DWARF
dwarfdump testlib(使用dwarfdump工具查看)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值