搜索
bottom↓
回复: 39

21*21二维数组如何定义比较好(都是bit型,定义成char型太浪费空间了)

[复制链接]

出0入0汤圆

发表于 2008-8-7 11:42:43 | 显示全部楼层 |阅读模式
21*21二维数组如何定义比较好(都是bit型,定义成char型太浪费空间了)
感觉这样太浪费空间了unsigned char a[21][21],毕竟取值都是0或者1,定义成什么样的结构体比较好呢?

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2008-8-7 12:54:34 | 显示全部楼层
typedef struct
        {
                unsigned long int a:1;
                unsigned long int b:1;
                        .
                        .
                      依次类推       
                        .
                unsigned long int u:1;
                unsigned long int :11;
        }A;
       
        A data[21];
         引用时data[3].e就是你所说的a[3][5]

出0入0汤圆

发表于 2008-8-7 13:00:41 | 显示全部楼层
1 楼的方法不错
不过把abcd...  改为 L0 L1 L2 L3 ...可能会更直观

不过如果是我的话,我可能定义一个一维数组,然后通过宏,或者函数来读写

出0入0汤圆

发表于 2008-8-7 13:35:24 | 显示全部楼层
实际上如果我做

也会用2楼的方法

出0入0汤圆

发表于 2008-8-7 15:17:53 | 显示全部楼层
贴上代码,如果_id值是常数的话,由于编译器的优化,一般可以产生比较好的代码,当然如果是变量的话,也是支持的
#define BIT_SET(_buf,_id) \
{ ((char *)(buf))[(_id)/(sizeof(char)<<3)] |= 1<<(_id)%(sizeof(char)<<3); }

#define BIT_CLR(_buf,_id) \
{ ((char *)(buf))[(_id)/(sizeof(char)<<3)] &= ~(1<<(_id)%(sizeof(char)<<3)); }

#define BIT_GET(_buf,_id) \
(((char *)(buf))[(_id)/(sizeof(char)<<3)] >> ((_id)%(sizeof(char)<<3))        & 0x01)

#define BIT_ROW_MAX   21
#define BIT_SET2(_buf,_max,_x,_y) BIT_SET((_buf),((_x)*(_max)+(_y)))
#define BIT_CLR2(_buf,_max,_x,_y) BIT_CLR((_buf),((_x)*(_max)+(_y)))
#define BIT_GET2(_buf,_max,_x,_y) BIT_GET((_buf),((_x)*(_max)+(_y)))

int main(int argc, char* argv[])
{
        char buf[256]={0};
        int s=5;;
        BIT_SET(buf,25);
        s = BIT_GET(buf,25);
        printf("25=%d\n",s);
        BIT_CLR(buf,25);
        s = BIT_GET(buf,25);
        printf("25=%d\n",s);

        BIT_SET2(buf,21,3,2);
        BIT_CLR2(buf,21,2,3);
        s = BIT_GET2(buf,21,3,2);
        printf("2,3=%d\n",s);
        BIT_CLR2(buf,21,2,3);
        s = BIT_GET2(buf,21,2,3);
        printf("2,3=%d\n",s);
        printf("Hello World!\n");
        return 0;
}

出0入0汤圆

发表于 2008-8-7 18:56:44 | 显示全部楼层
问下 【1楼】 mingyuexin1981  
        typedef struct  
        {
                unsigned long int a:1;
                unsigned long int b:1;
                        .
                        .
                      依次类推         
                        .
                unsigned long int u:1;
                unsigned long int :11;
        }A;

把 里面的  unsigned long int   换成  unsigned char 有什么区别

出0入0汤圆

发表于 2008-8-7 20:03:26 | 显示全部楼层
typedef struct   
        {  
                unsigned long int a:1;  
                unsigned long int b:1;  
                        .  
                        .  
                      依次类推         
                        .  
                unsigned long int u:1;  
                unsigned long int :11;  
        }A;  
是位段定义,unsigned long int用于表定义一个32位的位段,而unsigned char则定义一个8位的位段,而上面是访问21位

出0入0汤圆

