为什么有三个零后跟数组的值?

时间:2016-03-20 13:02:06

标签: c arrays pointers

这是该计划: -

#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.如果错误请解释。

3 个答案:

答案 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

其他排序是可能的,但现在很少见。