打印

请教 2维数组 地址传递问题???

[复制链接]
3157|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
avocationA|  楼主 | 2009-3-16 10:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
const static unsigned char A[3][26]=     //创建参数存储区_设定初始值
{
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5  
  {1,2,3,4,3,2,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,},//位数
  {0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},//号
  {1,2,3,4,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},//单位

};
const static unsigned char B[3][26]=
{
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5  
  {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,},//位数
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},//号
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},//单位
};
请教 2维数组 地址传递问题???

/***************************
【函数】:MenuDown()
【功能】:右移
【参数】:无
***************************/
void MenuDown(unsigned char 数组地址变量 unsigned char MenuY)
{ //         ?   
  DATA_1=*(*(A+0)+MenuY);////小数点
  DATA_2=*(*(A+1)+MenuY);//正负号 
  DATA_3=*(*(A+2)+MenuY);//显示单位 
}

请教我想通过参数传递把   上面的A地址   变成B地址   怎么操作

相关帖子

沙发
纯金属| | 2009-3-16 15:56 | 只看该作者

没有看懂楼主的问题

使用特权

评论回复
板凳
biao.l| | 2009-3-16 17:46 | 只看该作者

函数参数定义一个指针P

把P代替函数中的A,就可以通过函数调用把A,B的地址传给P了.

使用特权

评论回复
地板
avocationA|  楼主 | 2009-3-17 06:29 | 只看该作者

谢谢 楼上!

使用特权

评论回复
5
HWM| | 2009-3-17 09:30 | 只看该作者

别把数组看成一个“类型”

使用特权

评论回复
6
林粼粼| | 2009-3-17 09:40 | 只看该作者

unsigned char **PP

使用特权

评论回复
7
xwj| | 2009-3-17 09:58 | 只看该作者

唉,你到底想干什么?

//调试试函数------------------------------------------
void test(unsigned char *PP)                          //
{                                                     //
  LedDat.ShowRadix =*(*(PP+0)+1);//显示位数           //
  LedDat.ShowRadix =*(*(PP+1)+1);//小数点             //
}                                                     //
                                                      //
MMain()                                               //
{                                                     //
  MenuEnter_P(); //正确                               //
  test(A);       //错误!!!!!!!!????       //
}


是要把A的地址传递进test()? 
LedDat.ShowRadix 是单字节变量??
LedDat.ShowRadix 为A[0][0] 再+1???(为什么还要加个1?)

那这样写啊:
void test(unsigned char *PP)                          //
{                                                     //
  LedDat.ShowRadix =*PP  +1;//显示位数           //
  PP++;
  LedDat.ShowRadix =*PP  +1;//小数点             //
}                                                     //

随时谨记:
指针的声明是unsigned char *PP;(有星号就是声明的指针类型!)放在函数参数里的话也是一样,只是最后一个不要“;”号;

指针的赋值是:PP=地址; 没有星号!,地址也没有星号!;

指针内容的取出: *PP或*(指针运算表达式),有星号! “* ”和字符是紧耦合,所以指针要运算后再取出值的话指针表达式要加括号。



唉,都是C语言的基本常识,其实很简单的;
如果LZ还觉得虽然有点绕,甚至绕不清的话,建议LZ先去看书!!!
也就几页纸的内容。

使用特权

评论回复
8
avocationA|  楼主 | 2009-3-17 10:03 | 只看该作者

粘贴 错了!!

   LedDat.ShowBit =*(*(A+0)+1);//显示
  LedDat.ShowRadix =*(*(A+1)+1);//小数

使用特权

评论回复
9
avocationA|  楼主 | 2009-3-17 10:07 | 只看该作者

为了让 人 更好理解 所以就把MenuPlace 变1

LedDat.ShowRadix 为A[0][0] 再+1???(为什么还要加个1?)

---------------------------------------------------------
  LedDat.ShowBit =*(*(P00+0)+MenuPlace);//显示位数
  LedDat.ShowRadix =*(*(P00+1)+MenuPlace);//小数点
  LedDat.ShowSign_P=*(*(P00+2)+MenuPlace);//正负号 
  LedDat.ShowUnit  =*(*(P00+3)+MenuPlace);//显示单位

加1是X方向移动>>>>
*(P00+0)
*(P00+1)
*(P00+2)
是Y方向移动  

使用特权

评论回复
10
avocationA|  楼主 | 2009-3-17 10:08 | 只看该作者

xwj 是我没有说清楚 谢谢指教

使用特权

评论回复
11
HWM| | 2009-3-17 10:11 | 只看该作者

转本人的一个老贴

其中内容未列入随笔,在此帖出以供参考


数组实际上是一个由分层次叠加构造而成的一种数据结构,其最底层的基础就是下标操作符。作为一种操作符不仅可以和数组联用,还可以通过重载改变其原始语义(具体可见新手版内 C++ 随笔-21)。

