0

就编译器类型检查和自动转换而言,printf 的转换说明符是否等同于函数声明?

我试图了解 C 基本数据类型自动类型转换、促销等,并想知道我是否可以使用 printf 而不是虚拟函数来检查会发生什么。

为了让我的问题更清楚,举个例子,

void f1 (int a){}

int main() { f1('c'); return 0; }

帮助我理解如果我声明一个带有 int 参数的函数但在调用中传递 char 类型会发生什么。

我想知道我是否可以打电话

printf("%i", 'c');

为上述目的。

此外,如果有人可以指出一些关于 C 中类型表示/转换/推广的权威资源(在网络或书籍上),我将不胜感激。

4

4 回答 4

3

不。

许多编译器不对格式字符串进行任何类型检查。gcc 在-Wformat使用时确实如此,但这些检查与分配时完成的检查是分开的。

参数按printf原样传递。唯一的转换可能是将其增加到处理器字大小(这就是char变成的方式int),并且它不以任何方式依赖于格式字符串。请参阅 Jonathan Leflfer 的评论,该评论更准确地解释了这一点。

于 2013-07-23T05:57:49.130 回答
2

printf("%i", 'c');您将获得字符“c”的 ASCII 值,即 99。char 到 int 有两种方法。

如果您只想要 char 的 ASCII 值,只需char使用整数说明符进行打印。

如果要将 a 转换char为整数(如 '0' 为 0 或 '1' 为 1),则需要执行以下操作

char a = '4';
int ia = a - '0';  //subtraction of '0'

只是为了更清楚起见, printf 中的说明符表示要从 stack 弹出多少。如果是,%d则 pop 4 bytes(假设为 4 字节的 int)如果是%c,则 pop1 byte等。

于 2013-07-23T06:03:42.247 回答
2

就编译器类型检查和自动转换而言,printf 的转换说明符是否等同于函数声明?

不会。当您将 a 传递char给可变参数函数时,您传递的值将被提升为int。这与您使用的转换说明符无关。C11 标准在 §6.5.2.2p7 中对此进行了描述:

函数原型声明器中的省略号会导致参数类型转换在最后一个声明的参数之后停止。默认参数提升是在尾随参数上执行的。

默认参数提升在 §6.5.2.2p6 中定义为整数提升的超集:

...整数提升在每个参数上执行,并且具有类型的参数float被提升为double. 这些被称为默认参数提升

...和整数促销在 §6.3.1.1p2 中定义:

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


为了让我的问题更清楚,举个例子,

无效 f1 (int a){}

int main() { f1('c'); 返回0;}

帮助我理解如果我声明一个带有 int 参数的函数但在调用中传递 char 类型会发生什么。

不,它没有。'c'实际上是一个int. 如果你不相信我,你自己看看:

#include <stdio.h>

#ifdef __cplusplus
#error "Don't compile C code with a C++ compiler."
#endif

int main(void) {
    printf("sizeof 'c': %zu\n", sizeof 'c');
}
于 2013-07-23T07:03:14.043 回答
1

当您将“c”作为参数传递给函数f1时,字母c (99)的 ASCII 值将存储到a 中。因此,如果您修改下面的f1函数

void f1 (int a){
 printf("\n %d",a); // prints the ascii value of charecter c
 printf("\n %c",a); //prints the o/p as c
 printf("\n %i",a); //prints the ascii value of charecter c again 
}

O/p for the program

99
c
99

您问

I want to know if I can just call printf("%i", 'c');

是的,你可以这样就不需要函数f1的实现了。

于 2013-07-23T06:07:58.037 回答