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