使用指针

时间:2016-11-19 00:02:45

标签: c++ c pointers memory binary

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值?

5 个答案:

答案 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);
  1. 在C中,来自malloc()的返回类型是void*,可以将其分配给任何其他指针,因此在对代码应用维护时,转换会使代码混乱,并且可能会出现问题。
  2. C标准将sizeof(char)定义为1,因此表达式作为传递给malloc()的表达式的一部分绝对没有效果
  3. int的大小不一定是4(想想微处理器或64位架构)
  4. 函数:calloc()将所有字​​节预先设置为0x00
  5. 哪个字节应设置为0x01取决于底层架构的Endianness
  6. 让我们假设您的计算机目前是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