在 C 中确定字符串是否有效 wchar_t*

Determine if a string is a valid wchar_t* in C

我正在尝试重新编码 printf 的一部分。

setlocale(LC_ALL, "en_US.UTF-8");
int ret = printf("%S\n", "我是一只猫。");
printf("Printf returned %d\n", ret);

如果格式是%s,printf 写入宽字符和returns 19.

如果格式是%S, printf returns -1 因为参数不是宽字符串(没有L""").

之前

在我自己的 printf 实现中,如何确定传入参数的字符串是否很宽,如果不是,我可以 return -1?

编辑

In my own implementation of printf, how can I determine if the string passed in parameter is wide, so I can return -1 if it isn't ?

你不能。 %S 格式说明符在 printf(3) 中记录为

(Not in C99 or C11, but in SUSv2, SUSv3, and SUSv4.) Synonym for %ls. Don't use.

所以你可能不应该使用它(因为它在 C11 标准中是而不是,但在 SUSv4 中)。如果您确实将它用于您自己的 printf,那将是一个 承诺 相应的实际参数 一个宽字符串。

但是,如果您的 C 编译器是最新的 GCC, use an appropriate format function attribute (it is a GCC extension) in your declaration of your printf (or likewise) function. This would give warnings to the users of ill-typed arguments to your function. And you could even customize GCC (e.g. using MELT),您可能会定义自己的函数属性,这将在编译时启用额外的类型检查,因此没有可移植的方式,给定指向某物,在运行时检查它是否是指向字符串或其他东西(如整数数组)的指针。

在运行时,您的 printf 将使用 stdarg(3) facilities so would have to "interpret" the format string to handle appropriately the various format specifiers. Without compiler support (à la __attribute__((format(printf,1,2))) in GCC (also supported by Clang),或使用您自己的函数属性)您无法获得任何 编译时 类型检查可变函数。并且类型信息在运行时在 C 中被删除。

另请参阅 现有 printf 的实现,例如 free software implementations of the C standard library. The stdio/vfprintf.c file of MUSL libc 中的函数非常可读。

此外,GNU libunistring has some elementary string checks functions like e.g. u16_check which checks if an array (whose size is given) of 16 bits integers is a valid UTF16 string. Notice that "我是一只猫。" in UTF8 is not a zero-doublebyte or zero-widechar terminated UTF16 string (so simply computing its length as wchar_t* wide string is undefined behavior, because of buffer overflow!),甚至可能没有宽字符串所需的对齐方式。

基本上,你不能。为 %S 传递不是宽字符串的内容是 未定义的行为, 任何事情都可能发生,包括从你的鼻子飞出的精灵。您很幸运 printf 捕捉到这一点,它可能检测到 "我是一只猫。" 的内容在被解释为 wchar_t 的数组时并非都是有效的代码点(如果发生这种情况,errnoprintf) 设置为 EILSEQ