%c 格式化字符串在 shell 和 C 中显示不同的行为

%c 格式化字符串在 shell 和 C 中显示不同的行为

如果我用 C 写一行非常简单的代码:

printf("Ascii char for %d is %c\n",65,65);

它只是打印A,因为 ascii 值 65 对应于字符A。但是如果我在 shell 中使用相同的代码并编写命令

printf "Ascii char for %d is %c\n" 65 65

它显示输出为Ascii char for 65 is 6.我期望得到与 C 语言相同的输出,并且从逻辑上讲它也应该打印与给定 ascii 代码相对应的字符。

为什么它在这些情况下表现出不同的行为?

答案1

接受%c一个字符串并打印该字符串的第一个字符。如果字符串是65,如您的示例所示,那么它将打印6

这是由printf该实用程序的 POSIX 规范:

转换说明符的参数c可以是包含零个或多个字节的字符串。如果它包含一个或多个字节,第一个字节应被写入并且任何附加字节都应被忽略。如果参数是空字符串,则未指定是否不写入任何内容或写入空字节。

参数操作数应被视为字符串如果相应的转换说明符是b, c, 或s[...]

这意味着论证格式的%c解释在 C 中(其中一个小的正整数将被转换为 a char)和在 shell 中(其中相同的整数仍然是包含多个数字字符的字符串)。不过,格式本身也做了同样的事情;它输出一个字节作为一个字符。

然而:

$ printf '%d %b\n' 65 '\0101'
65 A

101 是八进制的 65。%b在 POSIX 中指定为

b应支持附加转换说明符字符 ,如下所示。该参数应被视为可以包含<backslash>转义序列的字符串。 [...]

\0ddd,其中ddd是零、一位、两位或三位八进制数,应转换为具有由八进制数指定的数值的字节。

这是一个额外的转换说明符,因为它在标准 C 中不可用。但是在 shell 中需要它,因为我们没有类型变量(在 POSIX shell 中)。

还:

$ printf '%d %b\n' 65 "$( printf '\\0%o\n' 65 )"
65 A

\0ddd在这里,我们首先使用 格式将 65 转换为八进制数,然后在另一个使用 的%o格式中使用该结果。printf%b

相关内容