为什么字符类型可以在%d格式说明符中进行转换?

huangapple go评论74阅读模式
英文:

the reason why type char can be converted in specifier %d?

问题

我突然注意到,尽管%d只接受int类型,但我在char类型上使用了转换说明符%d。

这怎么可能?

根据C标准,转换说明符%d对应于int类型的参数。而且,如果任何参数不是相应转换规范的正确类型,行为是未定义的。

但是,无论我如何编译上述代码,我总是得到预期的输出。

我不应该总是期望这个输出吗?

或者,当传递给函数的参数时,char类型会扩展为int类型吗?所以它可以是65,我可以使用类型char的转换说明符%d吗?

英文:

I suddenly noticed that i've used conversion specifier %d with type char although %d takes only type int.

How is it possible?

According to c standard, conversion specifier %d is corresponding to type int argument.
And if any argument is not the correct type for the corresponding conversion specification,
the behavior is undefined.

#include <stdio.h>
int main(void){
    char a= 'A'; // 'A' = 65 in ASCII

    printf("%c\n", a);
    printf("%d\n", a);

    return 0;
}

----- output -----
A
65

But whenever i compile the code like above , i always get output as intended.

Shouldn't i expect this output always?

Or, IS type char expanded to type int when passed to function's argument? So it can be 65 and i can use specifier %d with type char?

答案1

得分: 1

C 2018 6.5.2.2 7说:

如果表示被调用函数的表达式(printf就是这个表达式)具有包含原型的类型(它有),则参数会被隐式转换,就像通过赋值一样,转换为相应参数的类型,将每个参数的类型视为其声明类型的未限定版本。函数原型声明符中的省略号表示在最后一个声明的参数之后停止参数类型转换。默认参数提升会对尾部参数执行。

printf被声明为int printf(const char * restrict format, ...);,所以在printf("%d\n", a);中,"%d"参数对应于format参数,而a对应于...,使其成为尾部参数的一部分。因此,对其执行默认参数提升。这些在6.5.2.2 6中指定:

整数提升在6.3.1.1 2中指定:

如果int可以表示原始类型的所有值(对于位字段受限制的宽度),则将值转换为int;否则,将其转换为unsigned int。这些被称为整数提升...

因此,您的char参数a会自动转换为int,因此它是%d的正确类型。

英文:

C 2018 6.5.2.2 7 says:

> … If the expression that denotes the called function [printf is that expression] has a type that does include a prototype [it does], the arguments are implicitly converted, as if by assignment, to the types of the corresponding parameters, taking the type of each parameter to be the unqualified version of its declared type. The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments.

printf is declared <code>int printf(const char * restrict <i>format</i>, ...);</code>, so, in printf(&quot;%d\n&quot;, a);, the &quot;%d&quot; argument corresponds to the <code><i>format</i></code> parameter, and the a corresponds to the ..., making it part of the trailing arguments. So the default argument promotions are performed on it. These are specified in 6.5.2.2 6:

> … the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions.

The integer promotions are specified in 6.3.1.1 2:

> … If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions

Thus your char argument a is automatically converted to an int, so it is the correct type for %d.

huangapple
  • 本文由 发表于 2023年8月8日 22:46:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76860686.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定