嵌入式C语言总结

GCC是GNUCompilerCollection,用于将高级语言转化为机器码。编译过程包括预处理、编译、汇编和链接四个步骤。预处理处理#include和#define等,编译生成汇编代码,汇编转为机器码,链接则将所有.o文件合并。C语言中,define和include不在编译阶段处理,而是在预处理阶段。预处理错误通常涉及头文件找不到,可通过gcc-I指定路径。数据类型如int、char、float等,以及关键字如sizeof、return,都在C语言中扮演重要角色。
摘要由CSDN通过智能技术生成

GCC知识梳理

Q: GCC是什么?

GCC最初名称:GNU C Compiler; 随着其支持的语言越来越多,改称为:GNU Compiler Collection.
作用:将编程高级语言翻译为机器语言.

Q: C语言变成机器指令的过程?

gcc 根据文件后缀名(.c/.java/.cpp …)来调用对应的翻译服务.

Q: gcc工具的几个常用选项的意义?

-o 指令代表输出,该参数后衔接输出文件名
使用姿势: gcc 根据不同的版本,平台使用姿势上可能会有所不同,但是 (-o 输出文件名) 是标准
gcc 输入文件名 -o 输出文件名: gcc hello.c -o hello
gcc -o 输出文件名 输入文件名: gcc hello -o hello.c

-v -o 指令代表输出的同时,将翻译过程也输出到控制窗口

-D gcc条件编译指令,在宏的介绍中会有使用(见章节《gcc -D 条件宏编译指令》)

Q: gcc过程

step 0 预处理

cpp -o hello.i hello.c
cpp 指令的作用就是将 .c 文件输出为 .i 的文件; 相当于指令 gcc -E

step 1 编译

/usr/lib/gcc/x86_64-linux-gnu/11/cc1 -quiet -v -imultiarch x86_64-linux-gnu hello.c -quiet -dumpdir h2- -dumpbase hello.c -dumpbase-ext .c -mtune=generic -march=x86-64 -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccSiyn7M.s

/usr/lib/gcc/x86_64-linux-gnu/11/cc1 指令相当于 gcc -S; 该指令会将 .c 文件输出位 .s 文件;在上述的实际指令中,将 hello.c 输出为 /tmp/ccSiyn7M.s
例:gcc -S -o hell.s hello.c 等价于 /usr/lib/gcc/x86_64-linux-gnu/11/cc1 -o hell.s hello.c

step 2 汇编

as -v --64 -o /tmp/ccV00FrG.o /tmp/ccSiyn7M.s

as 指令将编译的产物 /tmp/ccSiyn7M.s 输出为 .o 文件;该指令的作用包含在 gcc -c 的指令中;gcc -c 的指令可以将 .c 或者 .s 文件输出为 .o .
例:as -o hell.o hell.s 等价于 gcc -c -o hell.o hell.s (gcc -c -o hell.o hello.c)

step 3 链接

/usr/lib/gcc/x86_64-linux-gnu/11/collect2 -o h hell.o + …(.o)

指令等价于 gcc -o h hello.c

Q: define 、include 是关键字吗?

不是,所谓关键字是需要编译阶段处理的字段,define/include 字段是在预处理阶段处理的

Q: C语言常见错误

预处理错误

#include 出错: not find

#include 使用:
#include “name” (先从当前工作目录下寻找,找不到会去系统库找)
#include <name> (去系统库寻找文件)

以上错误大部分时候都是发生找不到文件的错误,可能是文件夹目录层级不对,可以通过 gcc -I 指令来解决: gcc -I filePath -o h1 hello.c

编译错误

语法错误

链接错误

undefined reference …

multiple definition …

预处理的使用

#include 包含头文件

#define 宏 替换; 该阶段不进行语法检查,只有在编译阶段才会检查
#define 宏名 宏体

#define ABC 5+4
printf("number is %d \n", ABC*3) 
等同于
printf("number is %d \n", 5+4*3) 

#ifdef #else #endif 在章节《gcc -D 条件宏编译指令》有使用

预定义宏

//以下宏适用于调试

__FUNCTION__  			: 函数名
__LINE__				:行号
__FILE__				:文件名

