话说这C中动态获取 2维好比艺术作品中爱情(好烂比喻~~)都是永恒而难缠主题假期写并行作业又碰到了这个问题依然绞尽脑汁
其实 2维理解起来是很容易维是void * 2维自然就是void **高维以此类推然而多了个和数个*好比个“不可逾越障壁”不过直接申请**化很难并且退回也很难上次遇到时候就直接malloc了个width * height大小区域然后写个取值宏看起来很丑陋这次决定做个了断搜到台湾个技术论坛找到了这个终极方案真很妙~
如下:
\" align=top>void**malloc2d(w,h,size)
...{
\" align=top>j;
\" align=top>rowSize=w*size;
\" align=top>indexSize=h*(void*);
\" align=top>void**a=(void**)malloc(indexSize+h*rowSize);
\" align=top>char*dataStart=
(char*)a+indexSize;
\" align=top>for(j=0;j<h;j)
\" align=top>a[j]=dataStart+j*rowSize;
\" align=top>a;
\" align=top>}
参数wh是所申请 2维列数和行数size是单元字节数比如申请个4*5型 2维使用:
=Code> **m = ( **) malloc2d(5, 5, ());
直接使用m[x][y]即可以引用x行y列值
退回时直接使用free(m)即可
跟白老鼠开始相比改了些地方返值改成void **(char *)(a + h)改成了(char *) a + h加进了些循环外计算
解释下~就好像原帖里面cromayen2000所讲动态申请 2维通常需要个index区域和个数据区域index区域保存每行数据区域首地址数据区域存放实际值m地址是index区域首地址
这样对 2维中x行y列元素引用m[x][y]实际上是个两步运算
首先m是个**元素m[x]是*(m + x)即index区域第x个元素内值这个值就是数据区域第x行起始地址*(m + x)类型是*
的后寻找第y列值就是*(*(m + x) + y)正好对**进行两次解除引用得到个而写成中括号表示法m[x][y] = *(*(m + x) + y)
白老鼠把index和数据区域连在了起
+====+
+--+--* |〔0〕
| |----|
+----+--* |〔1〕
| | |----|
| | ~ ~
| | |----|
+------+--* |〔h-1〕
| | | +====+
| | |
| | | 〔0〕 〔w-1〕
| | | +======================+
| | +->| |〔0〕
| | |----------------------|
| +--->| |〔1〕
| |----------------------|[Page]
| ~ ~
| |----------------------|
+----->| |〔h-1〕
+======================+
嗯这个ASCII图画真是绝妙佩服台湾技术人员
首先区域总长度h * (void *) + h * rowSize前个加数就是index区域长度即h个void *指针长度后面加数就是数据区长度h个rowSize
数据区开始也就是开始指针后移整个index区后地址即地址dataStart循环把后面数据区每行开始地址连接到前面index区域
个malloc个free个 2维妙哉~
这个思路方法要比直接栈上申请多个index区域思路和申请w * h大小区域然后算出每个元素地址根本不样
帖子后面讨论了下字节对齐问题白老鼠应该是藐视了字节对齐重要性了稍微弄下SSE也会有感觉字节不对齐话会不见血死掉按照这个只需要保证数据区字节对齐就可以了思路方法是在index和数据区域的间加上padding白老鼠随手写出来疑似有问题自己写了个
\" align=top>void
**malloc2d(width,height,size_tsize,align)
...{
\" align=top>//allocallspaces:indexarea,largestpaddingareaanddataarea
\" align=top>index_size=(void*)*height;
\" align=top>row_size=size*width;
\" align=top>void**p=(void**)malloc(index_size+align+height*row_size);
\" align=top>//computepadding
\" align=top>char*ptr_index_ending=(char*)p+index_size;
\" align=top>
padding=(align-(()ptr_index_ending+1)%align)%align;
\" align=top>//linkindexareaanddataarea
\" align=top>//startingaddressofdataarea
\" align=top>char*ptr_data=ptr_index_ending+1+padding;
\" align=top>for(i=0;i<height;i)
...{
\" align=top>p[i]=ptr_data;
\" align=top>ptr_datasize*width;
\" align=top>}p;
\" align=top>}
在申请总大小时候把最大可能padding申请出来(就是要对齐字节数本身)然后链接时候数据区首地址根据整片区域首地址数值(a地址)加上index区大小适当后移到对齐字节数上[Page]
测试了下应该是好使嗯 最后还是赞下台湾PG们可以看到大家回帖里面重要概念都附上了wiki地址认真劲儿很了不起啊
最新评论