为何使用printf的%c格式符时,编译器仍会将char转换为int?
问题:明明在printf中使用了%c格式符,为何编译器生成的代码中仍会对char类型变量执行static_cast转换?
先看一下原代码和C++ Insights生成的编译器实际处理代码:
原代码
#include <cstdio> int main() { const char arr[10]{2,4,6,8}; for(const char& c : arr) { printf("c=%c\n", c); } }
编译器处理后的代码(来自C++ Insights)
#include <cstdio> int main() { const char arr[10] = {2, 4, 6, 8, '\0', '\0', '\0', '\0', '\0', '\0'}; { char const (&__range1)[10] = arr; const char * __begin1 = __range1; const char * __end1 = __range1 + 10L; for(; __begin1 != __end1; ++__begin1) { const char & c = *__begin1; printf("c=%c\n", static_cast<int>(c)); } } }
核心原因:可变参数函数的默认类型提升规则
这里的关键在于printf是一个可变参数函数,而C++(以及C)对于可变参数的参数传递有明确的默认类型提升规则:
- 所有
char、signed char、unsigned char类型的参数都会被提升为int(如果int能容纳原类型的所有值,这在几乎所有现代平台上都是成立的); short和unsigned short会被提升为int;float会被提升为double。
而printf的%c格式符,实际上要求的是一个int类型的参数——它会先把这个int值转换为unsigned char,然后输出对应的字符。
你写的代码里,c是const char&类型,在传递给printf时本来会隐式发生类型提升,变成int。C++ Insights把这个隐式的提升操作显式地写成了static_cast<int>(c),目的就是让你看到编译器在幕后做的这个“小动作”——这正是它的核心价值:把那些隐式的、容易被忽略的编译器操作暴露出来。
换句话说,即使你没写这个转换,编译器也会悄悄帮你做;Insights只是把这个过程摆到台面上,让你明白实际传递给printf的不是char,而是提升后的int。
内容的提问来源于stack exchange,提问作者Jolly Roger
相关产品推荐
相关产品推荐