例:
int main(){
	//输出结果:“the main.c, main, 5”
	printf("the %s, %s, %d", __FILE__, __FUNCTION__, __LINE__);
}

gcc -D 条件宏编译指令

gcc -DABC =>> 该指令等价于在 cpp(预处理) 之前定义宏 ABC = #define ABC
例:通过预处理指令和 gcc -D 的调试指令来分别发行版本和调试版本

//代码如下
#include <stdio.h>

int main(){
	#ifdef ABC
		printf("======== %s, %s, %d ========\n", __FILE__, __FUNCTION__, __LINE__);
	#endif
	printf("hello world!! \n");
}

正式版本编译指令: gcc -o build main.c
输出如下:hello world!! 

调试版本编译指令: gcc -DABC -o build main.c
输出如下:
======== main.c, main, 6 ========
hello world!! 

宏展开下的 # 、##

单个 # 表示,字符串化
双 # 表示,连接符号

#include <stdio.h>

#define ABC(x) #x
#define DAY(x) myday##x
int main(){
    printf(ABC(123\n));

    int myday1 = 10;
    int myday2 = 20;
    printf("this day is %d \n", DAY(1));
    printf("this day is %d \n", DAY(2));
    return 0;
}

输出如下:
在这里插入图片描述

C语言常用关键字及运算操作符

关键字

编译器 预先定义了一定意义的 字符串

sizeof

编译器给开发者用于查看变量对应类型占用内容空间大小的工具

#include <stdio.h>

int main(){
    int a;
    long b;
    printf("this a size is %d \n", sizeof a);
    printf("this b size is %d \n", sizeof(b));
    return 0;
}

//运行结果:
this a size is 4 
this b size is 8 

return

返回的概念

数据类型

数据类型可以理解为对当前变量所代表的这一块内存定义了它的属性

char

硬件芯片操作的最小单位:bit (只存在两种状态:1 / 0)
软件操作的最小单位:8bit == 1B(byte)

char 体现的是硬件能够操作的体现在软件层面的最小单位

int

编译器最优的处理大小(int的大小由编译器决定):
系统一个周期,所能接受的最大处理单位,int
32位系统 4B(4byte) int
16位系统 2B(2byte) int

PS:char 更多是与硬件相关的时候使用

int 表示八进制: int a = 010; // 此处表示的值为 8
int 表示十六进制: int a = 0x10; // 此处表示的值为 16

long、short

特殊长度的限制符

unsigned、signed

当前关键字决定了数据所在内存空间的最高位,表示的是符号还是数据

unsigned : 无符号: 在表示数据的时候用的较多
signed: 有符号 : 在表示数字的时候用的较多

int a =>> signed int a : 不写 signed/unsigned ,编译器默认为 signed

float、double

大小:
float 4B
double 8B

浮点型常量
1.0、1.1 这种写法会被编译器默认为 double
1.0f、1.1f 这种写法会被编译器默认为 float

void

无意义,或者无的意思, 更多的时候表示的是语义符号
例1:void a;
该代码的意思是,声明了一个变量,但是具体是什么类型是未知的,仅仅表示有这么一个变量名的存在,具体的使用在后续代码中(比如强制类型转换等操作,这里可以理解为占位符).
例2:void funname();
该函数无返回值. 此处的 void 就是典型的语义意义的符号,表示无返回.

自定义数据类型:struct、union、enum、typedef

存在的意义:C编译器默认定义的内存分配不符合实际资源的形式; 简单来说就是基本数据类型(char、short、int、long、float、double)无法满足实际需求。

自定义 = 基本数据类型的集合

struct

元素之间的和

struct myabc{
	unsigned int a;
	unsigned int b;
	unsigned int c;
	unsigned int d;
};

struct myabc mybuf;
union

共用起始地址的一段内存; 主要应用于技巧型的代码

union myabc{
	char a;
	int b;
};

union myabc mybuf;
enum

enumerate – 列举
解释:被命名的整型常数的集合

typedef

数据类型的别名
int a :此处 a 表示int类型的一个变量
typedef int a : 此处 a 表示int类型的别名

在C语言中一般对类型别名的定义为: xxx_t

逻辑结构关键字

if、else

switch、case、default
语法:
switch(整型){
case case1:
break;
case case2:
break;
}

do、while、for

continue、break、goto

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值