[求教]二维数组行之间存储为什么不是连续的?

影儿 2011-07-29 09:28:34

比如一个二维数组, a[2][2] , 按数组的连续存储观点来看,应该是 a[0][0], a[0][1], a[1][0], a[1][1] 连续存储在一个内存块里。但是通过实验, 只是同一行地址连续存储,不同行之间却不是地址连续的,比如 a[0][0] 与 a[0][1] 是地址连续的, a[1][0] 与 a[1][1] 是连续的, 但 a[0][1] 与 a[1][0] 却不是连续的。是程序写错了, 还是 这种观点是错误的? 或者二维数组的存储地址分配依赖于编译器?

请看下面的程序:


#include <stdio.h>

#define ARRAYLEN 5

typedef char Type;

void printAddr(Type* arr, int len);
void printAddr2d(Type** arr2d, int rows, int cols);

int main()
{
Type arr[ARRAYLEN];
Type arr2d[ARRAYLEN/2+1][ARRAYLEN];
printf("The address of the array: \n");
printAddr(arr, ARRAYLEN);
printf("-------------------------------\n");
printf("The address of 2-d array: \n");
printAddr2d((Type**)arr2d, ARRAYLEN/2+1, ARRAYLEN);
printf("-------------------------------\n");
return 0;
}

/*
* 打印一维数组的元素地址
*/
void printAddr(Type* arr, int len)
{
int i;
for (i = 0; i < len; i++) {
printf("0x%x%c", (unsigned)(arr+i), (i == len-1) ? '\n': ' ');
}
}

/*
* 打印二维数组的元素地址
*/
void printAddr2d(Type** arr2d, int rows, int cols)
{
int i, j;
for (i = 0; i < rows; i++) {
printf("row[%d]: ", i);
for (j = 0; j < cols; j++) {
printf("0x%x ", (unsigned)(*(arr2d+i)+j));
}
printf("\n");
}
}





用 gcc 编译过: $ gcc -Wall arrayAddr.c -o arrayAddr
$ arrayAddr

一次运行结果如下:

The address of the array:
0xbfa3723b 0xbfa3723c 0xbfa3723d 0xbfa3723e 0xbfa3723f
-------------------------------
The address of 2-d array:
row[0]: 0xbfa37248 0xbfa37249 0xbfa3724a 0xbfa3724b 0xbfa3724c
row[1]: 0x1e2985 0x1e2986 0x1e2987 0x1e2988 0x1e2989
row[2]: 0xb0eb60 0xb0eb61 0xb0eb62 0xb0eb63 0xb0eb64
-------------------------------



...全文
1776 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
研儒 2012-09-27
  • 打赏
  • 举报
回复
非标的是怎么规定的呢?请举一例说明,如果不顺序存储,还是数组?
AnYidan 2011-07-29
  • 打赏
  • 举报
回复
标准上规定是连续的,除非你的 ide 是非标的
影儿 2011-07-29
  • 打赏
  • 举报
回复
现在的问题是, 将二维数组传入指向指针的指针参数时, 行之间的存储地址不连续, 这一定是类型转换过程中发生了什么, 导致每一行的起始存储地址各自独立。 那么, 究竟发生了什么呢?
影儿 2011-07-29
  • 打赏
  • 举报
回复
恩, 我把函数参数中指向指针的指针换成二维数组形式, Type** ---> Type[][ARRAYLEN] 就是地址连续的了。 看来 Type** 和 Type[][ARRAYLEN] 不能混用阿, 我以为传入 Type** 表示二维数组会更灵活一点(可以处理动态存储分配的情况)
void printAddr2d(Type arr2d[][ARRAYLEN], int rows, int cols);
(unsigned)(arr2d[i]+j)

将二维数组传入指针的指针参数时 gcc 提出了警告, 我直接强制类型转换压下去了,呵呵
这个区别还是要仔细学习中。。。
sdupoplar 2011-07-29
  • 打赏
  • 举报
回复
*(arr2d+i)+j) == arr2d[i]+j
pengzhixi 2011-07-29
  • 打赏
  • 举报
回复
因为你把2维数组当成2级指针来使用,你本身的程序有问题。就不要乱怀疑了。
nnull 2011-07-29
  • 打赏
  • 举报
回复
最重要的是 *( (Type**)arr2d ) 指向的是数组内的的数据,你可以在输出之前给 arr和arr2d赋上值,便明白了。
nnull 2011-07-29
  • 打赏
  • 举报
回复
程序寻址错误:
...
printAddr2d((Type**)arr2d, ARRAYLEN/2+1, ARRAYLEN);
...
printf("0x%x ", (unsigned)(*(arr2d+i)+j));

将2维数组直接转换为指向指针的指针传递过去是错误的,指针的大小是固定的,数组的大小却是不定的

比如:
Type** pxxx;
如果pxxx的地址是 0x000011111 pxxx+1的地址就是 pxxx+sizeof(void*)=0x000011119 //32位程序中sizeof(void*) 等于8

char pyyy[2][2]
如果pyyy的地址是0x00002222 pyyy[0][1]的地址是0x00002223
sdupoplar 2011-07-29
  • 打赏
  • 举报
回复
VC6下的结果:

The address of the array:
0x12ff78 0x12ff79 0x12ff7a 0x12ff7b 0x12ff7c
-------------------------------
The address of 2-d array:
row[0]: 0xcccccccc 0xcccccccd 0xccccccce 0xcccccccf 0xccccccd0
row[1]: 0xcccccccc 0xcccccccd 0xccccccce 0xcccccccf 0xccccccd0
row[2]: 0xcccccccc 0xcccccccd 0xccccccce 0xcccccccf 0xccccccd0
-------------------------------
Press any key to continue

连续。

按道理来说一般是连续的,难道特殊情况下,编译器优化???

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