Xiao's Blog

Sep 19, 2025

C11 新特性和示例代码

参考文档,还可进一步了解c23(但是测试了安装的gcc和clang (2025.9.19) 编译器没有支持)

对齐处理(Alignment)的标准化

_Alignas 标识符

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdalign.h>

struct S {
char c;
_Alignas(16) int i;
};

int main() {
printf("Alignment of struct S: %zu\n", alignof(struct S));
return 0;
}

alignof 运算符

1
2
3
4
5
6
7
#include <stdio.h>
#include <stdalign.h>

int main() {
printf("Alignment of double: %zu\n", alignof(double));
return 0;
}

aligned_alloc 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdlib.h>
#include <stdio.h>

int main() {
size_t alignment = 32;
size_t size = 128;
void* ptr = aligned_alloc(alignment, size);
if (ptr) {
printf("Aligned allocation succeeded.\n");
free(ptr);
}
return 0;
}

<stdalign.h> 头文件

1
2
#include <stdalign.h>
alignas(16) int x;

_Noreturn 函数标记

_Noreturn 函数标记,类似于 gcc 的 __attribute__((noreturn))

1
2
3
4
5
6
7
#include <stdio.h>
#include <stdlib.h>

_Noreturn void fatal(const char* msg) {
fprintf(stderr, "Fatal error: %s\n", msg);
exit(1);
}

_Generic 泛型宏关键字

字符串例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

// 如:若x为int类型,则替换 type_name(x) 为 int 类型后面的值,即 "int" 这个字符串
#define type_name(x) _Generic((x), \
int: "int", \
float: "float", \
double: "double", \
default: "other")

int main() {
printf("%s\n", type_name(3.14)); // 输出 double
printf("%s\n", type_name(42)); // 输出 int
return 0;
}

“函数重载”例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

void foo_int(int x){
printf("I am int type !!~\n");
}

void foo_double(double x){
printf("I am double type !!~\n");
}

#define foo(x) _Generic(x, int : foo_int, \
double : foo_double)(x)

int main(){
foo(123); // foo_int(123) // I am int type !!~
foo(1.23); // foo_double(1.23) // I am double type !!~
return 0;
}

多线程(Multithreading)支持

注意:无法在 Darwin clang 环境下使用

_Thread_local 存储类型标识符 和 <threads.h> 头文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>
#include <threads.h>

#define NUM_THREADS 4
#define MAX_ITER 10000

_Thread_local int counter = 0;

void *incrementCounter(void *thr_id) {
int tid = (int)thr_id;
printf("thread %d started incrementing ID - %lu\n", tid, thrd_current());

for (int i = 0; i < MAX_ITER; ++i)
counter += 1;

return (void *)counter;
}

int main(int argc, char const *argv[]) {
thrd_t threads[NUM_THREADS];
int rc, sum = 0;

for (int i = 0; i < NUM_THREADS; ++i) {
rc = thrd_create(&threads[i], (thrd_start_t)incrementCounter, (void *)i);
if (rc == thrd_error) {
printf("ERORR; thrd_create() call failed\n");
exit(EXIT_FAILURE);
}
}

int retval;
for (int i = 0; i < NUM_THREADS; ++i) {
thrd_join(threads[i], &retval);
sum += retval;
}
printf("count = %d\n", sum);

thrd_exit(EXIT_SUCCESS);
}

输出:

1
2
3
4
5
thread 0 started incrementing ID - 281473108406528
thread 3 started incrementing ID - 281472963440896
thread 1 started incrementing ID - 281473099952384
thread 2 started incrementing ID - 281473091498240
count = 40000

不加的输出(各个线程在竞争数据):

1
2
3
4
5
thread 0 started incrementing ID - 281473865281824
thread 2 started incrementing ID - 281473848373536
thread 1 started incrementing ID - 281473856827680
thread 3 started incrementing ID - 281473768747296
count = 55938

_Atomic 类型修饰符和 <stdatomic.h> 头文件

1
2
3
4
5
6
7
#include <stdatomic.h>

_Atomic int count = 0;

void foo() {
atomic_fetch_add(&count, 1); // 原子量加一
}

增强的 Unicode 支持

char16_tchar32_t

1
2
char16_t utf16_str[] = u"你好";
char32_t utf32_str[] = U"世界";

<uchar.h> 头文件

1
2
3
4
5
6
7
8
#include <uchar.h>
#include <stdio.h>

int main() {
char16_t str[] = u"hello";
printf("%zu\n", sizeof(str));
return 0;
}

删除 gets(),新增 gets_s()

  • gets() 已被删除,不再安全。
  • gets_s() 是 C11 增加的安全替代:
1
2
3
// gets_s 在部分实现中可用
char buf[100];
gets_s(buf, 100);

边界检查函数接口(如 fopen_sstrcat_s 等)

增加了边界检查函数接口,定义了新的安全的函数

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

int main() {
FILE* fp;
if (fopen_s(&fp, "file.txt", "r") == 0) {
// 成功打开
fclose(fp);
}
return 0;
}

浮点处理宏的增强

1
2
#include <float.h>
printf("Decimal digits of precision: %d\n", DECIMAL_DIG);

输出:Decimal digits of precision: 36


匿名结构体/联合体支持

1
2
3
4
5
6
7
struct {
union {
int i;
float f;
};
} var;
var.i = 5;

静态断言(Static Assertion)_Static_assert

1
_Static_assert(sizeof(int) == 4, "int must be 4 bytes");

新的 fopen 模式(“…x”)

1
FILE* fp = fopen("test.txt", "wx"); // 仅当文件不存在才创建并写入

新增 quick_exit() 函数

1
2
3
4
5
6
7
8
9
10
#include <stdlib.h>

void cleanup(void) {
// 仅被 quick_exit 调用
}

int main() {
at_quick_exit(cleanup);
quick_exit(0); // 快速退出,不执行普通 atexit 注册的清理
}
OLDER > < NEWER