c语言学习心得:符号,存储,可见性或者作用域
符号,存储,可见性或者作用域

a)符号:
常见的符号在汇编里面是变量地址、可调用地址或者可跳转地址。对应C可以是变量,函数以及标号。之所以说“可以是”,因为gcc也出现了goto *func这种语法,其中func是函数名,并且在一些底层的实践中似乎没什么用,所以我不得不把它包含进来。
其实这点不能算最底层的。机器语言代码这三者和其他的是没有区分的,这些意义和段属性也是根据需要附加上去的,严肃汇编语言也好C也好,都是最接近这种底层的某种方式。
b)存储:
我曾经试着写了一个极其简陋的编译器,连文法都害怕自己去分析,好在简陋有简陋的过法,不引起歧义的情况下,只好求助于现实高级语言的正则表达式,(当然如果那时候我会一点Lex+Yacc/Flex+Bison可能会稍微看起来好点)。 然而有一样东西没有工具可以给你借鉴,(除非你就是改别人的编译器源码),那就是存储。除非你打算一直用寄存器,要不然总得和栈、堆、或者类似的东西打交道。想想看:你有了文法分析器,你有了gcc工具链,(C形式的预处理和汇编链接过程是很容易完成的),你还得定义存储。
好在汇编和C都是任意位置访问的,这两者都可以轻而易举定义存储。C常见的做法是全局存储的地址编译时分配(这个分配是assign,相比于allocate而言);局部存储的地址编译时assign,运行时在栈上面allocate;至于动态的分配这个常见由操作系统支持,程序员自己完成。这点汇编语言上还是没有任何优势,乃至于MASM不得不使用local伪指令来帮助它的入门用户来完成局部变量。当然严肃的汇编语言家可以在汇编上规定一个“闭包存储”等等,如果那样我可以试试在C里面用数据结构来完成同样的事情。
c)局部存储:
局部存储这一现象不是C独有的,而且在某些机器和配置上,由于程序的局部性以及缓存等,最靠近的栈帧可能会直接得到优化, 相对于变量全局化单独放在段里面可能还更有优势。作为曾经的严肃汇编语言用户(开选项-pedantic的),我甚至觉得.local伪指令这种不够酷,例如C代码
|
void func(){ if(…){ } if (…){ for(…){int x;} } } |
中的局部变量x
我认为应该叫做 func_2_1_x
并宏定义为 $-xx(%ebp)(xx自己计算一下就好了)。
而且需要手动去sub $yy, %esp(同样yy自己计算一下就好了)
d)字面量和POD
机器语言是没有non-trivial的字面量的,一切都可以当作字面量,或者一切都不是。严肃的汇编语言却需要借助语言以外的方法来表示一个字面量(我听见有人在窃笑说 DB ‘Hello world’, 0D, 0A, 不过DB也是伪指令可别忘了),GNU as更有一个.asciz伪指令,表示一个字符串字面量以0结尾,例如.asciz “Hello”其实是’H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘\0’,这还是很体现基于C系统的字符串特点,要不然为什么不用’$’表示字符串结尾呢?相比之下C的字面量还算丰富,1, 1.0f, 1.0, 1.0e+123, “Hello”, ‘H’, 还有初始化数组的int a[]={1,2,3}的{1,2,3},或者结构体的struct node a={1,2,(struct node *)0} 等等。至于有些语言,复杂的对象乃至于函数都可以表示成字面量,我虽然羡慕,不过好像与本篇无关就略去。
POD全名Plain-Old-Data,又名概念的天外来客。简而言之就是一个类似于结构体或者联合体的东西,按字节被复制到另一个内存区域的时候,可以按照原来被复制的那个东西一样使用。因为我们只是讨论C与严格汇编与宏汇编的话,是看不见这个东西的,C++为了兼容C语言时和C的结构体有所区别才引入了POD的概念。代表例子是struct和union以及他们的各种形式的杂交,严格汇编是不需要这些概念的,访问那个内存地址,操作他,不需要那些表示struct或者union的伪指令。
本文来源 我爱IT技术网 http://www.52ij.com/jishu/1058.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
