#include<stdio.h>
int main() {
long a = 9;
printf("a = %d",a);//output is 9 but with a warning 'expecting long int'
}
为什么这里不能长时间转换成int?
答案 0 :(得分:2)
一般的变量函数和特别是printf族,都是奇怪的特殊情况。它们因其不存在的类型安全性而臭名昭着,因此如果传递错误的类型或使用错误的格式字符串,则会调用未定义的行为,并且可能发生任何事情。
在您的情况下,很可能int
和long
碰巧具有相同的表示形式,因此尽管有警告,程序仍然有效。
在常规功能的情况下,有一种降级&#34;如果将较大的整数类型传递给期望较小的整数类型的函数,则会发生这种情况。发生这种情况时,您会触发从较大类型到较小类型的转换,这是明确定义的。 (但是,如果混合使用不同签名的类型,结果将是编译器特定的。)
编译器倾向于警告这种隐式转换,因此最好使用强制转换显式进行转换。
答案 1 :(得分:1)
因为这是可变函数在C语言中的行为方式。 printf
只是标准库中的一个函数,没有特殊处理。它被声明为
int printf(const char restrict *fmt, ...);
标准(C99的n1256草案)说(强调我的):
6.5.2.2函数调用
...
6如果表示被调用函数的表达式具有不包含a的类型 原型,整数促销对每个参数执行,参数为 将 float类型提升为double 。这些被称为默认参数 促销 ...
7 ...函数原型声明符中的省略号表示法 参数类型转换在最后声明的参数后停止。 默认参数 促销是在尾随参数上执行的。
这意味着在printf
的所有参数上,float
都会转换为double
,整数提升会出现整数提升。
在6.3.1.1算术操作数/布尔,字符和整数
中2无论int还是unsigned int都可以在表达式中使用以下内容 使用:
- 具有整数类型的对象或表达式,其整数转换等级较小 大于或等于int和unsigned int的等级 - _Bool,int,signed int或unsigned int类型的位字段 如果int可以表示原始类型的所有值,则该值将转换为int; 否则,它将转换为unsigned int。这些被称为整数 促销.48)整数促销活动保持所有其他类型不变。
因为long
的排名大于int,所以整数提升保持不变,格式应适合接受长:
long a = 9;
printf("a = %ld",a);
答案 2 :(得分:1)
以下传递long
,但printf()
期望由int
引起"%d"
。结果:未定义的行为(UB)。如果int
和long
的大小相同,那么UB可能看起来一切正常,或者可能会失败。这是UB。
long a = 9;
printf("a = %d",a); // UB
为什么不能在这里长时间转换为int?
long
可以转换,但代码没有像下面的代码那样指示。
printf("a = %d", (int) a); // OK
整数提升可以以相反的顺序发生...在varivadic函数中如printf()?
整数促销不会以相反的顺序发生,除非代码明确地向下转换或分配给更窄的类型。
有些情况下降级将出现与printf()
一致
以下内容将sc
提升为int
,因为它已传递给printf()
。 printf()
将int
"%hhd"
,signed char
会将其转换为signed char sc = 1;
printf("a = %hhd", cs); // prints 1
,然后打印该数值。
i
以下将printf()
传递给int
作为printf()
。 int
会"%hhd"
signed char
,i
会将其转换为int i = 0x101;
printf("a = %hhd", i); // prints 1
,然后打印该数值。所以在这种情况下,看起来就像with open("state_abbreviations.csv", "r") as f:
# you can use csv.DictReader() instead but lets strive for performance
reader = csv.reader(f)
next(reader) # skip the header
# assuming the first column holds the abbreviation, second the full state name
state_map = {state[0]: state[1] for state in reader}
被降级了一样。
state_map