chq*_*lie 10 c language-lawyer c23
即将推出的 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;
}
Run Code Online (Sandbox Code Playgroud)
这是一个更详细的方法,从二进制数据初始化非数组(无论这意味着什么):
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;
}
Run Code Online (Sandbox Code Playgroud)
C语言中加入这个的目的是什么?
#embed
允许轻松地将二进制数据作为数组unsigned char
或其他类型包含在程序可执行映像中,而不需要从 Makefile 运行外部脚本。大多数编译器在解析此类数组时效率非常低,但有一个明显的例外:tcc。
嵌入二进制甚至文本数据比从文件中读取数据有好处:
将其添加到 C 语言的主要原因似乎是一种新的冲动,即要将所有流行的 C++ 功能都转储到 C 上,徒劳地试图将 C 融合到两种语言的公共子集。C++ 委员会强烈支持这一扩展,而 C 委员会则不那么兴奋。
阅读详细信息: https://thephd.dev/_vendor/future_cxx/papers/C%20-%20embed.html
花了 30 年时间才strdup()
将其纳入标准库,突然之间,C23 很高兴地将语言在各个方向上扩展了 50%,没有任何悔恨。
将其作为预处理器拼凑的理由非常值得怀疑,最后一个原因不言自明:
最后,Microsoft 存在一个 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
};
Run Code Online (Sandbox Code Playgroud)
或者更糟:
int main () {
#define SOME_CONSTANT 0
return
#embed </dev/urandom> if_empty(0) limit(SOME_CONSTANT)
;
}
Run Code Online (Sandbox Code Playgroud)
将二进制文件组装成可链接对象和资源的简单数据描述和操作语言的侵入性较小,并且易于包含在所有语言(更重要的是所有现有编译器)的现有构建系统中。
本文列举了一些有趣的例子,这些例子#embed
可能会派上用场,但更通用的解决方案似乎是可能的。