前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >C语言C99标准、C11标准新增加的特性

C语言C99标准、C11标准新增加的特性

原创
作者头像
DS小龙哥
修改2025-01-16 09:41:25
修改2025-01-16 09:41:25
7600
代码可运行
举报
文章被收录于专栏:嵌入式项目开发
运行总次数:0
代码可运行

C语言标准

C语言从其诞生至今,经历了多个标准的更新,主要标准包括:

  1. C89/C90 (ANSI C / ISO/IEC 9899:1990):这是C语言的第一个官方标准,由ANSI于1989年发布,后被ISO采纳为国际标准,发布于1990年。它为C语言的语法、库函数等方面设定了基础规范,广泛被采用并成为后续标准的基础。
  2. C99 (ISO/IEC 9899:1999):发布于1999年,C99标准在C89的基础上进行了大量扩展,引入了如可变长度数组(VLAs)、限制指针(restrict)、内联函数、复数类型、新的整数类型(如_Bool)、改进的预处理功能等特性。
  3. C11 (ISO/IEC 9899:2011):发布于2011年,C11标准在C99基础上进一步完善,加入了对多线程编程的支持(通过<threads.h>库)、增强了Unicode支持(通过<uchar.h>)、引入了原子操作和线程内存模型、静态断言、匿名结构和联合、宏默认参数等新特性,并提高了语言的安全性。
  4. C18 (ISO/IEC 9899:2018):发布于2018年,这个版本主要是对C11标准的小幅修订和澄清,没有引入重大的新特性,主要目的是解决C11标准中发现的问题和歧义,提高标准的清晰度和一致性。C18有时也被视为C11的一个修正版。

目前,最新的官方标准是C18,但需要注意的是,并非所有的编译器都已经完全实现了最新标准的所有特性,开发者在编写代码时应考虑目标编译器的实际支持情况。

C89标准(也称为C90标准)

C89是C语言的第一个官方国际标准,正式名称为ISO/IEC 9899:1990。它是在1989年由美国国家标准协会(ANSI)制定并发布的,故得名C89,随后在1990年被国际标准化组织(ISO)采纳,成为国际标准。C89标准定义了C语言的基础语法、关键字、数据类型,并引入了标准库函数,比如stdio.hstdlib.h等,确立了C语言的基本形态。它的特点是简洁、可移植性强且易于理解,成为了后续C语言教材和实现的基础。

C99标准(ISO/IEC 9899:1999)

C99是C语言的一个重要更新,发布于1999年。它是C89标准的后续版本,引入了许多新特性和改进,旨在适应不断发展的编程需求和技术环境。C99标准增加了诸如限制指针(restrict)、内联函数、可变长度数组(VLAs)、复数类型(_Complex)、新的整型常量(如_Bool)、改进的浮点数处理以及对编译器限制的放宽等特性。此外,C99还引入了//风格的单行注释,使代码更加易读。尽管C99引入了许多现代化的特性,但直到今天,并非所有编译器和开发环境都完全支持C99的所有特性。

下面是一些C99标准新增特性及其示例代码:

1. restrict指针

代码语言:c
代码运行次数:0
复制
void copy_memory(void *restrict dest, const void *restrict src, size_t n) {
    for(size_t i = 0; i < n; ++i) {
        ((char*)dest)[i] = ((const char*)src)[i];
    }
}

在这个例子中,restrict关键字告诉编译器,destsrc指向的内存区域不会重叠,这使得编译器可以进行更多的优化。

2. 内联函数

代码语言:c
代码运行次数:0
复制
inline int add(int a, int b) {
    return a + b;
}

使用inline关键字建议编译器直接将函数体插入每次调用处,以减少函数调用的开销。

3. 可变长度数组(VLAs)

代码语言:c
代码运行次数:0
复制
#include <stdio.h>

int main() {
    int n = 5;
    int arr[n]; // 数组大小在运行时决定
    for(int i = 0; i < n; ++i) {
        arr[i] = i;
    }
    for(int i = 0; i < n; ++i) {
        printf("%d ", arr[i]);
    }
    return 0;
}

这里,数组arr的大小是在运行时根据变量n的值确定的。

4. 复数类型

代码语言:c
代码运行次数:0
复制
#include <complex.h>
#include <stdio.h>

