当前位置: 首页 > news >正文

GCC 对 C 语言的扩展

大家好!我是大聪明-PLUS

GNU 编译器集合 (GCC) 提供了 ISO 标准 C 中没有的几种语言功能。

在我撰写本文时,GCC 拥有超过60个不同的拓展,它们可以改变 C 语言(以及 C++)的行为或添加功能。其中一些扩展非常有趣,另一些则有点令人困惑,还有一些则有些危险!

了解这些 GCC 扩展非常重要,因为其中许多扩展被多个免费和开源项目使用,包括 Linux 内核。

让我们来看看其中的一些吧?

嵌套函数

GCC 允许声明嵌套函数(在另一个函数内部定义的函数)。

嵌套函数的名称将是其定义块的本地名称,并且可以访问其定义点可见的包含函数的所有变量。

 123456789
10
#include int main(int argc, const char *argv[])
{ void p (void) { printf("Inside a nested function!n"); } p(); return 0;
}
$ gcc nested.c -Wall -Werror -o nested
$ ./nested
Inside nested function!

typeof 关键字

我们可以使用typedef关键字来引用表达式的类型,从而可以在 C 中进行泛型编程!

例如,下面的max(a,b)宏可对任何算术类型进行操作:

 123456789
10
11
12
13
14
15
16
17
18
19
#include #define max(a,b) ({ typeof (a) _a = (a); typeof (b) _b = (b); _a > _b ? _a : _b; })int main(int argc, const char *argv[])
{ int x = 1024, y = 4096; char a = 10, b = 20; float j = 1.0, k = 2.0; printf("char max is %dn", max(a,b)); printf("int max is %dn", max(x,y)); printf("float max is %fn", max(j,k)); return 0;
}
$ gcc typeof.c -Wall -Werror -o typeof
$ ./typeof
char  max is 20
int   max is 4096
float max is 2.000000

空结构

GCC 允许 C结构没有成员(结构的大小为零)。

 123456789
10
11
#include struct empty {
}; int main(int argc, const char *argv[])
{ printf("sizeof struct empty is %ldn", sizeof(struct empty)); return 0;
}
$ gcc empty.c -Wall -Werror -o empty
$ ./empty
sizeof struct empty is 0

在 C++ 中,空结构是语言的一部分。

案例范围

在 GCC 中,我们可以在单个case标签中以"case start ... end ”的格式指定一系列连续的值。很疯狂吧?

这与适当数量的单独案例标签具有相同的效果,从startend(含)的每个整数值对应一个标签。

 123456789
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include void ranges(char c)
{ switch(c) { case '0' ... '9': printf("[%c] is a number.n", c); break; case 'a' ... 'z': printf("[%c] is a lowercase letter.n", c); break; case 'A' ... 'Z': printf("[%c] is an uppercase letter.n", c); break; default: printf("[%c] is not a valid character!n", c); break; }
} int main(int argc, const char *argv[])
{ ranges('a'); return 0;
}
$ gcc ranges.c -Wall -Werror -o ranges
$ ./ranges 
[a] is a lowercase letter.

零长度数组

GCC 允许声明零长度数组。

零长度数组可以用作结构体的最后一个元素,例如,用作可变长度对象的标头。在这种情况下,零长度数组的名称可以用作指向动态分配对象的指针。

 123456789
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include 
#include struct msg_header { int type; int size; char content[0];
}; int main(int argc, const char *argv[])
{ struct msg_header *msg; int size = 1024; msg = (struct msg_header *) malloc(sizeof (struct msg_header) + size); msg->type = 0x01; msg->size = size; printf("msg header is at %pn", (void *)msg); printf("msg content is at %pn", (void *)msg->content); return 0;
}
$ gcc array.c -Wall -Werror -o array
$ ./array
msg header  is at 0x55c428265260
msg content is at 0x55c428265268

还有许多其他扩展,但是我们真的应该使用它们吗?

我们应该使用 GCC 扩展吗?

所有示例均使用 GCC 7.4.0 编译。

这些扩展无需任何额外的编译器标志即可使用,因为默认情况下 GCC 7.4 使用-std=gnu11进行编译,这意味着支持 ISO C11 标准和 GCC 扩展。

虽然其中一些扩展确实很有用,但其代价是可移植性。使用 GCC 扩展,我们可能会在使用其他编译器构建程序时遇到问题。

例如,Clang有自己的一组扩展,并且不支持所有 GCC 扩展,如嵌套函数。

$ clang nested.c -o nested
nested.c:5:19: error: function definition is not allowed herevoid p (void) { printf("Inside a nested function!n"); }^
nested.c:7:5: warning: implicit declaration of function 'p' is invalid in C99 [-Wimplicit-function-declaration]p();^
1 warning and 1 error generated.

