对于初学者,我的主要目标是在64位环境中将unsigned long转换为unsigned int(并且在没有任何编译警告的情况下执行此操作)。这可以通过此功能轻松完成:
unsigned int a_to_b(unsigned long a)
{
return((unsigned int)(a));
}
虽然它给出了正确的结果,但问题是在64位环境中它会在编译时抛出警告:
1506-742(I)64位可移植性:通过将unsigned long int类型转换为unsigned int类型可能导致数字丢失。
要绕过此警告,我们尝试了此功能:
unsigned int a_to_b(unsigned long a)
{
unsigned int b;
int skip = sizeof(unsigned long) - sizeof(unsigned int);
memcpy(&b, (&a)+skip, sizeof(b));
return(b);
}
现在这并没有在编译时发出任何警告,但它没有给出正确的输出。 我在32位编译器中尝试了相同的代码,它工作正常。
请建议如何纠正memcpy的这种行为或绕过警告的任何其他方式。
答案 0 :(得分:2)
#include <limits.h>
unsigned int a_to_b(unsigned long a)
{
return(a & UINT_MAX);
}
在Mac OS X 10.9.4上传递,GCC 4.9.1设置为非常繁琐:
gcc -O3 -g -std=c11 -Wall -Wextra -Werror -c cvt.c
我无法在AIX上测试(或者是HP-UX?)。
如评论中所述:
我真的不喜欢这个主意,但有一种可能性是:
union { unsigned long ul; unsigned int ui[2]; } u;
并将参数分配给
u.ul
并返回u.ui[0]
或u.ui[1]
(可能是后者,因为AIX运行在大端的Power芯片上,至少在默认情况下是这样)。这是一个骗子。编译器可能足以发现“误用”,但可能不会。
充实为半便携式代码:
unsigned int a_to_b(unsigned long a)
{
const unsigned long byteorder = 0xFF;
const int LOW_ORDER_4_BYTES = (*(char *)&byteorder == 0);
union
{
unsigned long ul;
unsigned int ui[2];
} u;
u.ul = a;
return(u.ui[LOW_ORDER_4_BYTES]);
}
在小端机器上测试,它给出了正确的结果。我认为它应该会自动检测大端机器并在那里给出正确的结果,但我还是无法验证。
完整的测试代码:
#include <stdio.h>
unsigned int a_to_b(unsigned long a);
unsigned int a_to_b(unsigned long a)
{
const unsigned long byteorder = 0xFF;
const int LOW_ORDER_4_BYTES = (*(char *)&byteorder == 0);
union
{
unsigned long ul;
unsigned int ui[2];
} u;
u.ul = a;
return(u.ui[LOW_ORDER_4_BYTES]);
}
int main(void)
{
unsigned long x = 0xFEDCBA9876543210ULL;
printf("0x%.8X\n", a_to_b(x));
return 0;
}
输出:
0x76543210
答案 1 :(得分:0)
不要这样做,可能导致特定机器中的陷阱表示。
你的电脑是小端的。你应该这样写:unsigned int a_to_b(unsigned long a)
{
unsigned int b;
memcpy(&b, &a, sizeof(b));
return(b);
}