我想知道整数在内存中的样子(而不仅仅是将整数转换为二进制),所以我写了一个小的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;
}
当你把 *(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), ...);
我的版本在你的函数中。
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;
}
如果你用 "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)));
希望能帮到你...