刚才看到自己曾经写的一段代码,名为“print_bit.c”的c文件。虽然已经想不起来是为何写它,但经分析可知源目的可能是想将一个int型的数按字节打印,顺便可以分析出系统是大端还是小端。
代码如下:
main()
{
int p = 3;
printf("*(&p):%x\t%x\n",*(char *)(&p),(char *)((&p)+0));
printf("*(&p+1):%x\t%x\n",*(char *)((&p)+1),(char *)((&p)+1));
printf("*(&p+2):%x\t%x\n",*(char *)((&p)+2),(char *)((&p)+2));
printf("*(&p+3):%x\t%x\n",*(char *)((&p)+3),(char *)((&p)+3));
}
运行结果如下:
由上述结果可知,这段代码有误!
首先,程序没有依照预想的输出 int p 的四个字节的值;其次,由第二列的数据可知,地址长度为4个字节。也就是说,(&p+1)指向了p的下4个字节的首地址(此处越界访问了),以此类推。
所以说,&p+1中的1代表多少,与定义p时的类型有关。当我将p定义为char型时,第二列的值是依次增加1的。
那么如何将一个数据以字节形式打印出来呢?首先需要将p的地址强制转换并赋值给unsigned char *型的变量,然后再依次打印,代码如下:
main()
{
int p1 = 3;
unsigned char *byt = (unsigned char *)&p1;
printf("*(&p+0):%x\t%x\n",*(byt),(unsigned int)byt);
printf("*(&p+1):%x\t%x\n",*(byt+1),(unsigned int)(byt+1));
printf("*(&p+2):%x\t%x\n",*(byt+2),(unsigned int)(byt+2));
printf("*(&p+3):%x\t%x\n",*(byt+3),(unsigned int)(byt+3));
}
下面就是我们想要的结果了:
由此我们还可以知道本系统是小端系统。
下面附上不同类型对象的字节表示:(摘自《深入理解计算机系统》第二章)
#include <stdio.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, int len)
{
int i;
for(i = 0; i < len; i++)
printf(" %.2x",start[i]);
printf("\n");
}
void show_int(int x)
{
show_bytes((byte_pointer) &x,sizeof(int));
}
void show_float(float x)
{
show_bytes((byte_pointer) &x,sizeof(float));
}
void show_pointer(void *x)
{
show_bytes((byte_pointer) &x,sizeof(void *));
}
void show_double(double x)
{
show_bytes((byte_pointer) &x,sizeof(double));
}
//测试
main()
{
int ival = 3;
float fval = 0.0;
double dval = 0.0;
int *pi = &ival;
float *pf = &fval;
show_int(ival);
show_float(fval);
show_double(dval);
show_pointer(pi);
show_pointer(pf);
}
我的测试结果如下: