2009年3月27日星期五

zt ANSI C中取得结构体字段偏移值的惯用法

http://dev.21tx.com/2005/01/18/14190.html

 

假设在ANSI C程序中定义了一个名为MyStruct的结构类型,其中有一个名为MyField的字段,如何取得它在结构体中的偏移?

typedef struct MyStruct_tag
{
  // some fields
  ...

  long MyField;

  // other fields
  ...
} MyStruct;


    最容易想到的方法应该与如下代码差不多:

size_t GetOffset()
{
  MyStruct s;

  return (size_t)( (char*)(&s.MyField) - (char*)(&s) );
}

    这段代码确实能完成任务,但为了取得偏移值,函数不得不定义了一个MyStruct结构体实例,可这有必要吗?仔细想想,结构体的内存布局是在什么时候由谁决定的?没错,是编译器在编译期确定的,它一旦被确定就不会改变了,而依赖于结构体内存布局的字段偏移也就随之确定并不再改变。既然在编译阶段编译器就洞悉了内幕,那么我们完全有理由要求它在编译期为程序提供这些信息。如何做呢?请看下面的代码:

#define MY_OFFSET (size_t)&(((MyStruct*)0)->MyField)

    上面定义的MY_OFFSET宏就是我们要的MyField的偏移。一定有人问,这样强制转换后的结构指针怎么可以用来访问结构体字段?呵呵,其实这个表达式根本没有也不打算访问MyField字段。ANSI C标准允许任何值为0的常量被强制转换成任何一种类型的指针,并且转换结果是一个NULL指针,因此((MyStruct*)0)的结果就是一个类型为 MyStruct*的NULL指针。如果利用这个NULL指针来访问MyStruct的成员当然是非法的,但& (((MyStruct*)0)->MyField)的意图并非想存取MyField字段内容,而仅仅是计算当结构体实例的首址为 ((MyStruct*)0)时MyField字段的地址。聪明的编译器根本就不生成访问MyField的代码,而仅仅是根据MyStruct的内存布局和结构体实例首址在编译期计算这个(常量)地址,这样就完全避免了通过NULL指针访问内存的问题。又因为首址的值为0,所以这个地址的值就是字段相对于结构体基址的偏移。

    如上做法避免了一定要实例化一个MyStruct对象,并且求值是在编译期进行,没有运行期负担。实际上这种利用编译器掌握的整个程序的信息以在编译期计算某些值的方法与现在C++编程中很流行的(静态)元编程技术类似,只不过C++程序员可以利用模板技术在编译期完成非常复杂的计算,而缺乏模板支持的ANSI C在这方面的能力则要弱许多。

    或许因为求结构体字段偏移很常用,ANSI C在标准头文件stddef.h中就专门定义了一个形如offsetof(s,m)的宏来求任意一个结构类型中某个字段的偏移,而且绝大多数C开发系统的实现都采用了上述的方法,例如:

// VC7.1
#ifdef  _WIN64
#define offsetof(s,m)   (size_t)( (ptrdiff_t)&(((s *)0)->m) )
#else
#define offsetof(s,m)   (size_t)&(((s *)0)->m)

2009年3月24日星期二

[转] 有些事,一转身就是一辈子

有些人一直没机会见,等有机会见了,却又犹豫了,相见不如不见。

有些事一直没机会做,等有机会了,却不想再做了。

有些话埋藏在心中好久,没机会说,等有机会说的时候,却说不出口了。

有些爱一直没机会爱,等有机会了,已经不爱了。


有些人很多机会相见的,却总找借口推脱,想见的时候已经没机会了。

有些话有很多机会说的,却想着以后再说,要说的时候,已经没机会了。

有些事有很多机会做的,却一天一天推迟,想做的时候却发现没机会了。

有些爱给了你很多机会,却不在意没在乎,想重视的时候已经没机会爱了


人生有时候,总是很讽刺。

一转身可能就是一世。说好永远的,不知怎么就散了。

最后自己想来想去竟然也搞不清当初是什么原因分开彼此的。

然后,你忽然醒悟,感情原来是这么脆弱的。

经得起风雨,却经不起平凡;风雨同船,天晴便各自散了。


也许只是赌气,也许只是因为小小的事。

幻想着和好的甜蜜,或重逢时的拥抱,那个时候会是边流泪边捶打对方,还傻笑着。

该是多美的画面。

没想到的是,一别竟是一辈子了。

于是,各有各的生活,各自爱着别的人。

曾经相爱,现在已互不相干。

即使在同一个小小的城市,也不曾再相逢。

某一天某一刻,走在同一条街,也看不见对方。

先是感叹,后来是无奈。

也许你很幸福,因为找到另一个适合自己的人。

也许你不幸福,因为可能你这一生就只有那个人真正用心在你身上。

很久很久,没有对方的消息,也不再想起这个人,也是不想再想起这些事

2009年3月19日星期四

keil MDK3.23a + WinARM-2006060无法链接