发表于 2008-8-7 20:41:54 | 显示全部楼层
明白  非常感谢

出0入0汤圆

发表于 2008-8-7 21:13:06 | 显示全部楼层
不错

出0入0汤圆

发表于 2008-8-8 11:12:18 | 显示全部楼层
学习了~!~

出0入0汤圆

发表于 2008-8-8 11:18:58 | 显示全部楼层
顶一顶

出0入0汤圆

发表于 2008-8-8 18:14:23 | 显示全部楼层
这些东西 咋在书上都没有介绍的啊,唉~

出0入0汤圆

发表于 2008-8-8 23:11:49 | 显示全部楼层
顶一顶

出0入0汤圆

发表于 2008-8-9 01:56:35 | 显示全部楼层
不算不知道,一算吓一跳。

一楼的方法已经很节省空间了,可是2楼的方法还可以进一步节省空间。例如,21×21,一楼的方法是84字节,二楼的方法是56字节,节约28个字节。很可观呀。

方法      字节占用
2维数组   n×n
1楼       4n
2楼       (n×n + 7)/8,取整

而且2楼的方法可以任意扩展数组的大小。妙得很啊。

出0入0汤圆

发表于 2008-8-9 23:41:42 | 显示全部楼层
学习了

出0入0汤圆

发表于 2008-8-10 00:26:34 | 显示全部楼层
学习了 谢谢

出0入0汤圆

发表于 2008-8-19 08:13:18 | 显示全部楼层
不错.

出0入0汤圆

 楼主| 发表于 2008-8-19 09:10:23 | 显示全部楼层
4的代码谁看懂了,分析下,只能看懂个大概方向.

出0入0汤圆

发表于 2008-8-19 09:20:56 | 显示全部楼层
顶一下,以后应该会用到。。。

出0入0汤圆

发表于 2008-8-19 10:18:13 | 显示全部楼层
回17楼的,<<3 相当于 *8 即一个字节的大小,这样也许能帮助理解

出0入0汤圆

 楼主| 发表于 2008-8-19 10:59:51 | 显示全部楼层
谢谢,
#define BIT_SET(_buf,_id) \
{ ((char *)(buf))[(_id)/(sizeof(char)<<3)] |= 1<<(_id)%(sizeof(char)<<3); }

char buf[256]={0};
BIT_SET(buf,25);
你这个是针对buf整个数组操作,还是数组的前几个操作,为什么定义那么长的数组,只能领悟到数组置1置0,体会不到13楼感受到的那么的美妙.
还期望蚂蚁详细分下下.我有2个地方不大明白,只是能猜出什么意思,不大透彻
1 BIT_SET(buf,25); 传递的参数是什么意思,是buf指向的数组区第25个置1?
2 ((char *)(buf))这个不大明白,类型转换为指向char的指针?
3 上面有的是buf 有的是_buf,通用?

因为这个我没用过,所以不怎么明白,谢谢了.

出0入0汤圆

发表于 2008-8-19 11:04:51 | 显示全部楼层
不错。

出0入0汤圆

发表于 2008-8-19 11:13:15 | 显示全部楼层
1 BIT_SET(buf,25); 传递的参数是什么意思,是buf指向的数组区第25个置1?
如果将buf,看成是bit型缓冲区的话,是第25个
如果是将buf看成char型缓冲区的话,是第25/8个的第25%8位

2.缓冲区指针的强制转换

3.不通用,你真眼尖,我犯了一个错误,正确的应该为
#define BIT_SET(_buf,_id) \
{ ((char *)(_buf))[(_id)/(sizeof(char)<<3)] |= 1<<(_id)%(sizeof(char)<<3); }

#define BIT_CLR(_buf,_id) \
{ ((char *)(_buf))[(_id)/(sizeof(char)<<3)] &= ~(1<<(_id)%(sizeof(char)<<3)); }

#define BIT_GET(_buf,_id) \
(((char *)(_buf))[(_id)/(sizeof(char)<<3)] >> ((_id)%(sizeof(char)<<3))        & 0x01)

