C语言的编译
1.C语言的主要标准版本
- 1972诞生,Dennis Ritchie 设计。
- ANSI C89,于1989年由ANSI发布
- C90和ANSI C89是一个标准,只不过C90是由ISO组织发布,后续的版本也是由ISO采纳发布。
- C99 新特性:
- 支持单行注释//
- 允许变长数组
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int n = atoi(argv[1]); // int a[n] = {};//不能初始化,否则编译报错error: variable-sized object may not be initialized int a[n]; printf("%d %ld\n", n, sizeof(a)); return 0; } - 支引入布尔类型
- 支持内联函数
- 允许在表达式中直接创建匿名的结构体或数组
print((struct position){0, 1}); print((int[]){1, 2});
- C11 新特性:
- 引入多线程和原子操作
- 引入_Generic关键字,支持泛型编程。
- 引入_Noreturn关键字,声明一个函数不会返回。
- 允许在结构体和联合体中定义匿名成员
- 引入了<stdbounds.h>头文件,用于边界检查
- C17 主要是对C11的小幅度更新和修正,没有引入重大新特性。
- C23 标准进一步现代化了C语言,引入了许多新特性。
- 允许在字符串字面量之间使用空格进行连接,而不需要使用反斜杠
#include <stdio.h> int main() { const char *message = "Hello, " "C23!"; printf("%s\n", message); return 0; } - 引入了内置的动态数组类型,使用[]语法可以更方便地创建和管理动态数组
#include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { int n = 5; int arr[] = new int[n]; // 创建动态数组 for (int i = 0; i < n; i++) { arr[i] = i; } for (int i = 0; i < n; i++) { printf("%d ", arr[i]); } printf("\n"); delete[] arr; // 释放动态数组 return 0; } - 引入了[[attributes]]语法,用于指定函数或变量的属性。
- 增强了_Generic关键字的支持。
- 引入了许多新的库函数,如strdup、strndup等。
- 允许在字符串字面量之间使用空格进行连接,而不需要使用反斜杠
2.gcc 编译指定版本
gcc *.c -std=<version>
gcc -Wall foo.c -o foo -std=C89
使用gcc作为编译器时,由于GNU C对标准进行了一些扩展,导致在指定版本编译时支持了标准版本不支持的特性。
可以使用-pedantic告诉编译器,仅使用指定的标准,不进行扩展,如果涉及到扩展进行警告。
使用-pedantic-errors,仅使用指定的标准,不进行扩展,如果涉及到扩展报错。
test.c
#include <stdio.h>
#include <stdlib.h>
void print(int *a)
{
printf("%d\n", a[0]);
}
int main(int argc, char *argv[])
{
print((int[]){1, 2});
return 0;
}
代码使用了c99的特性
dhl@dhl:~$ gcc test.c -std=c89
dhl@dhl:~$
正常时不应该编译成功的,实际编译成功,因为gcc 扩展了GUN C
dhl@dhl:~$ gcc test.c -pedantic -std=c89
test.c: In function ‘main’:
test.c:12:18: warning: ISO C90 forbids compound literals [-Wpedantic]
12 | print((int[]){1, 2});
| ^
使用-pedantic,不适用GNU扩展,产生警告,但会编译通过,能够运行
dhl@dhl:~$ gcc test.c -pedantic-errors -std=c89
test.c: In function ‘main’:
test.c:12:18: error: ISO C90 forbids compound literals [-Wpedantic]
12 | print((int[]){1, 2});
| ^
使用-pedantic-errors,不适用GNU扩展,产生编译错误
3.查看本地gcc默认支持版本
在man gcc中搜索 default for C code

4.开源软件编译
4.1 本地编译
一般开源软件会有README文档,指导编译,通常的流程如下:
./configure --prefix=<installPath>
make
make install
installPath是想要安装应用的绝对路径,一般会在路径下生成bin lib等目录,包含生成的可执行文件、依赖库等。
也可能会遇到没有configure的情况,这是需要使用autoreconf工具,这个工具可以根据configure.ac 文件和 Makefile.am 模板,生成 configure 脚本。
如果系统没有命令则安装工具和依赖,Ubuntu系统下可以使用命令sudo apt-get install automake autoconf libtool
在使用autoreconf -ivf生成configure
4.2交叉编译
交叉编译可能会碰到各种问题,比如需要先行交叉编译依赖库,在编译时指定依赖库等等,后面补充具体实例

浙公网安备 33010602011771号