【问题标题】:What is the purpose of the new C23 #embed directive?新的 C23 #embed 指令的目的是什么?
【发布时间】:2022-11-30 09:01:10
【问题描述】:

即将推出的 C23 标准中提供了一个新的预处理器指令:#embed

这是一个简单的例子:

// Placing a small image resource.

#include <stddef.h>

void show_icon(const unsigned char *, size_t);

int main (int, char*[]) {
    static const unsigned char icon_data[] = {
#embed "black_sheep.ico"
    };
    show_icon(icon_data, sizeof(icon_data));
    return 0;
}

这是一个更详细的从二进制数据初始化非数组(不管是什么意思):

int main() {
    /* Braces may be kept or elided as per normal initialization rules */
    int i = {
#embed "i.dat"
    }; /* i value is [0, 2^(embed element width)) first entry */
    int i2 =
#embed "i.dat"
    ; /* valid if i.dat produces 1 value, i2 value is [0, 2^(embed element width)) */
    struct s {
        double a, b, c;
        struct { double e, f, g; };
        double h, i, j;
    };
    struct s x = {
        /* initializes each element in order according to 
           initialization rules with comma-separated list
           of integer constant expressions inside of braces */
#embed "s.dat"
   };
   return 0;
}

把这个加入到C语言中的目的是什么?

【问题讨论】:

    标签: c language-lawyer c23


    【解决方案1】:

    #embed 允许在程序可执行映像中轻松包含二进制数据,如 unsigned char 或其他类型的数组,而无需从 Makefile 运行外部脚本。大多数编译器在解析此类数组时效率很低,但有一个明显的例外:tcc.

    嵌入二进制甚至文本数据比从文件读取有优势:

    • 可能没有文件系统
    • 文件路径可能不明显
    • 文件可能丢失或无法访问

    将此添加到 C 语言的主要原因似乎是新的冲动,即把所有流行的 C++ 特性都倾倒在 C 上,徒劳地试图将 C 收敛到两种语言的公共子集。 C++ 委员会强烈支持这个扩展,而 C 委员会则不太高兴。

    阅读详情:https://thephd.dev/_vendor/future_cxx/papers/C%20-%20embed.html

    strdup() 进入标准库看起来已经 30 年了,突然间 C23 欣然将语言在各个方向上扩展了 50%,没有任何悔意。

    使它成为预处理器混乱的基本原理是非常值得怀疑的,最后一个原因不言而喻:

    最后,微软有一个 ABI 问题,它的最大字符串文字大小无法使用字符串文字或任何像字符串文字一样处理的东西来解决

    #embed 的规范充满了怪癖和缺点。不愿编写适当的脚本会导致令人厌恶的行为,例如:

    const unsigned char null_terminated_file_data[] = {
        #embed "might_be_empty.txt" 
            prefix(0xEF, 0xBB, 0xBF, ) /* UTF-8 BOM */ 
            suffix(,)
        0 // always null-terminated
    };
    

    或者更糟:

    int main () {
    #define SOME_CONSTANT 0
        return
    #embed </dev/urandom> if_empty(0) limit(SOME_CONSTANT)
        ;
    }
    

    将二进制文件组装成可链接对象和资源的简单数据描述和操作语言的侵入性较小,并且很容易包含在所有语言的现有构建系统中,更重要的是所有现有编译器。

    该论文列举了一些有趣的示例,其中 #embed 可能会派上用场,但似乎可以采用更通用的解决方案。

    【讨论】:

      猜你喜欢
      • 2011-11-12
      • 1970-01-01
      • 2011-02-17
      • 2012-10-05
      • 2020-11-12
      • 2021-08-29
      • 2016-12-23
      相关资源
      最近更新 更多