use*_*329 5 c locale standard-library
是否有计划添加在当前语言环境下不变的 C 标准库字符串处理函数版本?
目前有很多脆弱的解决方法,例如,来自 jansson/strconv.c:
static void to_locale(strbuffer_t *strbuffer)
{
const char *point;
char *pos;
point = localeconv()->decimal_point;
if(*point == '.') {
/* No conversion needed */
return;
}
pos = strchr(strbuffer->value, '.');
if(pos)
*pos = *point;
}
static void from_locale(char *buffer)
{
const char *point;
char *pos;
point = localeconv()->decimal_point;
if(*point == '.') {
/* No conversion needed */
return;
}
pos = strchr(buffer, *point);
if(pos)
*pos = '.';
}
Run Code Online (Sandbox Code Playgroud)
这些函数预处理它的输入,以便它可以独立于当前语言环境使用,在假设下
setlocale在这些修复函数和对任何受影响函数的调用之间没有调用(1) 意味着预处理方法在异国语言环境中中断(参见https://en.wikipedia.org/wiki/Decimal_mark#Hindu.E2.80.93Arabic_numeral_system示例)。(2) 暗示预处理方法在没有锁的情况下不能是线程安全的,并且必须将该锁添加到 C 库中。(3) 只是愚蠢。
如果只能为字符串处理函数的单个调用指定语言环境作为参数,而不影响任何其他线程,则这些限制都不适用。
问题:
更新:
在 Internet 上搜索后,我找到了 *_l 函数,可在 FreeBSD、GNU/Linux 和 MacOSX 上使用。Windows 上也存在类似的功能。这些解决了我的问题,但是这些不在 POSIX 中,POSIX 是 C 的超集(不是真的,POSIX 在指针上放松)。所以问题 1 和 2 仍然悬而未决。
BSD 和 macOS Sierra(以及之前的 Mac OS X)支持_l允许您指定区域设置的功能,而不是依赖于当前区域设置。例如:
\n\n\nRun Code Online (Sandbox Code Playgroud)\nint\nfprintf_l(FILE * restrict stream, locale_t loc, const char * restrict format, ...);\n\nint\nprintf_l(locale_t loc, const char * restrict format, ...);\n\nint\nsnprintf_l(char * restrict str, size_t size, locale_t loc, const char * restrict format, ...);\n\nint\nsprintf_l(char * restrict str, locale_t loc, const char * restrict format, ...);\n
和:
\n\n\n\n\nRun Code Online (Sandbox Code Playgroud)\nint\nfscanf_l(FILE * restrict stream, locale_t loc, const char * restrict format, ...);\n\nint\nscanf_l(locale_t loc, const char * restrict format, ...);\n\nint\nsscanf_l(const char * restrict str, locale_t loc, const char * restrict format, ...);\n
作为一般设计,这似乎是明智的。该类型locale_t不是标准 C 的一部分,而是 POSIX 的一部分(并在<locale.h>那里定义),并在<ctype.h>其他地方使用。BSD 手册页说要使用的标头是<xlocale.h>而不是<locale.h>; 这也许可以通过标准来解决。除非 BSD 函数的设计存在重大缺陷,否则这些应该是任何标准化工作的良好基础,无论是在 POSIX 还是标准 C 下。
BSD 设计的一个问题可能是locale_t结构是按值传递的,而不是按(常量受限的)指针传递的,这有点令人惊讶。然而,它与 POSIX 函数一致,例如:
\n\n\nRun Code Online (Sandbox Code Playgroud)\nint isalpha_l(int, locale_t);\n
也可以设计类似的方案来处理时区设置。由于还没有时区类型(而locale_tPOSIX 的一部分已经是 \xe2\x80\x94,并且可能可以在不更改为标准 C 的情况下采用),因此需要进行更多的设置工作。但是,与区域设置相结合,它可以使时间例程更容易通过单个可执行文件在不同的环境中使用。