发新帖我要提问
12
返回列表
打印

第三道嵌入式系统功夫题

[复制链接]
楼主: djyos
手机看帖
扫描二维码
随时随地手机跟帖
21
sz_kd| | 2008-2-27 20:51 | 只看该作者 回帖奖励 |倒序浏览

哎~~~~~~~~~~~

使用特权

评论回复
22
computer00| | 2008-2-27 21:42 | 只看该作者

除了常见的大小端问题和对齐问题之外,想不出还有什么问

要是我写程序就一个个比较,干脆。

if((buf[0]!='A')||(buf[1]!='B')||(buf[2]!='C')||(buf[3]!='D'))
return false;
else return true;

使用特权

评论回复
23
dai_weis| | 2008-2-27 21:51 | 只看该作者

我也是一个一个的比较然后确定结果

这样程序容易读和理解,但是可能效率和速率不高,但可移植性应该好些

使用特权

评论回复
24
djyos|  楼主 | 2008-2-27 21:53 | 只看该作者

我的见解

sinanjj同学:你的语法分析非常正确,只是偏了题,我这道题和前面的几道题都不是语法问题,语法问题书上都有,按HWM同学的建议,看书可矣。第二道题见帖子“再来一道功夫题”。
本题答案:
问题1:由于没有考虑字节序、对齐等问题,故verify函数是错误的。
问题2:在纯8位机小端模式下,或者允许不对齐访问的x86系在CPU,verify函数能给出正确的结果。
问题3:a、字节序的问题,圈圈已经回答了。
       b、对齐问题,d1d2同学已经回答了。
       c、字长问题,对于纯16位或32位(不能以字节寻址)计算机,如Ti的24和28系列cpu,这类cpu的c编译器往往用一个16位或32位字存储一个字符,把字符数组转换成32位数也不能得到正确的结果。
       就这么多,欢迎补充。

使用特权

评论回复
25
computer00| | 2008-2-27 21:58 | 只看该作者

最后一类C编译器比较特殊,羚羊16位MCU的C编译器也是如此,

char是16位的。

使用特权

评论回复
26
HWM| | 2008-2-28 08:04 | 只看该作者