如果您想知道是否正在使用任何 GCC 扩展,请启用-pedantic编译器选项来生成警告或启用-pedantic-errors编译器选项来生成错误。

$ gcc arrayzero.c -o arrayzero -pedantic-errors
arrayzero.c:7:7: error: ISO C forbids zero-size array ‘content’ [-Wpedantic]char content[0];^~~~~~~

并且,如果您想使用 GCC 扩展并仍保持程序的可移植性,则可以使用宏__GNUC__进行条件编译来测试这些功能的可用性,该宏始终在 GCC 下定义。

GCC文档中提供了 C 语言的 GCC 扩展的完整列表。

现在来个挑战吧!你能通过阅读源代码,找到下面程序中使用的两个 GCC 扩展吗?

 123456789
10
11
12
13
#include int main(int argc, const char *argv[])
{ int a = 10; int x = 0; a = x ? : 0b0010; printf("a is %d.n", a); return 0;
}

文章转载自:

http://k32qxHFr.dhckp.cn
http://e1DVPlIT.dhckp.cn
http://7YZMt4Zj.dhckp.cn
http://O8FGq6Q9.dhckp.cn
http://199zLcjk.dhckp.cn
http://HAtkCBBB.dhckp.cn
http://lXzn2Xpw.dhckp.cn
http://28WOZizz.dhckp.cn
http://JV39lDit.dhckp.cn
http://xHRhiGgD.dhckp.cn
http://aHDU2ntz.dhckp.cn
http://mV73Ih7D.dhckp.cn
http://LMFPvBdK.dhckp.cn
http://igRU7203.dhckp.cn
http://jcRJNMXk.dhckp.cn
http://INC1WtcS.dhckp.cn
http://9VWuwhBV.dhckp.cn
http://Kt48GkY0.dhckp.cn
http://yPrEpF9k.dhckp.cn
http://t6lxgAJZ.dhckp.cn
http://nCVIbYcE.dhckp.cn
http://DjRK9Q3x.dhckp.cn
http://dLCN7xvU.dhckp.cn
http://5EuLsCiW.dhckp.cn
http://ek5ppXtQ.dhckp.cn
http://u2OQboda.dhckp.cn
http://wfrox2ji.dhckp.cn
http://8pYZDdG0.dhckp.cn
http://4epr95i2.dhckp.cn
http://gmbGNnIS.dhckp.cn
http://www.dtcms.com/a/378064.html

相关文章:

  • 基于STM32的智能语音识别饮水机系统设计
  • 基于ubuntu-base制作Linux可启动镜像
  • 速通ACM省铜第一天 赋源码(The Cunning Seller (hard version))
  • springboot+vue旧物回收管理系统(源码+文档+调试+基础修改+答疑)
  • Reactnative实现远程热更新的原理是什么
  • OCDM 波形通信感知一体化:从原理到 MATLAB 实现
  • 智源研究院新研究:突破物理世界智能边界的RoboBrain 2.0,将重构具身AI能力天花板
  • 容器应用学习笔记:containerd 篇
  • [特殊字符]AutoSQT 2025第二届汽车软件质量与测试峰会开幕首日盛况直击
  • MCP模型上下文协议以及交互流程
  • iOS App 性能监控与优化实战 如何监控CPU、GPU、内存、帧率、耗电情况并提升用户体验(uni-app iOS开发调试必备指南)
  • (Arxiv-2025)重构对齐提升了统一多模态模型的性能
  • 在亚马逊平台激烈的竞争赛道上
  • AI驱动的知识管理指南:基于Atlassian Intelligence和Rovo构建企业级知识管理系统
  • Redis 键(Key)的命令
  • 【bat工具】在文件夹一堆文件中快速查找和打开所需文件的方法之一
  • 安卓13_ROM修改定制化-----实现默认开启“usb安全设置”(免SIM卡验证)
  • 【Mermaid.js】从入门到精通:完美处理节点中的空格、括号和特殊字符
  • MySQL 如何查看事务隔离级别?
  • 嵌入式硬件工程师的每日提问
  • HTML--最简的二级菜单页面
  • 【ARDUINO】ESP8266断电有效的指令断电后无效的指令
  • 亚马逊云代理商:AWS亚马逊云的独特优势与实用价值
  • [deepseek] C语言头文件与汇编实现讨论
  • 20250911-01: 概念:基础认知--消息
  • leetcode26(字母异位词分组)
  • 超球损失函数
  • 26. AI-Agent-Dify
  • OpenCV 发票识别全流程:透视变换与轮廓检测详解
  • Wappalyzer-网站技术栈识别