查看整数的内存表示的C程序

问题描述 投票:0回答:1

我想知道整数在内存中的样子(而不仅仅是将整数转换为二进制),所以我写了一个小的C程序,从命令行中获取一个整数,然后将指针指向一个典型的C 32位整数的四个字节,并得到它的十六进制值。

这对于正整数来说非常有效。然而,一旦你输入一个负整数,你就会得到有趣的输出,好像十六进制指针不再知道该做什么。

$ ./int2bin 1
Binary representation of 1 is:
01000000
$ ./int2bin -2
Binary representation of -2 is:
fffffffeffffffffffffffffffffffff

我的代码如下 我是C语言的新手,所以我试图做的事情可能是非常幼稚的,如果不是完全错误的话。但是可以使用一些.提示。

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>

char* int2bin(int x) {
    char *y = (char *) &x;
    char *returnString = malloc (sizeof(char) * 33);

    for (int i = 0; i<4; i++) {  // increase the pointer to the next byte at every iteration
        sprintf(returnString, "%s%02x", returnString, *(y+i));  // get the hex value for the data under the pointer
    }

    return returnString;
}


int main(int argc, char* argv[])
{
    if (argc <= 1) {
        printf("No arguments entered\n");
        return 1;
    }

    int x = atoi(argv[1]); // convert argument to integer

    printf("Binary representation of %d is:\n", x);
    printf("%s\n", int2bin(x));

    return 0;
}
c pointers
1个回答
0
投票

当你把 *(y+I)sprintf,它会被提升为一个更宽的整数。特别是,这将会导致符号扩展,使大于0x80的字节在十六进制中加上一堆ff的前缀。这可以通过将 y 类型 unsigned char这意味着它将是零扩展而不是符号扩展。

unsigned char *y = (unsigned char *) &x;
sprintf(returnString, "%02x%02x%02x%02x", *(y), *(y+1), ...);

所有其他的例子 char 可以保持 char 而不需要做成无符号的。

你也可以使用掩码。

sprintf(returnString, "%02x%02x%02x%02x", 0xff & *(y), 0xff & *(y+1), ...);

2
投票

我的版本在你的函数中。

char * int2bin(int x)
{
    unsigned char *y = (unsigned char *) &x; // char may work but logically %02X format is unsigned
    char * returnString = malloc( sizeof x * 2 + 1 ); // 33 is too much (16 bytes long int type?)

    returnString[0] = 0;
    for ( int i = 0; i < sizeof x; i++ )
    {
        sprintf( returnString + strlen( returnString ), "%02X", y[i] );  // get the hex value for the data under the pointer
    }

    return returnString;
}

2
投票

如果你用 "unsigned char *"来表示 "y", 那就能解决你的符号整数问题. 另外,你生成'returnString'的方式有点低效,因为你在每次循环时都要通过'for'循环把前一个字符串重复写回自己的身上。 这应该可以解决这两个问题。

char  *int2bin( int x )
{
    unsigned char  *y;
    char           *returnString;
    char           *retPtr;
    int            i;
    char           *hexDigits   = "0123456789ABCDEF";

    y = (unsigned char *) &x;
    returnString = malloc (sizeof(int) * 2 + 1);

    if (returnString != NULL) {
        retPtr = returnString;
        for (i = 0; i < sizeof(int); i++) {
            /* Strip off the high order nibble of the byte and the bits
               right to get a value of 0 to 15.  Use that to index into
               the hexDigits string to get the associated hex digit for
               that value, storing it in the next returnString position. */
            *retPtr = hexDigits[(y[i] & 0xF0) >> 4)];

            /* Position the pointer into the returnString to where the
               next hex digit needs to be placed */
            retPtr++;

            /* Strip off the lower order nibble of the byte (which is
               already in the range of 0 to 15.  Use that to index into
               the hexDigits string to get the associated hex digit for
               that value, storing it in the next returnString position. */
            *retPtr = hexDigits[y[i] & 0x0F];

            /* Position the pointer into the returnString to where the next
               hex digit or the terminating NULL character needs to be placed */
            retPtr++;
        }

        /* Add a trailing NULL character to terminate the generated string */
        *retPtr = '\0';
    }

    return (returnString);
}

或者,如果你真的想用sprintf,那就用这个。

char  *int2bin( int x )
{
    unsigned char  *y;
    char           *returnString;
    char           *retPtr;
    int            i;

    y = (unsigned char *) &x;
    returnString = malloc (sizeof(int) * 2 + 1);

    if (returnString != NULL) {
        retPtr = returnString;
        for (i = 0; i < sizeof(int); i++) {
            retPtr += sprintf(retPtr, "%02X", y[i]);
        }
        *retPtr = '\0';
    }

    return (returnString);
}

不管是哪种方法,记得在调用例程中使用返回字符串后要 "释放 "它,否则你会有内存泄漏。 更好的解决方案可能是把要用来接收字符串的缓冲区作为参数传递,同时在返回语句中也返回这个地址。 这样一来,它仍然可以在另一个函数调用中被调用(例如'printf')。 就像这样。

char  buffer[sizeof(int)*2 + 1];
int   x;

x = 12345;

printf("Converting %d -- %s\n", x, int2bin(buffer, x));

你在这里要做的基本上是一个内存位置的十六进制转储。 因此,一个通用的HexDump函数可能更有用,因为它可以用于任何大小的数据区域,而不仅仅是一个整数。 比如说,你可以这样调用它

char  *HexDump( char *buffer, void *data, int dataSize )
{
    char           *bufferPtr;
    unsigned char  *dataPtr;
    int            i;
    char           *hexDigits   = "0123456789ABCDEF";

    if (buffer != NULL) {
        bufferPtr = buffer;
        dataPtr = (unsigned char *) data;
        for (i = 0; i < dataSize; i++) {
            *bufferPtr = hexDigits[(dataPtr[i] & 0xF0) >> 4)];
            bufferPtr++;
            *bufferPtr = hexDigits[dataPtr[i] & 0x0F];
            bufferPtr++;
        }

        *bufferPtr= '\0';
    }

    return (buffer);
}

你可以这样调用它

char  buffer[sizeof(int) * 2 + 1];
int   x;

x = 12345;
printf("Converting %d to hex -- %s\n", x, HexDump(buffer, &x, sizeof(x)));

希望能帮到你...

© www.soinside.com 2019 - 2024. All rights reserved.