呵呵,如果LZ真的要这样玩的话可用union,一石双鸟(不,一

但实在没有多大意义。

使用特权

评论回复
27
djyos|  楼主 | 2008-2-28 10:56 | 只看该作者

难道HWM大侠不知道大名鼎鼎的MISRA C

    MISRA C:2004明文规定不得使用union,不是没有道理的。ucosii就得意地宣称自己99%符合MISRA C,不信你去看看ucosii的代码,要是能找到一条union,我把它吃了。
    这些可是书上有的哟,我按楼上的指示看书了,楼上自己别舍不得。

使用特权

评论回复
28
HWM| | 2008-2-28 11:25 | 只看该作者

楼主:你都知道MISRA C 2004不支持union,还出这种馊题?

看清了,我说的是“如果LZ真的要这样玩的话”。清楚了没有?若没就再加副眼镜。

使用特权

评论回复
29
平常人| | 2008-2-28 14:07 | 只看该作者

请教LZ一个问题:uint32是MISRA C 2004定义的标准数据类型吗?

对不起,我没有看过这个标准的文本。

看到LZ给出的题目中出现uint32这样的类型,我知道这不是ANSI-C的标准数据类型,但不知道它是否是MISRA C 2004定义的标准数据类型;如果是MISRA C 2004定义的标准数据类型,标准定义了这个类型的长度了吗?是多少位?

使用特权

评论回复
30
xiezonglin| | 2008-2-28 21:24 | 只看该作者

LS,这是自己定义的类型,只是为了移植性好而已

使用特权

评论回复
31
djyos|  楼主 | 2008-2-28 22:25 | 只看该作者

回平常兄

uint32是自己定义的类型,为了移植方便,当开发环境改变时,需要修改它的定义以确保是32位的,比如在32位系统中,定义
typedef unsigned int uint32;
在16位系统中,定义
typedef unsigned long uint32;

至于MISRA C 2004,实际上与我这道题无关,使用union也解决不了本题的问题,union只能解决对齐的问题,字长问题和大小端问题是解决不了的,也就是说,问题3的三个因素中,只解决了一个。有人提出用union可以解决问题,才借用MISRA C 2004的规定,从侧面证明union不是一个精确和安全的数据类型。

使用特权

评论回复
32
平常人| | 2008-2-28 22:40 | 只看该作者

如果真的为了可读性和移植方便,应该采用22楼的方法

你可以自定义变量类型,但不宜用在本题的场合。

反对为了程序的精炼或炫耀自己的编程技巧而使用带有歧义性或移植困难的语句;如果一定要用,就必须在该语句的旁边使用更大的篇幅说明语句的适用范围,在可能的情况下使用ASSERT限定使用条件,如:ASSERT(sizeof(uint32)==32)

使用特权

评论回复
33
djyos|  楼主 | 2008-2-28 22:49 | 只看该作者

平常大侠认真读题哦,还有8楼的说明

认真读题,冷静思考,才是平常心。
我本来就是拿了一段错误代码,讨论的也是这段代码错在哪里,并不是如何改正。至于uint32,估计许多玩嵌入式的人都会很熟悉,不会认为是奇技淫巧,而且一目了然,一看便知是一个32位无符号整型数。
siziof(uint32)=4而不是32.

使用特权

评论回复
34
mikesullen| | 2008-2-28 23:53 | 只看该作者

误导群众

不要总是来做题,有几个高手是做题做出来的?????
做题也就罢了,为什么总要和什么功力联系在一起????
实在看不惯。。。

难道是考试考多了????

使用特权

评论回复
35
wenming| | 2008-2-29 07:19 | 只看该作者

讨论这个问题没有什么意义

除非楼主想做学术研究.

使用特权

评论回复
36
HWM| | 2008-2-29 07:53 | 只看该作者

to LZ:我说的一石二鸟可是实实在在的。

继续蹲马步吧,有你练的呢。

使用特权

评论回复
37
sinanjj| | 2008-2-29 12:43 | 只看该作者

总结一下

char *buf;
函数verify用于校验buf中头4个字节的内容是不是'ABCD'4个字符
bool verify(char *buf)
{
uint32 a=0x44434241;
return ((*(uint32 *)buf)==a);
}
要求函数verify能在各种嵌入式环境中移植.
问题:
1,verify函数正确吗?
2,在什么环境下是正确的?
3,在什么环境下是不正确的?
答1: 由于没有考虑字节序,对齐等问题, 故verify函数是错误的.
答2: 在纯8位机小端模式下, 或者允许不对齐访问的x86系在CPU, verify函数能给出正确的结果.
答3: a,字节序的问题(大小端问题). 在几乎所有的机器上, 多字节对象被存储为连续的字节序列, 对象的地址为所使用字节序列中最低字节地址. 某些机器选择在存储器中按照从最低有效字节到最高有效字节的顺序存储对象, 这种最低有效字节在最前面的表示方式被称为小端法(little endian)(e.g.:Intel处理器上运行Linux,NT); 某些机器则按照从最高有效字节到最低有效字节的顺序储存, 这种最高有效字节在最前面的方式被称为大端法(big endian)(e.g.:Sun Microsystem UltraSPARC运行Solaris).
b,对齐问题. 传递的buf指向的多字节对象的长度是4的倍数.
c,字长问题. 对于纯16位或32位(不能以字节寻址)计算机, 如Ti的24和28系列cpu, 这类cpu的c编译器往往用一个16位或32位字存储一个字符, 把字符数组转换成32位数也不能得到正确的结果.

使用特权

评论回复
38
wang345| | 2008-2-29 14:22 | 只看该作者

细节问题

这是细节问题,应该不能完全代表一个工程师的水平吧?最多实践一下了。
哈哈。

使用特权

评论回复
39
djyos|  楼主 | 2008-3-1 22:20 | 只看该作者

有自信,就不怕出题

    这几个问题,出不出题倒是次要的,要知道,这几个问题都是从自己或别人的实际工作中提炼出来的,并不像35楼说的学术研究,研发工程师好好研究对做好产品其实是很有帮助的,把自己的经验拿出来分享,并且先思考以后再得到答案,或者从答对题中获得成就感,有何不可?
    能者为师敢为师,不敢为师假谦虚。我儿子上幼儿园没多久,天天挂在嘴边的是“嘿嘿你真棒,自信我会比你棒”,人长大了,也应该保持这份自信才好。
    然人各有长短,敢为师者,必敢于为学,再菜的问题,我也敢问,从不怕人笑我菜鸟;再不成熟的观点,也敢于提出来,从不怕别人议论。同样,我也从不笑别人菜鸟,从不骂别人垃圾,从不称别人为初学者,同样也不喜欢张口闭口说别人菜鸟的人,或者自以为了不起挂起来卖的人。
    是的,把这几道题跟“功夫”联系在一起,有些夸张,有骗眼球的嫌疑,mikesullen大侠说的对,接受批评,下次不了。

使用特权

评论回复
40
HWM| | 2008-3-3 08:45 | 只看该作者

既然LZ这么“自信”,就再次跟你讲讲吧。

你出的第一道题和所谓的“母函数和子函数”实在没啥关系。数组访问超界的破坏力远比篡改所谓的母函数内部变量更可怕(虽然破下界一般不会出现LZ所说的情况)。至于硬要以此杜撰出一个所谓的访问母函数内部变量的方法更是有混淆概念之嫌。另外关于母函数和子函数的关系在语法关系上并不存在(只是一种临时的调用动态关系),如果存在递归函数又如何区分“母子”关系呢?,语法上只存在有从属函数的关系(见PASCAL)或函数的继承关系(见C++)。

你出的第二个问题,那根本就不是一个层面的概念,把它们捏在一块更是混淆视听。若你真的要搞清楚它们的关系可以看一下Linux和RT-Linux的核心差异,但若你要真的想去了解“硬实时”推荐你一个真正的玩意儿--ThreadX。

至于你所出的第三个题目,不用看内容,就其形式就是不可取的。若不用注释能一眼看出“ABCD”吗?况且其中还存在有歧义(大小端的二义性)。另外强行指针类型转换又是一大忌。所以这不是垃圾是什么呢?

最后要说明的是用union确实可以解决你所出的第三题所涉及的大小端和对齐问题,这叫“以毒攻毒”。

使用特权

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

本版积分规则