int main() {
    double complex z = 3.0 + 4.0*I;
    printf("The complex number is: %f + %fi\n", creal(z), cimag(z));
    return 0;
}

使用_Complex关键字定义复数类型,并通过crealcimag函数获取实部和虚部。

5. 指定成员初始化器

代码语言:c
代码运行次数:0
复制
struct Person {
    char name[20];
    int age;
};

int main() {
    struct Person p = {.name = "Alice", .age = 30};
    printf("Name: %s, Age: %d\n", p.name, p.age);
    return 0;
}

在结构体初始化时,可以直接指定成员的名字进行初始化,提高了代码的清晰度。

6. 对齐处理

代码语言:c
代码运行次数:0
复制
#include <stdalign.h>

alignas(16) char buffer[100]; // 确保buffer对齐在16字节边界上

int main() {
    // ... 使用对齐后的buffer
    return 0;
}

使用_Alignas关键字可以指定变量或类型的对齐要求。

C11 (ISO/IEC 9899:2011)

C11标准引入了若干新特性,以下是一些主要特性的示例代码:

1. 多线程支持

代码语言:c
代码运行次数:0
复制
#include <threads.h>
#include <stdio.h>

void thread_function(void* arg) {
    printf("Hello, World! from thread\n");
}

int main() {
    thrd_t t;
    if(thrd_create(&t, thread_function, NULL) == thrd_success) {
        thrd_join(t, NULL); // 等待线程结束
    }
    printf("Hello, World! from main thread\n");
    return 0;
}

这段代码展示了如何使用C11中的<threads.h>库创建和等待一个线程完成。

2. Unicode支持

代码语言:c
代码运行次数:0
复制
#include <stdio.h>
#include <uchar.h>

int main() {
    char32_t unicode_char = U'ação'; // 使用UTF-32编码存储Unicode字符
    printf("Unicode character: %C\n", unicode_char);
    return 0;
}

通过<uchar.h>头文件,可以使用Unicode字符,并利用宽字符输出函数打印。

3. 静态断言

代码语言:c
代码运行次数:0
复制
#include <assert.h>

#define MAX_SIZE 100

void func(int size) {
    _Static_assert(size <= MAX_SIZE, "size exceeds maximum allowed");
    // ... 函数逻辑
}

int main() {
    func(99); // 正常执行
    // func(101); // 如果取消注释,编译时会报错
    return 0;
}

_Static_assert允许在编译时验证条件,如果条件不满足,则编译失败。

4. 匿名结构与联合

代码语言:c
代码运行次数:0
复制
#include <stdio.h>

struct Info {
    int id;
    union {
        char name[20];
        // 可以有其他成员
    };
};

int main() {
    struct Info info = {1, "Alice"};
    printf("ID: %d, Name: %s\n", info.id, info.name);
    return 0;
}

C11允许在结构体内部直接定义匿名的联合,简化了结构体的设计。

5. 原子类型和操作

代码语言:c
代码运行次数:0
复制
#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>

atomic_int counter = ATOMIC_VAR_INIT(0);

void increment(void* arg) {
    for(int i = 0; i < 100000; ++i) {
        atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);
    }
}

int main() {
    thrd_t threads[10];
    for(int i = 0; i < 10; ++i) {
        thrd_create(&threads[i], increment, NULL);
    }
    for(int i = 0; i < 10; ++i) {
        thrd_join(threads[i], NULL);
    }
    printf("Counter: %d\n", atomic_load_explicit(&counter, memory_order_relaxed));
    return 0;
}

通过<stdatomic.h>头文件,可以使用原子类型和操作进行线程安全的计数,这里展示了如何在多线程环境下安全地增加一个计数器的值。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C语言标准
  • C89标准(也称为C90标准)
  • C99标准(ISO/IEC 9899:1999)
    • 1. restrict指针
    • 2. 内联函数
    • 3. 可变长度数组(VLAs)
    • 4. 复数类型
    • 5. 指定成员初始化器
    • 6. 对齐处理
  • C11 (ISO/IEC 9899:2011)
    • 1. 多线程支持
    • 2. Unicode支持
    • 3. 静态断言
    • 4. 匿名结构与联合
    • 5. 原子类型和操作
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档