char* f = (char*)malloc(4 * sizeof(char));
f[0] = 0;
f[1] = 0;
f[2] = 0;
f[3] = 1;
unsigned int j = *f;
printf("%u\n", j);
所以如果内存看起来像这样: 0000 0000 0000 0000 0000 0000 0000 0001
程序输出0。 如何使其输出整个32位的uint值?
答案 0 :(得分:3)
因为您正在使用类型推广。 char
会在访问时提升为int
。你没有得到诊断。所以你正在做的是取消引用char
数组中的第一个元素,即0,并将其分配给int
...同样最终为0。
您想要做的是技术上未定义的行为但通常有效。你想这样做:
unsigned int j = *reinterpret_cast<unsigned int*>(f);
此时,您将处理未定义的行为以及平台的字节顺序。您可能没有在字节流中记录的值。您正处于需要熟悉编译器和目标体系结构的领域。
答案 1 :(得分:3)
假设您的平台支持32位长整数,您可以执行以下操作来实现您想要的强制:
char* f = (char*)malloc(4 * sizeof(char));
f[0] = 0;
f[1] = 0;
f[2] = 0;
f[3] = 1;
uint32_t j;
memcpy(&j,f,sizeof(j));
printf("%u\n", j);
请注意整数表示中的endianess。
答案 2 :(得分:2)
为了确保您的代码适用于小端和大端系统,您可以执行以下操作:
char f[4] = {0,0,0,1};
int32_t j = *((int32_t *)f);
j=ntohl(j);
printf("%d", j);
这将在小端和大端系统上打印1。不使用ntohl,1只会在Big Endian系统上打印。
代码有效,因为f
的分配值与Big Endian系统中的值相同。由于网络订单也是Big Endian,因此ntohl会正确转换j
。如果主机是Big Endian,j
将保持不变。如果主机是Little Endian,j
中的字节将被反转。
答案 3 :(得分:1)
行中会发生什么:
unsigned int j = *f;
只是将f的第一个元素赋给整数j。它相当于:
unsigned int j = f[0];
并且由于f [0]为0,它实际上只是将0赋给整数:
unsigned int j = 0;
您必须转换f。
的元素重新解释将始终导致未定义的行为。以下示例显示了此类用法,始终不正确:
unsigned int j = *( unsigned int* )f;
未定义的行为可能会产生任何结果,即使是明显正确的结果。即使这样的代码在第一次运行时看起来产生了正确的结果,也不能证明程序是定义的。该程序仍未定义,可能随时产生不正确的结果。
没有技术上未定义的行为或通常有效,程序未定义或未定义。依赖这些陈述是危险和不负责任的。
幸运的是,我们不必依赖这样糟糕的代码。
您需要做的就是选择将存储在f中的整数的表示形式,然后将其转换。您似乎希望以big-endian存储,每个元素最多8位。这并不意味着机器必须是big-endian,只是表示你在f中编码的整数。在机器上表示整数并不重要,因为这种方法是完全可移植的。
这意味着最重要的字节将首先出现。最重要的字节是f [0],最低有效字节是f [3]。
我们需要一个能够存储至少32位的整数,并且需要输入unsigned long。
类型char用于存储字符而不是整数。应使用无符号整数类型,如unsigned char。
然后只能进行f中编码的big-endian的转换:
unsigned char encoded[4] = { 0 , 0 , 0 , 1 };
unsigned long value = 0;
value = value | ( ( ( unsigned long )encoded[0] & 0xFF ) << 24 );
value = value | ( ( ( unsigned long )encoded[1] & 0xFF ) << 16 );
value = value | ( ( ( unsigned long )encoded[2] & 0xFF ) << 8 );
value = value | ( ( ( unsigned long )encoded[3] & 0xFF ) << 0 );
答案 4 :(得分:-2)
关于发布的代码:
char* f = (char*)malloc(4 * sizeof(char));
f[0] = 0;
f[1] = 0;
f[2] = 0;
f[3] = 1;
unsigned int j = *f;
printf("%u\n", j);
malloc()
的返回类型是void*
,可以将其分配给任何其他指针,因此在对代码应用维护时,转换会使代码混乱,并且可能会出现问题。sizeof(char)
定义为1,因此表达式作为传递给malloc()
的表达式的一部分绝对没有效果int
的大小不一定是4(想想微处理器或64位架构)calloc()
将所有字节预先设置为0x00 0x01
取决于底层架构的Endianness
让我们假设您的计算机目前是little Endian
架构。 (英特尔或类似的)
然后代码应该类似于以下内容:
#include <stdio.h> // printf(), perror()
#include <stdlib.h> // calloc(), exit(), EXIT_FAILURE
int main( void )
{
char *f = calloc( 1, sizeof(unsigned int) );
if( !f )
{
perror( "calloc failed" );
exit( EXIT_FAILURE );
}
// implied else, calloc successful
// f[sizeof(unsigned int)-1] = 0x01; // if big Endian
f[0] = 0x01; // assume little Endian/Intel x86 or similar
unsigned int j = *(unsigned int*)f;
printf("%u\n", j);
}
在编译/链接时,输出以下内容:
1