使用带字符串的长度子说明符的 printf 行为
Behaviour of printf using length subspecifier with a string
我很好奇 printf 是如何工作的,我尝试了很多技巧,例如:
printf("Test 1: %hs\n", "hi");
printf("Test 2: %hhs\n", "hi");
printf("Test 3: %ls\n", "hi");
printf("Test 4: %lls\n", "hi");
printf("Test 5: %js\n", "hi");
printf("Test 6: %zs\n", "hi");
printf("Test 7: %ts", "hi");
我正在使用带有 s
说明符和所有长度修饰符的 printf(通常与数字说明符一起使用(如 d / i / u / o ...
),我得到了奇怪的输出:
Test 1: hi
Test 2: hi
Test 3: Test 4: Test 5: Test 6: hi
Test 7: hi
似乎是 l / ll / j
长度修饰符导致 printf 错误并停止工作(它不打印 \n
但对于所有其他长度修饰符,它似乎忽略了长度修饰符并工作像正常使用一样)。
为什么会出现这种行为?
答案是undefined behaviour。格式说明符 %s
不支持您用于传递的参数的任何长度修饰符。格式说明符不匹配在 C 中未定义。当我使用 gcc 编译器 (gcc -Wall -Wextra -std=c11 test.c
) 编译您的代码时,它表示:
test.c: In function ‘main’:
test.c:5:19: warning: use of ‘h’ length modifier with ‘s’ type character has either no effect or undefined behavior [-Wformat=]
printf("Test 1: %hs\n", "hi");
^
test.c:6:20: warning: use of ‘hh’ length modifier with ‘s’ type character has either no effect or undefined behavior [-Wformat=]
printf("Test 2: %hhs\n", "hi");
^
test.c:7:19: warning: format ‘%ls’ expects argument of type ‘wchar_t *’, but argument 2 has type ‘char *’ [-Wformat=]
printf("Test 3: %ls\n", "hi");
^
test.c:8:20: warning: use of ‘ll’ length modifier with ‘s’ type character has either no effect or undefined behavior [-Wformat=]
printf("Test 4: %lls\n", "hi");
^
test.c:9:19: warning: use of ‘j’ length modifier with ‘s’ type character has either no effect or undefined behavior [-Wformat=]
printf("Test 5: %js\n", "hi");
^
test.c:10:19: warning: use of ‘z’ length modifier with ‘s’ type character has either no effect or undefined behavior [-Wformat=]
printf("Test 6: %zs\n", "hi");
^
test.c:11:19: warning: use of ‘t’ length modifier with ‘s’ type character has either no effect or undefined behavior [-Wformat=]
printf("Test 7: %ts", "hi");
唯一可以与 %s
一起使用的有效长度修饰符是 l
,它表示参数的类型为 wchar_t
,而不是 char
。
hh
、h
、ll
、j
、z
或 t
中的 None 定义为与 s
一起使用。
请参阅 C 2011 online standard,§7.21.6.1,第 7 段。
我很好奇 printf 是如何工作的,我尝试了很多技巧,例如:
printf("Test 1: %hs\n", "hi");
printf("Test 2: %hhs\n", "hi");
printf("Test 3: %ls\n", "hi");
printf("Test 4: %lls\n", "hi");
printf("Test 5: %js\n", "hi");
printf("Test 6: %zs\n", "hi");
printf("Test 7: %ts", "hi");
我正在使用带有 s
说明符和所有长度修饰符的 printf(通常与数字说明符一起使用(如 d / i / u / o ...
),我得到了奇怪的输出:
Test 1: hi
Test 2: hi
Test 3: Test 4: Test 5: Test 6: hi
Test 7: hi
似乎是 l / ll / j
长度修饰符导致 printf 错误并停止工作(它不打印 \n
但对于所有其他长度修饰符,它似乎忽略了长度修饰符并工作像正常使用一样)。
为什么会出现这种行为?
答案是undefined behaviour。格式说明符 %s
不支持您用于传递的参数的任何长度修饰符。格式说明符不匹配在 C 中未定义。当我使用 gcc 编译器 (gcc -Wall -Wextra -std=c11 test.c
) 编译您的代码时,它表示:
test.c: In function ‘main’:
test.c:5:19: warning: use of ‘h’ length modifier with ‘s’ type character has either no effect or undefined behavior [-Wformat=]
printf("Test 1: %hs\n", "hi");
^
test.c:6:20: warning: use of ‘hh’ length modifier with ‘s’ type character has either no effect or undefined behavior [-Wformat=]
printf("Test 2: %hhs\n", "hi");
^
test.c:7:19: warning: format ‘%ls’ expects argument of type ‘wchar_t *’, but argument 2 has type ‘char *’ [-Wformat=]
printf("Test 3: %ls\n", "hi");
^
test.c:8:20: warning: use of ‘ll’ length modifier with ‘s’ type character has either no effect or undefined behavior [-Wformat=]
printf("Test 4: %lls\n", "hi");
^
test.c:9:19: warning: use of ‘j’ length modifier with ‘s’ type character has either no effect or undefined behavior [-Wformat=]
printf("Test 5: %js\n", "hi");
^
test.c:10:19: warning: use of ‘z’ length modifier with ‘s’ type character has either no effect or undefined behavior [-Wformat=]
printf("Test 6: %zs\n", "hi");
^
test.c:11:19: warning: use of ‘t’ length modifier with ‘s’ type character has either no effect or undefined behavior [-Wformat=]
printf("Test 7: %ts", "hi");
唯一可以与 %s
一起使用的有效长度修饰符是 l
,它表示参数的类型为 wchar_t
,而不是 char
。
hh
、h
、ll
、j
、z
或 t
中的 None 定义为与 s
一起使用。
请参阅 C 2011 online standard,§7.21.6.1,第 7 段。