一篇快速复习C语言语法的小文。
走马观花
- C语言和Java语言一样,变量使用前需要先声明,但是由于Java特有的初始化机制,使得声明的语句并非一定要显式摆放在执行的方法之前,但C语言在调用函数之前需要显式声明。
|
|
int和float等类型的取值范围取决于机器。
#define在预编译阶段将符号名或者符号常量定义为特定的字符串,指令的末尾没有分号。
C语言的函数参数通过值传递。
自动变量对标Java中局部变量,每次entry函数时都需要显式为其赋值,如果没有,那么存放的将是“garbage”。
- 外部变量指的是函数外的变量,可以在函数内显式声明,即用“extern”关键字,也可以通过上下文隐式声明,即比如定义在使用函数之前就可以不使用“extern”关键字。
- 通常习惯把extern声明的变量和函数放在单独的一个文件中,该文件成为头文件。
类型、操作符和表达式
- C中的const对标Java中的final,但是和Java又有区别,例如如果用const修饰数组,那么数组中的元素就不能改变了,而且在声明的同时就应该初始化赋值:
|
|
- 下划线在C中被看作是字母,但是通常不应以下划线开头来命名变量或函数,因为library routines常常使用这样的方式命名。
- C的字符串和Java的相比,最后多了一个
\0
字符,程序是需要扫描整个字符串才能确定字符串的长度,该长度不包括\0
字符。 - 取模运算符%不能作用于float活着double类型。
- C没有指定char类型的变量是无符号还是带符号变量,这个由不同的机器决定。
- 全局变量 、静态变量初始值为0,局部变量,自动变量如果没有初始化值随机分配(“garbage”)。
函数
- 和Java不同,C中函数的定义中各个部分都可以省略,比如dumy() {}的书写是合法的,这种函数可以作为钩子函数在开发期间进行保留。
- 外部变量或函数的作用域和Java中的各种变量的相比并不相同,它是从声明的地方开始,在其所以在的文件的末尾结束。
- 静态变量只供所在源文件的函数使用,其他函数不能访问。
- 静态变量也可以存在于函数内,这和局部变量一样,但它不仅是该函数私有的,而且无论函数调用是否结束,它仍然占据内存空间。所以静态变量和外部变量相比,能让编码者更细腻地控制作用范围。
- 寄存器变量只适用于自动变量以及函数的形参。
- 寄存器变量的地址不能访问,且过量使用没有什么害处。
- 外部变量和静态变量在没有显式初始化的时候都被初始化为0,而自动变量和寄存器变量不会,它们的值是“garbage”。
指针和数组
结构体
结构体可以视为一种数据结构,它集合了一个或者多个变量,这些变量可以是不同类型的。
结构体的形式一般如下:
|
|
structuretag是可选的,可以作为括号内声明部分的简写形式。
结构体声明
在通过struct <structuretag> {...} <var>
进行声明后,可以用struct <structuretag> <var>
进行简化声明,例如:
|
|
结构体与函数
给函数传入一个结构体参数很像Java中的引用传递,毕竟很多人可能将结构体类比为Java中的类或对象,但结构体依然是值传递,例如:
|
|
打印为:
|
|
结构体会在函数内整个复制,如果该结构体很大,那么采用这种方式效率较低,好的方法是使用指针。
使用指针时首先要注意的是*
的优先级低于.
,所以*p.x
和(*p).x
是不一样的。
其次,指针的使用频率很高,所以可以采用一种简写方式p->x
来代替前面(*p).x
的写法。
结构体数组
借助结构体,可以将多个长度相同的数组构成的集合,改写成数组相同索引下数据的集合(结构体)构成的数组。
初始化的格式:
|
|
如果要求结构体数组的长度,可以使用sizeof函数,它会返回无符号整型值,类型为size_t。
sizeof接结构体参数时,可以采用sizeof(struct
预处理器不对类型名进行分析,但预处理器并不计算#define里的表达式,所以可以用#define搭配sizeof函数使用。
指向结构体指针
这里要注意的是,指针的加法运算是非法的,而减法是合法的。
其次,C中的结构体内存在字节对齐现象,所以结构体的长度未必等于它成员长度只和。
再次,返回结构体指针的函数,可以用如下格式来书写:
|
|
typedef
typedef的功能一言以蔽之:“it merely adds a new name for some existing type”。
下面举一个最简单的typedef例子来说明:
|
|
此时Len和int具有等同意涵。这里最好遵照一定的规范,即typedef定义的类型名首字母大写。
编写了一个函数如下:
|
|
现在假设需要声明一个变量,它的类型是指向函数的指针,该函数是这样一种函数:参数是(int, int),返回值是int,该指针变量指向之前编写的method函数,所以有:
|
|
总是这样写相较麻烦,为这种类型创建一个新名称吧:
|
|
此时之前的methodref02可以这样定义:
|
|
联合体
联合体开辟的内存,等于它所有成员中所占内存最大的成员的内存。读取的类型必须是最近一次存入的类型,初始化的时候使用第一个成员类型的值进行初始化,其它操作大体和结构体相同。
|
|
打印结果:
|
|
位字段
位字段一个主要的作用就是节约内存,在Java中boolean类型的变量在虚拟机占用了一个int的大小,也就是四个字节。实际上,原本一个bit就能完成同样功能。Java这样做当然有它自己的实现机理,而在C语言中,为了节约内存采用了一种新的手段,即位字段。来看一个例子:
|
|
运行结果:
|
|
a占了一比特,b占了2比特,c占了20比特,如果单独声明,它们可能会占用更多的内存,但是现在仅仅一个unsigned int大小的内存就能搞定,也就是4字节。
小结
以上就是本人针对Java和C的语法区别做的一个记录,旨在复习C语法。