只要有了一个常量指针,配合下标操作符的使用,就可以形成一个数组的雏形(前提是具备一个以常量指针为起始点的存储空间)。当然作为数组的雏形自然有其缺陷,那就是缺少数组的长度信息,以至于不可能得到其有效的整体特性。因此作为一个“完整”的数组定义还必须加入数组的长度信息。但作为一维数组,相关定义并未改变其“数组名”和下标操作符的基本属性。

那么多维数组情形又将是如何的呢?显然由于多维数组必须含有n-1维下标长度的信息(n>1),所以不可能存在上述数组的原始实现(仅用起始指针和下标)。那么多维数组具体又是如何定义的呢?先列出定义形式:

type A[N1][N2]...[Nn];

其中n为数组的维数,N1...Nn为数组各维的长度。

类似的,若将A独立拿出来看,它还是一个指向数组起始位置的常量指针。问题是在此情况下所指对象的“类型”是什么?是否还能象一维数组那样所指类型为数组单元变量类型呢?显然不行,因为这样的话将失去多维数组中相当重要的长度信息。那么不指向数组单元变量又指向什么呢?答案是,A将被定义为指向“数组类型”type [N2]...[Nn]的指针。由此,实际上还可以得出这样一个结论,数组A是被组织成N1个类型为type [N2]...[Nn]的单元的“一维数组”,其中*(A+i)为此“一维数组”的第i+1个单元(即i+1个数组的数组名)。以此类推,可以得到这样一个表达式:

    *(...*(*(A+i)+j)+...k) <=> A[j]...[k]

利用这种层次叠加构造法,顺理成章地建立了从最原始的数组雏形,通过不断地增加维长信息,最终到多维数组空间的形成机制。

下面列出一个具体的实例:

#include "stdafx.h"

int A[10][20][30];
int x, y;

int main(int argc, char* argv[])
{
    A[1][2][3] = 1234;
    *(*(*(A+3)+2)+1) = 4321;
    x = *(*(*(A+1)+2)+3);
    y = A[3][2][1];

    return 0;
}

使用特权

评论回复
12
xwj| | 2009-3-17 10:21 | 只看该作者

如果是要取出多维数组中的值,应该这样:

还是按字节来定义指针,即:
void test(unsigned char *PP)
{
}
这时,PP每加1就指向下一个字节,也就是按线性寻址。

对于多维数组,A[x][y]的位置其实就是A[0][0]再加上 x*下层就宽度(26)+y,
其实从下面数组赋初值的规律也可以看出:一个一个排列,从A[0][0]开始排满26个就到了A[1][0]:

const static unsigned char A[3][26]=     //创建参数存储区_设定初始值
{
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5  
  {1,2,3,4,3,2,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,},//位数
  {0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},//号
  {1,2,3,4,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},//单位

};
 

然后赋值时可以用:
test(A);                       //--这时A实际上就是A[0][0]

又或者这样赋值:
test(&A[x][y]);                 //--这时传入指向A[x][y]的指针


还可以这样赋值:
test(A + x*26 +y]);                 //--这时传入指向A[x][y]的指针

甚至可以这样写:
还可以这样赋值:
test(&A[0][0] + x*26 +y]);                 //--这时传入指向A[x][y]的指针

注意:
&A[0][0]   实际上就是A
A代表的是&A[0][0]位置的指针,因为A是数组名,
A[0][0]代表的却是这个位置的内容,要获得该位置的指针必须的加上取指针符号“&”!


总之:
    一定要明白数组地址和 地址内元素的关系和区别,不要搞混了;
    指针变量永远只准过地址,指针永远只可能是地址加纯数字,当你把它变成了纯数字或者多个指针相加之类的而又没有强制转换,那就肯定是你搞错了,这是个大大的

BUG!


   

使用特权

评论回复
13
xwj| | 2009-3-17 10:59 | 只看该作者

是的,理解多维数组先得理解多维数组实际上是多层堆叠再

实际上不管多少维度,都是相对于第一个(首地址、数组地址)的下标偏移,
而数组不管是多少维的,都是一段线性(一维)的连续存储空间。

多维数组是这样排列的:
一维:
A[MaxX]:  A[0],A[1],A[2],A[..],A[MaxX-2],A[MaxX-1],          //注意,由于下标从0开始,最大只能是总尺寸-1;
一维对应空间当然就是收地址开始连续MaxX个单元了,所以按*(p+x)也可以取到正确位置的值;