#define BIT_ROW_MAX   21
#define BIT_SET2(_buf,_max,_x,_y) BIT_SET((_buf),((_x)*(_max)+(_y)))
#define BIT_CLR2(_buf,_max,_x,_y) BIT_CLR((_buf),((_x)*(_max)+(_y)))
#define BIT_GET2(_buf,_max,_x,_y) BIT_GET((_buf),((_x)*(_max)+(_y)))

出0入0汤圆

 楼主| 发表于 2008-8-19 11:22:39 | 显示全部楼层
明白了,谢谢蚂蚁.

出0入0汤圆

发表于 2008-8-19 11:50:50 | 显示全部楼层
再说几句,
在一个应用中,应该这么用
#define BUFSIZ 4
uchar buf[BUFSIZ]={0};
#define SET(_id) BIT_SET(buf,_id)
#define CLR(_id) BIT_CLR(buf,_id)
#define GET(_id) BIT_GET(buf,_id)

#define LIGHT0   (1<<0)
#define LIGHT1   (1<<1)
...
#define LIGHTn   (1<<n) /* n < BUGSIZ*8*/


函数中调用
  uchar lightState;
  SET(LIGHT0);
  CLR(LIGHT3);
  lightState = GET(LIGHT9);

在51中可以这样优化
  uchar data buf[BUFSIZ]={0};
  { ((char data * data)(_buf))[(_id)/(sizeof(char)<<3)] |= 1<<(_id)%(sizeof(char)<<3); }

出0入0汤圆

发表于 2008-8-19 12:37:26 | 显示全部楼层
很好的思路,顶下

出0入0汤圆

发表于 2008-9-1 10:58:55 | 显示全部楼层
记号

出0入0汤圆

发表于 2010-11-12 15:21:56 | 显示全部楼层
一维的咋搞?没明白

出0入0汤圆

发表于 2010-11-28 23:46:36 | 显示全部楼层
好方法,记下!

出0入0汤圆

发表于 2010-11-29 00:16:01 | 显示全部楼层
学习了

出0入0汤圆

发表于 2010-11-29 00:21:27 | 显示全部楼层
Mark!

出0入9汤圆

发表于 2010-11-29 08:17:15 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-29 09:27:58 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2011-8-10 20:57:01 | 显示全部楼层
学习了

出0入0汤圆

发表于 2011-8-10 21:26:52 | 显示全部楼层
我跟随挖坟的做个标记

出0入0汤圆

发表于 2011-8-23 21:32:47 | 显示全部楼层
谢谢,已经基本领悟,收藏一下,用的时候复习一下

出0入0汤圆

发表于 2011-8-24 04:59:37 | 显示全部楼层
既然有人挖出来了,就标记下。

首先看懂了4楼的前几句:
#define BIT_SET(_buf,_id) \
{ ((char *)(buf))[(_id)/(sizeof(char)<<3)] |= 1<<(_id)%(sizeof(char)<<3); }

#define BIT_CLR(_buf,_id) \
{ ((char *)(buf))[(_id)/(sizeof(char)<<3)] &= ~(1<<(_id)%(sizeof(char)<<3)); }

#define BIT_GET(_buf,_id) \
(((char *)(buf))[(_id)/(sizeof(char)<<3)] >> ((_id)%(sizeof(char)<<3)) & 0x01)

20楼问道:((char *)(buf))这个不大明白,类型转换为指向char的指针?

我理解这里做强制类型转换有一点好处:buf数组元素可以是任何整数类型,只要字节数量足够就可。比如楼主的问题可以定义
char buf[56];//21*21=441, 56*8=448 > 441.
也可以定义
int buf[14];//21*21=441, 14*32=448 > 441.

两个buf都可以直接使用4楼方法
BIT_SET(buf, 20);

以及
BIT_SET2(buf, 21, 0, 20);

出0入0汤圆

发表于 2011-8-24 08:59:37 | 显示全部楼层
受教!

出0入0汤圆

发表于 2012-6-4 16:57:24 | 显示全部楼层
很不错,研究下
头像被屏蔽

出0入0汤圆

发表于 2012-12-6 10:20:55 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 05:14

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表