【发布时间】:2022-01-28 04:25:03
【问题描述】:
通过阅读 MSDN 或 n1256 委员会草案中的文档,我的印象是,char 始终与 <limits.h> 中定义的 CHAR_BIT 位完全相同。
如果 CHAR_BIT 设置为 8,则一个字节为 8 位长,char 也是如此。
测试代码
给定以下 C 代码:
int main(int argc, char **argv) {
int length = 0;
while (argv[1][length] != '\0') {
// print the character, its hexa value, and its size
printf("char %u: %c\tvalue: 0x%X\t sizeof char: %u\n",
length,
argv[1][length],
argv[1][length],
sizeof argv[1][length]);
length++;
}
printf("\nTotal length: %u\n", length);
printf("Actual char size: %u\n", CHAR_BIT);
return 0;
}
对于包含非 ASCII 字符的参数(例如 ç 和 à),我不确定会发生什么行为。
这些字符应该是 UTF-8,所以每个都写成多个字节。我希望它们被作为单个字节处理,这意味着 ça 的长度为 3(例如,如果计算 \0,则为 4),并且在打印时,我会得到每个字节一行,所以 3 行而不是2(这将是实际的拉丁字符数)。
输出
$ gcc --std=c99 -o program.exe win32.c
$ program.exe test_çà
char 0: t value: 0x74 sizeof char: 1
char 1: e value: 0x65 sizeof char: 1
char 2: s value: 0x73 sizeof char: 1
char 3: t value: 0x74 sizeof char: 1
char 4: _ value: 0x5F sizeof char: 1
char 5: τ value: 0xFFFFFFE7 sizeof char: 1
char 6: α value: 0xFFFFFFE0 sizeof char: 1
Total length: 7
Actual char size: 8
问题
幕后可能发生的事情是char **argv 变成了int **argv。这可以解释为什么第 5 行和第 6 行有一个写在 4 个字节上的十六进制值。
- 实际情况是这样吗?
- 这是标准行为吗?
- 为什么字符 5 和 6 不是作为输入给出的?
-
CHAR_BIT == 8和sizeof(achar) == 1和somechar = 0xFFFFFFE7。这似乎违反直觉。发生了什么事?
环境
- Windows 10
- 终端:Alacritty 和 Windows 默认 cmd(均已尝试以防万一)
- Mingw-w64 下的 GCC
【问题讨论】:
-
您误解了您的程序正在做什么和结果。
printf正在打印提升为int的char。您的字符在127ASCII 以上,因此被解释为负数,然后符号扩展为负数ints。然后您使用%x打印它们,并获得这些的十六进制 2 的补码表示。与其他无关 -
所以你是对的,
char在某些时候会变成int。但这一点在printf调用中。由于它是一个可变参数函数,它的参数正在进行默认提升(对于char,它将是int)。 -
代码中也有一些bug。 (1)
0x%X应该是0x%zX,因为对应的参数的类型是size_t。 (2)printf("\nTotal length: %u\n", argv[1][length], length);参数过多。 -
@ValentinO。你可能想看看stackoverflow.com/questions/4101864/…
-
@ValentinO。其实,我错了。
0x%X可以,但sizeof char: %u应该是sizeof char: %zu。这假设您使用的是 MingW 的替换格式标准 I/O 例程,而不是来自 msvcrt.dll 的例程。
标签: c windows gcc unicode argv