11
0
0

C语言

2026-08-25
2026-09-14
文章摘要
|

一、GCC扩展语法

1.语句表达式

#include<stdio.h>

void main(void)
{
    int a=({1;2;4;})+10;
    printf("%d\n",a);//a=14
}

这段代码中的 {1;2;4;} 是 GCC 编译器提供的一个特殊扩展语法,叫做 语句表达式(Statement Expression)。

  • 里面可以写多条正常的 C 语言语句。

  • 最关键的一点:整个语句表达式的值,等于最后一条表达式语句的值。

它最大的作用是把复杂的逻辑封装成一个表达式,常用于宏定义(Macro)中,避免宏参数被多次求值的问题。

例如下面的示例:

// 普通宏:如果传入 func(),func 会被执行两次!
#define MAX(a,b) ((a)>(b)?(a):(b)) 

// 使用语句表达式的宏:安全且能包含局部变量
#define MAX(a,b) \
    ({ \
        typeof(a) _a = (a); \
        typeof(b) _b = (b); \
        _a > _b ? _a : _b; \
    })

2.扩展关键字 typeof(a)

这个关键字是C 语言里的“类型推导器”:

typeof(x) y = 20; // 编译器看到后,等同于:int y = 20;

因此

typeof(a) _a = (a); //它的作用就是创造一个和A一样类型的变量

3.局部标签(Local Labels)

这个功能是 GCC (GNU Compiler Collection) 对 C 语言家族 (主要是 C 和 C++) 进行的非标准扩展,允许您在函数内部的 局部作用域 中声明一个标签,然后使用 goto 语句跳转到这个标签。

GCC 的 局部声明标签 功能通过使用 label 关键字,将标签的声明限制在一个更小的 局部作用域 (例如一个复合语句或代码块) 内,从而避免了标签名称与函数内其他地方的标签或变量名冲突。

void func(int condition) {
    // 使用 __label__ 关键字声明局部标签
    __label__ local_target;

    if (condition > 0) {
        goto local_target; // 可以跳转到局部标签
    }

    // ... 其他代码 ...

    // 局部标签的定义
    local_target:
        printf("Jumped to local target.\n");

    // 注意:如果在另一个块内声明了同名的局部标签,
    // 它们将是不同的实体。
}

二、C语言中应该注意的地方

三、一些思路或方法、杂项

1.空指针偏移量计算

在 C 语言里,内存地址 0 是个很危险的地方。我们不是真的要去“碰”它,我们只是拿它当个“假想的起点”。所以 (struct st*)0 的意思就是:“假装地址 0 的位置,放了一个 struct st 结构体。

现在我想要测量这个结构体的b元素的位置,&((struct st*)0)->b,既然起点是 0,那你顺着往下找,找到 b 的位置,告诉我它距离起点 0 有多远(偏移量是多少)

看完上面的解释,应该知道下面这两个代码的功能是一样的。

typeof ((struct st*)0)->b) c; // 取b的类型来声明c
int c;

既然你能把结构体强转成 0 刻度(也就是 (struct st*)0),那如果现在要量的是个数组(比如 int 数组),你是不是也能用同样的方法,把数组强转成 0 刻度呢?

答:假设你有一个整型数组 int arr[10];,你想把它的首地址当成 0 刻度,你可以这样写:(int*)0

如果你想获取数组中第 3 个元素(即 arr[2])相对于 0 刻度的偏移量,你可以这样写:&(((int*)0)[2])

实际上上述操作就是Linux内核源码中的offsetof宏函数:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

2.volatile 修饰函数的历史用法与 noreturn 的演进

  • Linux源码现象:在早期 Linux 源码(如 volatile void do_exit(long code);)中出现的用法,是早期 GCC(2.5版本前)的非标准扩展。

实际上:与“防止内存优化”无关,而是告诉编译器该函数永远不会返回(No Return)。编译器知道函数不返回,从而省略在堆栈上保存调用者返回地址的操作,节省空间并提升性能。

  • 在现代C语言中,

    • GCC 扩展:void func() __attribute__((noreturn));

    • C11 标准:_Noreturn void func();

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给予支持!

C语言
/archives/cyu-yan
作者
Sharkey
发布于
2026-08-25
许可协议
CC BY-NC-SA 4.0

评论