指针
问题都集中在 指针 。
(1)比如说,指针的运算: 加减相对好理解,可是乘除呢?在实际编程中,印象中是无法通过编译,为此我使用了另一种同样不明风险的事情:强制转换成int来进行运算——选择int是 因为它代表机器字长,而指针当然是机器字长。然后运算完毕后,我再转回去。 虽然我说不清我具体在哪里犯了地址转换上的错误,但我最终制造的一个问题是,我的指针无意指向了一个几K以外的一个位上,结果造成了一个隐藏得很深的 判断失误。
(2)用函数返回指针 这种问题我似乎没有遇到过,但我最近在看一本C++的入门书时。里头提到一个例子,用函数返回值返回指针,说有问题,但我并不太明白细节。
(3)一种奇怪的宏定义,在地址上直接操作 在一个项目中,出于需要,我要把一系列变量直接定义在一个特定地址的RAM空间里。很遗憾,它不像51有_at_或者不同空间区域的修饰词,诸如IDATA XDATA DATA等。
最后我使用了一个参考STM32库文件中定义寄存器的办法做。
对 于单个变量,问题不大。 #define pcredit (char *)0x030 这是在0x030这个位置上定义一个 char 型变量,为了方便或者不总是使用 引用地址符号,我还做了一个宏——其实这主要是为了配合我原来已经写好的部分代码 #define credit (*pcredit) 但是到了后来,出现了数组,我写的就总是编译不过。
再后来,我改用了结构体的组织方式。
这里基本没遇到太大问题. 除了一个问题。 struct module { int a; int b; }M; 你觉着,M 是不是代表着 &M呢? 我意思是,类比数组,它会是首地址么?
各种变量的存储位置 和 编译顺序
静态变量 和 静态全局变量 它们分别存储在哪里?
—— 后来在实际项目中我才知道,原来,不仅这么分,还分 初始化了的和未初始化了的 全局/静态变量。 然后是静态函数,虽然我知道,它只是作用域不一样,不过,难道 静态变量 和 全局变量 差的不就是 作用域? 所以,这些到底是怎么回事——尽管这一系列问题最初来自于一个错误判断,但随着看 深入理解计算机 这本书,我对这个 问题非常感兴趣。
PC-lint
第一次听说这东西,是还在51阶段的时候,看 何宗彬 的书,看到的。当时虽然有想试试,但是这东西弄起来不那么容易,而且没特别感觉到很需要。但是,后来看好几本C语言的书,发现它经常被提起,而且这次第一 次做一个比较大的完整的项目,终于意识到我的确需要一个更严格的检查工具,而这对我以后想写出更高质量的代码,想必也是必不可少的一步。
中间文件
有时候我会查看一些编译过程产生的中间文件,比如.o文件一类的。但是,有时候我看到的是带乱码的,我不晓得这种乱码是没有办法回避的,还是有什么手段可以复原呢?
栈的工作细节
这个东西对我来说,至今为止,我基本没有半点概念,虽然我知道它是中间上下文的现场保护。
(1)是谁决定栈的分配——我是说,在哪里可以修改栈的大小。显然,不是所有的MCU都像51一样,只要设置SP就好了。 而在带操作系统的情况下,这个问题会更复杂——因为可能这是连修改汇编代码都解决不了的问题。
(2)每个函数占用了多大的空间。在弹栈压栈时的行为细节。