原来用着keil MDK3.23a + WinARM-2006060 配合的挺好的,不过随着文件和子目录的增多,最近问题多多,首先是选项里的优化等级设置的不能保存,后来是经常链接出错,有时候说找不到文件,而文件名是给的却字母的文件名;有时候是非得跟默认的启动文件链接。感觉应该是keil传递给gcc的链接参数有问题,最后只能采取了一方法,还是不错的,就是使用makefile链接(傻瓜都能想出来的方法,呵呵)。然后一个批处理解决问题。
 
俺的makefile的内容:
#
#  $Id: Makefile 1.1 2009-03-12 22:03:17Z yushiyou $
#  $Revision: 1.1 $
#  $Author: jcw $
#  $Date: 
#  
#  只是链接所有文件的makefile
#  不使用默认的启动文件,使用标准库和数学库,不进行垃圾清理,生成map文件
export CC=D:\WinARM\bin\arm-elf-gcc
export AR=D:\WinARM\bin\arm-elf-ar
export OBJCOPY=D:\WinARM\bin\arm-elf-objcopy
export OBJDUMP=D:\WinARM\bin\arm-elf-objdump
ELF: 
$(CC) -T .\LPC2294-ERAM.ld -Wl,-Map=".\lst\psmu-c30-m.map"  -o .\obj\psmu-c30-m.elf .\obj\*.o -nostartfiles -lm
 
俺的批处理的内容:
REM 链接文件的批处理
D:\WinARM\utils\bin\make ELF
pause

C语言中的对齐

Win32平台下的微软C编译器(cl.exe for 80x86)在默认情况下采用如下的对齐规则: 任何基本数据类型T的对齐模数就是T的大小,即sizeof(T)。比如对于double类型(8字节),就要求该类型数据的地址总是8的倍数,而 char类型数据(1字节)则可以从任何一个地址开始。Linux下的GCC奉行的是另外一套规则(在资料中查得,并未验证,如错误请指正):任何2字节大小(包括单字节吗?)的数据类型(比如short)的对齐模数是2,而其它所有超过2字节的数据类型(比如long,double)都以4为对齐模数。
 
ANSI C规定一种结构类型的大小是它所有字段的大小以及字段之间或字段尾部的填充区大小之和。填充区就是为了使结构体字段满足内存对齐要求而额外分配给结构体的空间。那么结构体本身有什么对齐要求吗?有的,ANSI C标准规定结构体类型的对齐要求不能比它所有字段中要求最严格的那个宽松,可以更严格(但此非强制要求,VC7.1就仅仅是让它们一样严格)。
 
__attribute__((packed))意思是按最小对齐,也就是单字节。__attribute__((aligned(n)))是指按n字节对齐,这里的对齐不仅指起始位置n字节对齐,也指的结束的位置也是n字节对齐。对于结构来说,例如:
struct E{
        char a;
        int b;
        unsigned short c;
        long d;
        unsigned long long e;
        char f;
}__attribute__((aligned(8)));
结构内部的成员按照自己的对齐方式,而该结构的起始和结束位置都要8字节对齐,所以a占4字节,b占4字节,c占4字节,d占4字节,e占8字节,f占8字节(为了结束位置对齐),总共占32字节。
struct E{
        char a;
        int b;
        unsigned short c;
        long d;
        unsigned long long e;
        char f;
}__attribute__((aligned(4)));
a占4字节,b占4字节,c占4字节,d占4字节,e占8字节,f占4字节,共28字节。
 
但是:
struct E{
        char a;
        int b;
        unsigned short c;
        long d;
        unsigned long long e;
        char f;
}__attribute__((aligned(1)));
也是占用28字节,怎样解释?可能,"ANSI C标准规定结构体类型的对齐要求不能比它所有字段中要求最严格的那个宽松",这个条件的优先级更高。它屏蔽了__attribute__((aligned(1)))这个条件。(注意该处编译器是GCC,处理器认为是arm,"Linux下的GCC奉行的是另外一套规则(在资料中查得,并未验证,如错误请指正):任何2字节大小(包括单字节吗?)的数据类型(比如short)的对齐模数是2,而其它所有超过2字节的数据类型(比如long,double)都以4为对齐模数")。
 
而例如#pragma pack(1) ,则应该是对所有数据类型的对齐吧!

利用XMPP协议进行远程控制

