C 函数参数从有符号整数到无符号整数的转换
在我前几天偶然发现的以下代码片段中,它将C 函数参数从有符号整数到无符号整数的转换,c,type-conversion,implicit-conversion,C,Type Conversion,Implicit Conversion,在我前几天偶然发现的以下代码片段中,它将带符号int传递给一个需要无符号int的函数 #include "stdio.h" void set_data(unsigned int* addr, const unsigned int data) { printf("Inside set_data:%d\n", data); *addr = data; } int main() { unsigned int a = 2; printf("Before set_dat
带符号int
传递给一个需要无符号int
的函数
#include "stdio.h"
void set_data(unsigned int* addr, const unsigned int data)
{
printf("Inside set_data:%d\n", data);
*addr = data;
}
int main() {
unsigned int a = 2;
printf("Before set_data:%d\n", a);
set_data(&a, -10);
printf("After set_data:%d\n", a);
return 0;
}
输出:-注意:编译器没有引发任何警告:-
zhossain@zhossain-linux1:~$ gcc -Wall test.c
zhossain@zhossain-linux1:~$ ./a.out
Before set_data:2
Inside set_data:-10
After set_data:-10
问题:-1.为什么编译器不叫喊?隐式转换?
2.为什么“内部集合数据”打印负整数而
数据
被明确定义为无符号整数
3.是否有可能定义了未定义的行为或实现,这可能不是编写安全可移植代码的良好实践
期待详细解释,如果您能指出相关的SO线程,我也将不胜感激。查看您的代码,我想我理解您的困惑所在。您正在将
-10
作为无符号
值传递,并且您正在用“如果它是一个`无符号的值,为什么它要打印-10
”来挠头?”
这一切归结起来都是零碎的。10
的位是(使用16
位防止大量零)
在大多数计算机中,负值是以两位补码格式存储的(外行术语是所有位加一的倒数)。如果应用两次,则返回相同的数字。因此,-10
的两个补码存储是:
1111111111110110
这将很好地适应和无符号
相同类型的值
下一个难题是“如何打印-10
?”,只要您的值不超过int
的最大值,%d
将愉快地将您提供的位打印为整数。您的代码将-10
赋值为int
,然后作为未签名的传递是没有问题的,因为您传递的是值1111110110
。您可以将值打印为signed int
(-10
)或unsigned int
(4294967286
)
这是您为printf
回答的唯一问题。它应该如何处理这些位?,“我是将1111111111111111111111111010
打印为unsigned
,还是将其打印为int
。这就是你用%u
或%d
告诉我的printf
只要您不尝试使用a
中大于INT\u MAX
的值作为INT
,未定义的行为就没有问题。否则,您就可以了
消化这一点,如果我理解了您的担忧,或者我没有理解您的意思,请告诉我,我很乐意提供进一步的帮助。查看您的代码,我想我理解您的困惑所在。您正在将-10
作为未签名的值传递,您正在用“如果它是一个`无符号值',为什么它要打印-10
它可以归结为位。10
的位是(使用16
位来防止大量的零)
在大多数计算机中,负值以两位补码格式存储(外行术语是所有位加一的倒数)。如果应用两次,则返回相同的数字。因此,-10
的两位补码存储为:
1111111111110110
这将很好地适应和无符号
相同类型的值
下一个难题是“如何打印-10
?”,只要您的值不超过int
,%d的最大值“
将愉快地将您提供的位打印为整数。您的代码将-10
赋值为int
,然后作为未签名的传递是没有问题的,因为您传递的是值1111110110
。您可以将值打印为signed int
(-10
)或unsigned int
(4294967286
)
这是您为printf
回答的唯一问题。它应该如何处理这些位?,“我是将1111111111111111111111111010
打印为unsigned
,还是将其打印为int
。这就是你用%u
或%d
告诉我的printf
只要您不尝试使用a
中大于INT\u MAX
的值作为INT
,未定义的行为就没有问题。否则,您就可以了
请消化这一点,如果我理解您的担忧,或者如果我没有理解您的担忧,请告诉我,我很乐意进一步提供帮助。1)编译器没有“叫喊”(更正确的描述是“发出诊断”)关于隐式转换,因为标准很好地定义了从有符号
类型到无符号
类型的转换-它使用(数学上)称为模运算的方法。调用集_数据(&a,-10)
在调用集_数据()
。将-10
值转换为无符号
时,将产生UINT_MAX-9
值,其中UINT_MAX
是从
获得的,表示无符号int
可以表示的最大值。编译器通常可以配置为发出有关此类转换的警告,但,默认情况下,大多数编译器都配置为不显示警告。如果需要警告,则需要阅读编译器的文档以了解如何显示警告
2) 对printf()
的所有调用都会导致未定义的行为,因为%d
通知printf()
相应的参数的类型为int
,并且您传递了一个未签名的(即类型不匹配)。对于您的特定实现,将int
类型的值转换为unsigned
或从unsigned
类型的值不会更改按位表示,并且传递给printf()
的unsigned
值具有与int