在 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?
编辑
- 我正在 OS X El Capitan 上编程(但如果可能的话,我想要一个便携式解决方案)
- 在我的编程环境中,%S 和 %ls 是相同的 - 这对我这里的问题来说并不重要
- Printf 也 returns -1 当我没有为格式为 %s 的示例设置语言环境时。这是我设置语言环境的唯一原因。
- 我正在使用 clang 进行编译(Apple LLVM 版本 7.0.0 (clang-700.1.76))
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
的数组时并非都是有效的代码点(如果发生这种情况,errno
被 printf
) 设置为 EILSEQ
。
我正在尝试重新编码 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?
编辑
- 我正在 OS X El Capitan 上编程(但如果可能的话,我想要一个便携式解决方案)
- 在我的编程环境中,%S 和 %ls 是相同的 - 这对我这里的问题来说并不重要
- Printf 也 returns -1 当我没有为格式为 %s 的示例设置语言环境时。这是我设置语言环境的唯一原因。
- 我正在使用 clang 进行编译(Apple LLVM 版本 7.0.0 (clang-700.1.76))
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
的数组时并非都是有效的代码点(如果发生这种情况,errno
被 printf
) 设置为 EILSEQ
。