原来转过一篇《gtalk机器人实验成功》(http://yushiyou.blogspot.com/2008/09/zt-gtalk.html。刚发现了一个使用于嵌入式系统的XMPP客户端 iksemel(https://www.ohloh.net/p/iksemel ):

iksemel is an XML (eXtensible Markup Language) parser library designed for Jabber applications.

Some features:

Highly portable, builds on all POSIX environments and Windows (via mingw). Suitable for embedded systems. Code is small and highly modular, you can trim unneeded parts. Memory usage is low, parser is quite fast. Provides SAX, DOM and XMPP parsers. TLS (via gnutls) and SASL support for XMPP security. Only UTF8 encoding is built-in supported. Fully documented with examples. Latest source code is currently hosted at this subversion repo:

http://svn.pardus.org.tr/projeler/iksemel/

兼容POSIX接口,那么应该也支持ECOS,RTEMS啊!那就好了,使用块ARM7和COTEX-3内核的ARM即可,跑个ecos还是绰绰有余的!实在不行就用个ATMEL的ARM9,不过50多元,北京君正的也行啊,国产的才30多元,软件支持的也很好,linux,wince的都提供完整的平台软件,功耗很小,可以长期开着,还可以淘宝上买个路由器,刷下机,跑个linux。的gtalk的客户端和机器人,解析远程命令并进行相应的操作,开个灯、开个空调、开个热水器啥的,很是不错!

移植Microchip Graphics Library(PIC GUI)到ARM7 + RA8835(SED1335)上刷屏慢的解决方法

上次移植的Microchip Graphics Library(PIC GUI) 在LPC2214上运行很慢,即使主频提高到48Mhz还是很慢,大概刷一屏要1秒。感觉关键问题,一个是RA8835的读写速度太慢,大约在1MHZ;再一个,底层只实现了画点函数,这样如果填充一个矩形,就必须每个点都要画,而其实一次写可以画8个点,还有每次画点都要先设置光标,读回数据,修改,设置光标,写数据,浪费了大量时间;
 
一种加速的方法是,在片内内存设置一屏数据的缓冲区,写屏时对缓冲区操作,速度快,操作完成后,根据裁剪域,把裁剪域数据一次写入液晶控制器;
 
再一种方法也是在片内内存设置一屏数据的缓冲区,每次操作先对缓冲区操作,然后把得到的字节写入控制器,这样画点时对液晶控制器的读写简化为设置光标,写数据;uc/gui的SED1335驱动(UCGUI332a_LCDDriver的LCDSLin.c文件 )就是采用了这种方法,再加上画水平直线,画垂直直线等的优化函数;
 
经仔细分析,发现第一种方法没法实现,因为在GOLDraw() 函数返回时,没有有效的裁剪域存在;只能使用第二种方法。

2009年3月13日星期五

zt非诚勿扰征婚启事英译版

 
  Here's his announcement looking for a bride.
  你要想找一帅哥就别来了,你要想找一钱包就别见了,硕士学历以上的免谈,上海女人免谈,女企业家免谈(小商小贩除外),省得咱们互相都会失望。刘德华和阿汤哥那种财貌双全的郎君是不会来征你的婚的,当然我也没有做诺丁山的梦。您要真是一仙女我也接不住,没期待您长得更画报封面一样看一眼就魂飞魄散。外表时尚,内心保守,身心都健康的一般人就行,要是多少还有点儿婉约那就更靠谱了。心眼儿别太多岁数别太小,允许时常有不切实际的想入非非,但三句话就能给轰回现实还不气脑顶多有点儿难为情地咧嘴一笑就该干吗干吗去了。我喜欢会叠衣服的女人,每次洗完烫平叠得都像刚从商店里买回来的一样。说得够具体了吧。
  If you are looking for a handsome guy or a wallet,don't reply;If you hold a Master's degree or higher, not possible;girls born in Shanghai, not possible;female entrepreneurs(except small business hawker), not possible, so that we don't waste each other's hope. The Andy Liu or Tom criuse kind, ,who are both wealthy and good-looking, would not make an announcement looking for you. Surely, I don't expect a Notting Hill story either. Even if you're indeed an angle, I won't be able to handle you――I don't expect that you looks like that girl on the magazine cover, just one look crushing people's souls.An averge person, with outside stylishness and inside conservativeness,with fit body and mind,will just do, even better if you're beautifully shy. You need not to play too many tricks or be too young, from time to time, you're allowed to have unrealistic dreams, but a few words is enough to get you back into reality without getting you angry――a little embarassed grin at most,and then do what you ought to do. I like a woman who knows how to fold clothes in a way that whenever you finish washing, ironing and folding them, they will look just like when you bought them from stores. It cannot be more specific than this, can it?
  自我介绍一下,我,岁数已经不小了,日子小康,抽烟不喝酒,留学生身份出去的,在国外生活过十几年,没正经上过学,蹉跎中练就一身生存技能,现在学无所成海外归来,实话实说应该定性为一只没有公司没有股票没有学位的"三无劣海龟"。性格OPEN,人品五五开,不算老实人,但天生胆小,杀人不犯法我也杀不了人,伤天害理了自己良心也备受摧残,命中注定想学坏都当不了大坏蛋。总体而言基本上还是属于对人类对社会有益无害的一类。
  Let me introduce myself for you. I'm a man whose age is no longer small, living a moderately well-off life, who doesn't drink but smoke. I went abroad as a student and spent more than a decade living abroad, but never attended a real education. In wasting time, I learned all sorts of ways to make a living. Now I returned with no achivement at all. To tell you the truth, I should be judged as a "Fake Turtle" without the three―No company, no stocks and no degree. My personality is open;My character is neither good nor bad. I'm not exactly an honest man, but I am without much courage since I was born. Even it is not illegal to kill, I wouldn't kill anyone. My conscience will be tortured by the guilt if I do anything cruel to others.I am meant not to be a villain, even if I try to be one. In general and basically, I'm still one of those who are beneficial and harmless to the mankind and our society.
  有意者电联,非诚勿扰
  Contact me by phone, if you're the one.