二维,其实就是多组一维叠起来:
A[MaxY][MaxX]:
  A[0][0],A[0][1],A[0][2],A[0][..],A[0][MaxX-2],A[0][MaxX-1], 
  0       1       2       ...      MaxX-2            MaxX-1 
  A[1][0],A[1][1],A[1][2],A[1][..],A[1][MaxX-2],A[1][MaxX-1], 
  MaxX+0  MaxX+01  MaxX+1 MaxX+... MaxX+MaxX-2  MaxX+MaxX-1
  ....
  A[MaxY-2][0],A[MaxY-2][1],A[MaxY-2][2],A[MaxY-2][..],A[MaxY-2][MaxX-2],A[MaxY-2][MaxX-1], 

  A[MaxY-1][0],A[MaxY-1][1],A[MaxY-1][2],A[MaxY-1][..],A[MaxY-1][MaxX-2],A[MaxY-1][MaxX-1], 
  MaxX*(MaxY-1)+0,MaxX*(MaxY-1)+1.....        MaxX*(MaxY-1)+(MaxX-1)也就是MaxX*MaxY-1
  整个数组有MaxX*MaxY个元素,一维下标从0一致排到MaxX*MaxY-1
  
   //注意,同样的,由于下标从0开始,所以MaxY最大只能是总尺寸MaxY-1;


而三维数组,同样就是多组二维数组叠起来,MaxX*MaxY*MaxZ个元素,一维下标从0一致排到MaxX*MaxY+MaxZ-1,自己去类推即可。


存储器空间都是线性编址的,空间坐标、维度转换是最基本的加法和乘法罢了(显示器的时间坐标变换也是一样),
这真的很基本也很简单啊,只要智力没问题,肯定能够自己想明白的:-)



PS:
跑题了,LZ的问题只是在于没搞清楚到底给指针赋了什么类型的值,和怎么取出对应层次的指针的问题。

其实,指针,你声明时是一维的,那不管它指向多少维的数组,它还是一维的!!!

使用特权

评论回复
14
avocationA|  楼主 | 2009-3-17 11:31 | 只看该作者

TO

每个2维数组代表一组数据的属性   他们的y相同  但是x不同(2维数组值是常量)
  
本想用3维数组 但是那样的话太占空间因为  每个2维数组(每组数据)的长度相差太大

所以我就用 N(N>100)个2维数组  ,〈以后可能还要加 多组数据〉

通过test(?) 传递 每个2维数组 的首地址 来切换组 !




const static unsigned char A[5][10]=     
{
........................
};

const static unsigned char B[5][20]=
{
..................
};


const static unsigned char C[5][60]=
{
..................
};

const static unsigned char E[5][60]=
{
..................
};

const static unsigned char F[5][90]=
{
..................
};

我的MCU是16位
他的地址因该也是16位

所以unsigned char **PP  是否因改成 unsigned short **PP

void test(unsigned char **PP)
{
}
----------------------------------------------------------
还是按字节来定义指针,即:  |、  可能不符合我的这个思路!!
void test(unsigned char *PP)|
{                            |
}--------------------------------------------------------






使用特权

评论回复
15
avocationA|  楼主 | 2009-3-17 12:14 | 只看该作者

我只把A当成存地址的变量

我只把A当成存地址的变量
然后想办法用B里的地址传过去.
-----------------------------------------------

使用特权

评论回复
16
avocationA|  楼主 | 2009-3-17 12:14 | 只看该作者

U char *A

U char  *A

51的 @A==*A

使用特权

评论回复
17
xwj| | 2009-3-17 16:30 | 只看该作者

LZ,关于指向指针的指针,可以去看我以前发的那个T9拼音示

如果是准备用数组来存储指针,规范的做法是直接定义个指针数组,而不应该用一大堆的强制转换。

当然,你非要用强制转换也未尝不可,但再怎么说也的把它写完整啊!!!

使用特权

评论回复
18
avocationA|  楼主 | 2009-3-17 18:08 | 只看该作者

恩复习下C 不行俺就用苯的方法解决.

或者一个参数用一个结构体.链表解决
2级指针 初次使用 有点晕

使用特权

评论回复
19
avocationA|  楼主 | 2009-3-18 08:20 | 只看该作者

const static 报错 转不过来

const static unsigned char P09[5][P00_Extent]=     //创建菜单属性存储区
{
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 
  {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,},//显示位数 
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}//最小
};

void Menu_P(unsigned char (*P0X)[26])
{
  
  LedDat.ShowBit   =*(*(P0X+0)+MenuPlace);//显示位数
  LedDat.ShowRadix =*(*(P0X+1)+MenuPlace);//小数点
}


void Menu(void)
{
//int*p=&ver[0][0];
//int**pp=&p;
  Menu_P(P09);
  MenuMode();
  

}

使用特权

评论回复
20
avocationA|  楼主 | 2009-3-18 15:56 | 只看该作者

OK 了NND 是__pmem (编译环境问题)自己C也不牢靠

__pmem unsigned char P00[5][P00_Extent]

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

123

主题

935

帖子

0

粉丝