Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

“设置标准库调用系统 API 所用的编码,用于 fopen,ifstream 等函数 ”。具体是通过什么字段来影响? #14

Open
bxhuanxue opened this issue Jul 31, 2024 · 5 comments

Comments

@bxhuanxue
Copy link

小彭老师好😋
我有个问题想请教一下

setlocale(LC_ALL, ".utf-8"); // 设置标准库调用系统 API 所用的编码,用于 fopen,ifstream 等函数

根据我的理解,fopen 函数主要创建一个 FILE 结构体,和用户缓冲区,其中包含了管理文件操作的多个字段。然而,在查看 struct _IO_FILE 时,我注意到并没有明确setlocale相关字段。以下是该结构体:

struct _IO_FILE
{
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */

/* The following pointers correspond to the C++ streambuf protocol. */
char _IO_read_ptr; / Current read pointer */
char _IO_read_end; / End of get area. */
char _IO_read_base; / Start of putback+get area. */
char _IO_write_base; / Start of put area. */
char _IO_write_ptr; / Current put pointer. */
char _IO_write_end; / End of put area. */
char _IO_buf_base; / Start of reserve area. */
char _IO_buf_end; / End of reserve area. */

/* The following fields are used to support backing up and undo. */
char _IO_save_base; / Pointer to start of non-current get area. */
char _IO_backup_base; / Pointer to first valid character of backup area */
char _IO_save_end; / Pointer to end of non-current get area. */

struct _IO_marker *_markers;

struct _IO_FILE *_chain;

int _fileno;
int _flags2;
__off_t _old_offset; /* This used to be _offset but it's too small. */

/* 1+column number of pbase(); 0 is unknown. */
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];

_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
我想了解“设置标准库调用系统 API 所用的编码,用于 fopen,ifstream 等函数 ”。具体是通过什么字段来影响呢💕

@archibate
Copy link
Contributor

locale在c语言中是一个全局变量,当_IO_FILE需要了解当前编码时,只需要读取那个全局变量即可,不用占用_IO_FILE空间。所有的ctype.h函数也都是读取全局locale的。

@archibate
Copy link
Contributor

https://github.com/icidicf/library/blob/267ca3c87b44ccbf4eaa6b8e7416f3e38b269332/microsoft/CRT/SRC/SETLOCAL.C#L37
你可以清楚的看到__lc_category是一个全局变量。
而这里的所有__init_xxx则是初始化每个方面(facet)locale的“构造函数”,以LC_TIME方面的__init_time为例:
https://github.com/icidicf/library/blob/267ca3c87b44ccbf4eaa6b8e7416f3e38b269332/microsoft/CRT/SRC/INITTIME.C#L75
又是一个全局变量__lc_time_curr,里面存储着当前locale的时间表示格式信息。他们兜兜转转最后调用了__crtGetLocaleInfoA,其调用Windows API获取当前locale数据:
https://github.com/icidicf/library/blob/267ca3c87b44ccbf4eaa6b8e7416f3e38b269332/microsoft/CRT/SRC/A_LOC.C#L49
然后,就相当于一次性调用完Windows API获取当前locale数据存到了一系列__lc_xxx全局变量,就是这样。

@bxhuanxue
Copy link
Author

讲得很清楚,谢谢小彭老师啦❤️

@frederick-vs-ja
Copy link
Contributor

这条注释好像是错的……

  1. fopen 只负责打开文件,而且 C locale 不影响打开setlocalefopen 可以并发而不产生数据竞争。或许我们应该提及 scanf/printf
  2. ifstream 不是函数。或许我们可以说“iostream 默认使用的 locale”(但好像不适合在这个注释里)。这里的 locale 是在构造 ios_base 的时候从当时的 C locale 复制过去的。

或许可以说:

用于 scanf、printf 等函数以及此后构造的 ifstream 等 C++ 标准流类对象

@archibate
Copy link
Contributor

archibate commented Aug 21, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants