这是该计划: -
#include<stdio.h>
int main()
{
int a[8]={1,2,3,4,5,6,7,8,9},i;
char* p;
p=(char*)a;
printf("%d",*p);
for( i=0;i<32;i++)
{
p=p+1;
printf("%d",*p);
}
return 0;
}
输出: -
$ ./a.out
100020003000400050006000700080000
为什么输出会这样?
为什么有三个零后跟数组的值?
char
指针递增1个字节。存储在内存中的二进制表示形式为0000000 00000000 00000000 00000001.是吗?因此输出应该像0 0 0 1.如果错误请解释。
答案 0 :(得分:5)
<强>解决方案强>
char
通常为1个字节,而int
通常为4个字节。在内存中,如果您需要增加char pointer
4次以完全增加int
。
更改
char* p;
p=(char*)a;
为:
int* p;
p=(int*)a;
这将删除所有零
同时更改
int a[8]={1,2,3,4,5,6,7,8,9},i;
为:
int a[9]={1,2,3,4,5,6,7,8,9},i;
因为你没有分配足够的空间并改变
printf("%d",*p);
for( i=0;i<32;i++)
{
p=p+1;
printf("%d",*p);
}
为:
for(i=0; i<9; i++)
{
printf("%d",*p);
p=p+1;
}
内存映射可视化
C语言和大多数语言中的数组只是存储在连续内存位置的元素。 int array[2] = {1,2}
在内存中看起来像这样:
// Assuming array starts at location 0x000 (in hex)
// Keep in mind a byte is 8 bits so a byte can contain values from 0x00 to 0xff
location: value:
0x00 = [0x01] // first byte of first int
0x01 = [0x00] // second byte of first int
0x02 = [0x00] // third byte of first int
0x03 = [0x00] // fourth byte of first int
0x04 = [0x02] // first byte of second int
0x05 = [0x00] // second byte of second int
0x06 = [0x00] // third byte of second int
0x07 = [0x00] // fourth byte of second int
如您所见,int
占用4个字节。 int *
增加4个内存位置,这将使您获得下一个整数值。在您的情况下,在增加char *
后,您只需增加int
的四分之一并打印出零(其中3个)。
如果您尝试int array[2] = {256, 2}
并使用char *
进行迭代,我相信您会打印出来:
0 1 0 0 2 0 0 0
这是因为256等于0x100因此它不能存储在一个字节中并且必须利用第一个int
内的第二个字节。内存映射将如下所示:
location: value:
0x00 = [0x00] // first byte of first int
0x01 = [0x01] // second byte of first int
0x02 = [0x00] // third byte of first int
0x03 = [0x00] // fourth byte of first int
0x04 = [0x02] // first byte of second int
0x05 = [0x00] // second byte of second int
0x06 = [0x00] // third byte of second int
0x07 = [0x00] // fourth byte of second int
答案 1 :(得分:2)
你的循环访问32个地址n = 0; n&lt; 32。 假设整数占用系统上的4个字节,那么每次第4次只访问4字节整数开头的字节。
对于每个循环,此代码递增4。
#include<stdio.h>
int main()
{
int a[8]={1,2,3,4,5,6,7,8}, i;
char* p;
p=(char*)a;
for( i = 0; i < 32; i += 4) {
printf("%d\t",*(p+i));
}
printf("\n");
return 0;
}
使用此
,循环控制将更加强大for( i = 0; i < 32; i += sizeof(int)) {
因为它会将增量设置为任何大小&#39;整数&#39;是在它运行的机器上。
还有其他问题,包括您的数组分配超过分配的数组大小。
是否有理由不仅访问数组元素:
#include<stdio.h>
int main()
{
int a[8]={1,2,3,4,5,6,7,8}, i;
for(i = 0; i < sizeof(a)/sizeof(a[0]); i ++) {
printf("%d\t", a[i]);
}
printf("\n");
return 0;
}
这可以帮助您了解整数的存储方式。由于它是一个有符号的值,因此很可能是两个补码表示法。
#include<stdio.h>
int main()
{
int a[8] = {1, -2147483647 ,3,4,5,6,7,8}, i;
char* p;
p=(char*)a;
for( i = 0; i < 32; i++) {
printf("%d\t",(*p));
p++;
if (i%4 == 3) printf("\n");
}
return 0;
}
递减负数后再次运行(32位有符号整数的最大负数) \ t和附加的printf行有助于格式化输出,使其更容易理解。另请注意,p在打印后递增,而不是之前。在原始代码中,您访问的是超出数组中使用的字节的末尾。
同时删除第一个printf行,因为它会混淆输出
答案 2 :(得分:1)
这是一个endian问题。
存储在内存中的二进制表示形式为0000000 00000000 00000000 00000001?是吗?
是 - 但请考虑 存储这些字节的位置。
所以输出应该像0 0 0 1.如果错误请解释
OP的情况并非如此,而不是如此。
[我们假设int
的大小是char
的4倍,而char
的大小是8位]
为什么这个c程序的输出是这样的?
4内存中的顺序取决于endian。在OP的情况下,最低有效字节存储在第一个地址中,然后剩下的3个可能存在于下一个被寻址字节中的每个更高有效字节中。这是 little endian 。
在另一台机器上,订单可能会按照OP期望的顺序颠倒 - 这是 big endian 。
其他排序是可能的,但现在很少见。