pascal语言语法 C|语法的合理性理解和分析试想
作者:admin 发布时间:2023-04-04 07:31:46 分类:随笔 浏览:65
C|语法的合理性理解和分析
试想如果你作为C语言或C语言编译器的的设计者,肯定不会任意设置语法规则,除了考虑不能有歧义以外,还会考虑其合理性。
1 效率是第一位的,安全处于次要位置
了解C语言“效率第一、安全次之”的原则(因为天才的程序员可以回避掉所有所谓的安全问题),对一些语法设置和编译器行为的合理性理解就豁然开朗了。
1.1 数组边界不做检查;
1.2 整数溢出不做检查;
1.3 对于局部变量不做初始化(Deubg版会初始化一个特定值,如0xcc);
1.4 输入输出不是语言自身功能的一部分,而是放到了标准库中。
C以前的很多语言,把输入输出作为语言自身功能的一部分。比如在Pascal 中与C的printf()的功能相当的, 是使用write()这样的标准规范。 它在 Pascal的语法规则中受到了特别对待。
相对这种方式,C语言将printf()这样的输入输出功能从语言的主体部分分离出来, 让它单纯地成为库函数。 对于编译器来说,printf()函数和其他由普通程序员写的函数并没有什么不同。
从程序员的角度来看,printf ()操作一下子就完成了。 其实为了完成这个操作, 需要在幕后做诸如向操作系统进行各种各样的请求等非常复杂的处理。C语言并没有把这种复杂的处理放在语言主体部分,而将它们全部规划在 函数库中。
很多编译型的语言会将被称为 “run-time routine” (运行时例程)的机器码悄悄地” 嵌入到编译(链接)后的程序中, 输入输出这样的功能就是包含在 run-time routine 之中的。C语言基本上没有必须要 “悄悄地” 嵌入运行时的复杂功能*。由于稍微复杂一点的功能被全部规划到了库中, 程序员只需要 去显式地调用函数。
2 对字符串的操作
C是只使用标量(scalar)的语言。
标量就是指char、int、double和枚举型等数值类型,以及指针。相对地,像数组、结构体和共用体这样的将多个标量进行组合的类型,我们称之为聚合类型(aggregate)。
早期的C语言一度只能使用标量。
例如:
char str[]=“abc”;if (str==“abc”)
这样的代码为什么不能执行预期的动作呢?确实已经将”abc”放到了str中, 条件表达式的值却不为真。这是为什么?
对于这样的疑问,通常给出的答案是“这个表达式不是在比较字符串的内容, 它只是在比较指针”,其实还可以给出另外一个答案:
字符串其实就是char类型的数组,也就是说它不是标量,当然在C里面不能用==进行比较了。(包括字符串的合并也不是使用“ ”,而是使用string.h中的库函数,如strcpy();)
C就是这样的语言,一门”不用说对于输入输出,就连数组和结构体也放弃了通过语言自身进行整合利用” 的语言。
但是,如今的C (ANSIC)通过以下几个追加的功能,已经能够让我们整合地使用聚合类型了。
结构体的一次赋值;
将结构体作为函数返回值传递;
将结构体作为函数返回值返回;
auto变量的初始化;
当然,这些都是非常方便的功能,如今已经可以积极地使用了(不如说应该去使用)。可是在早期的C语言里,它们是不存在的。为了理解C语言的基本原则, 了解早期的C语言也不是什么坏事。
特别要提出来的是, 即使是ANSIC, 也还不能做到对数组的整合利用。
将数组赋值给另外一个数组,或者将数组作为参数传递给其他函数等手段,在C语言中是不存在的。
3 数组下标
P[i]是*(p i)的简单写法,实际上,至少对于编译器来说,[]这样的运算符完全可以不存在。可是,对于人类来说,*(p i)这种写法在解读上比较困难,写起来也麻烦(键入量大)。因此,C语言引入了[]运算符。就像这样,这些仅仅是为了让人类容易理解而引入的功能,的确可以让我们感受到编程语言的甜蜜味道(容易着手),有时我们称这些功能为语法糖(syntax sugar或者syntactic sugar)。
4 全局变量与extern
C编译器使用分开编译的机器,一个大型的应用可以多个程序员合作,大型应用在层层分解出众多的接口后,各自可以去实现一些接口,分开编译,在链接时再链接到一起,所以分散在某一文件中的全局变量、函数可以被其它文件引用。但需要注意的是,链接发生在编译之后,所以需要在使用其它文件中定义的全局变量时,要先用extern声明,以告诉编译器,该符号会在链接时寻找其定义。
为了在链接器中将名称结合起来, 各目标代码大多都具备一个符号表(symbol table) (详细内容需要依赖实现细节)。
5 函数调用返回后,栈内存清理了,返回值怎样保存?
确实,函数调用返回后,栈内存会清理。对于寄存器大小的数据,会保存在寄存器。超过寄存器容量的返回数据,编译器会事先在栈内存中分配一块区域,用来保存返回值。
6 可变长参数与参数压栈顺序
大部分的C语言入门书籍往往在一开始就频繁地使用printf ()这个输出文字信息的函数, 利用这个函数, 可以将可变个数的参数填充到字符串中的指定位置。
C语言的参数是从右往左被堆积在栈中的。
另外, 在C语言中, 应该是由调用方将参数从栈中除去。顺便提一下,Pascal和Java是从左往右将参数堆积在栈中的。这种方式能够从前面开始对参数进行处理,所以对于程序员来说比较直观。此外, 将参数从栈中除去是被调用方应该承担的工作。大部分情况下, 这种方式的效率还是比较高的。
为什么C故意采取和Pascal、Java相反的处理方式呢?其实就是为了实现可变长参数这个功能。
比如, 对于像printf(“%d, %sn”, 100, str);
这样的调用, 栈的状态:
再看一个复杂的声明:
void (*signal(int sig, void (*func)(int)))(int);
signal is function(sig is int, func is pointer to function(int) returning void) returning pointer to function(int) returning void
此时, 运用typedef 可以让声明变得格外得简洁。
typedef void(*sig_t)(int);sig_t signal(int sig, sig_t func);
sig_t代表”指向信号处理函数的指针” 这个类型。
19 多维数组的类型
我们知道,表达式的操作数,赋值运算符两边的左值、右值需要类型一致,除非编译器能够做隐式类型转换,否则会报错。
如多维数组int arr[3][4][5]是什么类型呢?如果用arr做右值,左值的类型是什么呢?
在C中,除标识符以外,有时候还必须定义”类型”。
具体来说,遇到以下情况需定义”类型”
I 在强制转型运算符中
II 类型作为sizeof 运算符的操作数
比如,将强制转型运算符写成下面这样:
(int*)
这里指定”int*” 为类型名。
从标识符的声明中,将标识符取出后,剩下的部分自然就是类型名。
int hoge; 类型是:int
int *hoge; 类型是:int *
double(*p)[3]; 类型是:double(*)[3]
void(*func)(); 类型是:void(*)()
同样的问题,对于typedef类型定义,新的类型标识就是标识符,抽出标识符剩下的就是类型定义:
int func(int){return 0;};typedef int (*funcpT)(int);typedef struct{ int a; double b;}struT;int main(){ funcpT funcp=func; struT str; return 0;}
回到上面的问题:
如多维数组int arr[3][4][5]是什么类型呢?如果用arr做右值,左值的类型是什么呢?
对于数组名,其逻辑含义是数组元素的首地址,逻辑上相当于&arr[0]。
arr[]指向一个二维数组arr[4][5], 所以其类型是一个特定指针,一个指向一个二维数组arr[4][5]的指针,其类型是int (*)[4][5]。
int (*arrp)[4][5]=arr;
用作函数参数时:
int func(int (*arrp)[4][5], int n);
或者语法糖的写法:
int func(int arr[][4][5], int n);
-End-
相关推荐
- 大宝眼袋霜价格 说到家喻户晓的平价护肤品,很多
- 成语网名大全 1、枯萎的信2、往事如烟3、悲
- 微肥 微肥是什么?该如何使用?作物生
- 林建鹏 说到王思聪,大家都会想到他是王
- 曾轶可父亲 曾轶可说出来很多人不清楚,可她
- 安吉中南百草园 位于湖州的安吉中南百草园是一处
- 梅姨案 1、梅姨案指全国通缉的人贩子子
- 平凡之路歌词是什么意思 1、寓意:《平凡之路》延续了朴
- 孟尝君有舍人 1、《孟尝君舍人》出于战国时代
- 大连红旗高中 1,大连红旗高中好吗这个学校还
- 农民工保险 现在大家都开始买保险了,
- 恐龙宝贝之失落的文明动漫 1、《恐龙宝贝之失落的文明》是
- 未来可期 1、未来可期的意思是未来可以期
- 拾忆歌词 1、歌词翻开日记整理破碎的心情
- 小日向白朗 1、普安协会,1935年在天津
- 标杆管理起源于 1、标杆管理起源于美国施乐公司
- 桑兰的资料 1、黄健,男,出生于中国福建,
- 天上白玉京下句 1、《天空中的白玉景》的下一句
- 浙江卫视左岩 1、左岩,女,满族,1985年
- 固定收益 固定收益类理财是指一部分的理财
- 浙江外国语学院专科 1、浙江外国语学院(Zheji
- 拉登的儿子 1、奥马尔·本·拉登(Omar
- 河南工程学院专科 1,河南工程学院都有什么大专专
- 王传越简历 1、《请放心》是王传越演唱的一
- 民国四大家族 1、一般是指蒋宋孔陈四大家族,
- 王紫藤 王紫藤的拼音怎么读王紫藤的拼音
- 溏心风暴剧情分集介绍 第1集正哥心头二件事正哥买下心
- 欧莱雅眼线膏 1、巴黎欧莱雅(L’Oréal
- 圣诞贺卡 011、人依旧,物依旧,又是一
- 玻尿酸充填 说到玻尿酸填充,相信许多爱美人
- 最新推荐
-
- 野心勃勃的意思 【野心勃勃】的意思,拼音,读音
- 梦幻诛仙青云门加点 梦幻诛仙青云门加点,相信很多小
- 卡天赋bug 卡天赋bug之前,最烦人的就是
- 颊 【颊】字的意思解释,拼音,组词
- 百无禁忌什么意思 【百无禁忌】的意思,拼音,读音
- 对方 【对方】的意思,拼音,读音
- profiled单词的意思,例句
- 自树一帜的意思,拼音
- 拾人牙慧什么意思 【拾人牙慧】的意思,拼音,读音
- 倦的组词 疲倦
- 酒席 【酒席】的意思,拼音,读音等)
- 步步生莲游戏 阴阳师谋士任务中怎么种莲花?玩
- 叠组词 重叠
- 雀圣1演员表 演员表角色演员备注十三飞元秋雀
- 火炬之光2修改器怎么用 火炬之光2修改器怎么用?《火炬
- 地牢围攻1攻略 地牢围攻1攻略及地牢围攻1攻略
- derivative单词的意思,例句
- 硬派 【硬派】的意思,拼音,读音等)
- 年年 【年年】的意思,拼音,读音
- supplying单词的意思,例句
- 繁弦急管的意思 【繁弦急管】的意思,拼音,读音
- 引诱 【引诱】的意思,拼音,读音
- 遗嘱的拼音 【遗嘱】的意思,拼音,读音等)
- 求道 【求道】的意思,拼音,读音等)
- 夏组词 “夏”组词,拼音,解释夏橘夏成
- brutally单词的意思,例句
- 生化危机5秘籍 生化危机5攻略秘籍及生化危机5
- 国手是什么意思 【国手】的意思,拼音,读音
- bitty单词的意思,例句
- 瓜田李下的意思,拼音
- 天下3职业介绍 天下3职业加点和天下3职业技能
- looting单词的意思,例句
- 缀的组词和拼音 【缀】字的意思解释,拼音,组词
- 慎的组词 “慎”组词,拼音,解释慎狱慎防
- 中国乒乓球运动员 中国乒乓球十大巨星中国乒乓球十
- 诡组词 【诡】字的意思解释,拼音,组词
- 极限的祭坛攻略 极限的祭坛攻略及地下城极限的祭
- 冷暖自知的意思 【冷暖自知】的意思,拼音,读音
- 跳水拼音 【跳水】的意思,拼音,读音等)
- 朱墨 【朱墨】的意思,拼音,读音等)
- 刀剑2公测 刀剑2什么时候公测?可能有部分
- 通天塔电影解析 2007年奥斯卡结束当夜,罗杰
- 楷怎么读 【楷】字的意思解释,拼音,组词
- 受罚 【受罚】的意思,拼音,读音
- 鬼镜1 (本文由火锅剧场原创:hott
- 瞎子摸象的意思,拼音
- 弦组词 “弦”组词,拼音,解释弦脉弦韦
- tighten单词的意思,例句
- 莫须有 【莫须有】的意思,拼音,读音等
- 无能 【无能】的意思,拼音,读音等)
- 凉帽 【凉帽】的意思,拼音,读音
- 隐姓埋名 【隐姓埋名】的意思,拼音,读音
- 清理平台 清理平台任务完成攻略清理平台任
- 四不像是什么 【四不像】的意思,拼音,读音等
- 驱魔师pk加点 驱魔师pk加点和法驱魔师加点,
- 猎刃好玩吗 猎刃好玩吗?猎刃怎么样?猎刃游
- 国统纲领 国统纲领全名为国家统一纲领,经
- 验的组词 “验”组词,拼音,解释验明正身
- 独组词 独立
- 外宽内深 【外宽内深】的意思,拼音,读音