第一章 关键字
什么是定义?什么是声明?
什么是定义:所谓的定义就是(编译器)创建一个对象,为这个对象分配一块内存并给它取上一个名字,这个名字就是我们经常所说的变量名或对象名。但注意,这个名字一旦和这块内存匹配起来,它们就同生共死,终生不离不弃。并且这块内存的位置也不能被改变。一个变量或对象在一定的区域内(比如函数内,全局等)只能被定义一次,如果定义多次,编译器会提示你重复定义同一个变量或对象。
什么是声明:有两重含义,如下:
第一重含义:告诉编译器,这个名字已经匹配到一块内存上了,下面的代码用到变量或对象是在别的地方定义的。声明可以出现多次。
第二重含义:告诉编译器,我这个名字我先预定了,别的地方再也不能用它来作为变量名或对象名。
定义声明最重要的区别:定义创建了对象并为这个对象分配了内存,声明没有分配内存
C语言标准定义的 32个关键字
关键字 意 义
auto 声明自动变量,缺省时编译器一般默认为 auto
int 声明整型变量
double 声明双精度变量
long 声明长整型变量
char 声明字符型变量
float 声明浮点型变量
short 声明短整型变量
这六个关键字代表 C 语言里的六种基本数据类型
在 32位的系统上 short内存大小是2 个byte;int内存大小是4个byte;long内存大小是4个byte;float内存大小是4个byte;double内存大小是 8 个byte;char内存大小是 1 个 byte。(注意这里指一般情况,可能不同的平台还会有所不同,具体平台可以用 sizeof关键字测试一下)
signed 声明有符号类型变量
unsigned 声明无符号类型变量
正负数:最高位如果是 1,表明这个数是负数。如果最高位是 0,表明这个数是正数
struct 声明结构体变量
不要认为结构体内不能放函数\
union 声明联合数据类型
union只配置一个足够大的空间以来容纳最大长度的数据成员
enum 声明枚举类型
成员都是常量,也就是我们平时所说的枚举常量(常量一般用大写)。enum变量类型还可以给其中的常量符号赋值,如果不赋值则会从被赋初值的那个常量开始依次加 1,如果都没有赋值,它们的值从 0开始依次递增 1
static 声明静态变量
第一个作用:修饰变量。
1、静态全局变量,作用域仅限于变量被定义的文件中,其他文件即使用 extern声明也没法使用他
2、静态局部变量,在函数体里面定义的,就只能在这个函数里用。由于是存在内存的静态区,所以即使这个函数运行结束,这个静态变量的值还是不会被销毁,函数下次使用时仍然能用到这个值。
第一个作用:修饰函数
函数前加 static使得函数成为静态函数。但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件(所以又称内部函数)。使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。
switch 用于开关语句
case 开关语句分支
default 开关语句中的“其他”分支
break 跳出当前循环
如果分支很多……请用switch、case
case 后面只能是整型或字符型的常量或常量表达式【C语言中,字符常量的字面值是整型,表达式运算时,字符型也会自动提升为整型。这也就是说,在switch或case中写的表达式,其值是整型:】
register 声明寄存器变量
这个关键字请求编译器尽可能的将变量存在 CPU 内部寄存器中而不是通过内存寻址访问以提高效率。注意是尽可能,不是绝对
register变量必须是能被 CPU寄存器所接受的类型。意味着 register变量必须是一个单个的值,并且其长度应小于或等于整型的长度
const 声明只读变量
volatile 说明变量在程序执行中可被隐含地改变
用它修饰的变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
typedef 用以给数据类型取别名(当然还有其他作用)
extern 声明变量是在其他文件正声明(也可以看做是引用变量)
return 子程序返回语句(可以带参数,也可不带参数)
void 声明函数无返回值或无参数,声明空类型指针
void* 任何类型的指针都可以直接赋值给它,无需进行强制类型转换
continue 结束当前循环,开始下一轮循环
do 循环语句的循环体
while 循环语句的循环条件
for 一种循环语句(可意会不可言传)
if 条件语句
else 条件语句否定分支(与 if 连用)
C 语言有这样的规定:else始终与同一括号内最近的未匹配的 if语句结合
goto 无条件跳转语句
goto 语句可以灵活跳转,如果不加限制,它的确会破坏结构化设计风格;其次,goto 语句经常带来错误或隐患。它可能跳过了变量的初始化、重要的计算等语句
sizeof 计算对象所占内存空间大小
sizeof是关键字不是函数。sizeof在计算变量所占空间大小时,括号可以省略,而计算类型(模子)大小时不能省略
第二章 符号
国际 C 语言乱码大赛(IOCCC)这是IOCCC 1988年获奖作品,作者是 IanPhillipps。
#include
main(t,_,a)char*a;{return!0<t?t<3?main(-79,-13,a+main(-87,1-_,
main(-86,0,a+1)+a)):1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
main(2,_+1,"%s%d%d\n"):9:16:t<0?t<-72?main(_,t,
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#\
;#q#n+,/+k#;*+,/'r :'d*'3,}{w+Kw'K:'+}e#';dq#'l\
q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;#\
){nl]!/n{n#';r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wknw'\
iwk{KK{nl]!/w{%'l##w#'i;:{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w!nr'/ ') }+}{rl#'{n'')# \
}'+}##(!!/")
:t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
:0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,
"!ek;dci@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m.vpbks,fxntdCeghiry"),a+1);}
接续符和转义符
C语言里以反斜杠(\)表示断行。编译器会将反斜杠剔除掉,跟在反斜杠后面的字符自动接续到前一行。但是注意:反斜杠之后不能有空格,反斜杠的下一行之前也不能有空格。
花括号
char a[10]= {“abcde”};[正确] char a[10]{ =“abcde”}; [错误]
用花括号是为了把一些语句或代码打个包包起来,使之形成一个整体,并与外界绝缘,
++、--操作符
inti =3;
(++i)+(++i)+(++i);
表达式的值为多少?15吗?16吗?18吗?其实对于这种情况,C语言标准并没有作出规定。有点编译器计算出来为 18,因为 i经过 3次自加后变为 6,然后3 个6 相加得18;而有的编译器计算出来为 16(比如 VisualC++6.0),先计算前两个i 的和,这时候i 自加两次,2 个 i的和为 10,然后再加上第三次自加的i 得 16。其实这些没有必要辩论,用到哪个编译器写句代码测试就行了。但不会计算出 15的结果来的。
贪心法
C 语言有这样一个规则:每一个符号应该包含尽可能多的字符。也就是说,编译器将程序分解成符号的方法是,从左到右一个一个字符地读入,如果该字符可能组成一个符号,那么再读入下一个字符,判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分;如果可能,继续读入下一个字符,重复上述判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号。这个处理的策略被称为“贪心法”。需要注意到是,除了字符串与字符常量,符号的中间不能嵌有空白(空格、制表符、换行符等)
按照这个规则可能很轻松的判断 a+++b表达式与 a+++b一致
|
|