register
register 变量必须是一个单个的值,并且其长度应小 于或等于整型的长度。 而且 register 变量可能不存放在内存中,所以不能用取址运算符“&” 来获取 register 变量的地址。
float
变量与“零值”进行比较
//EPSINON 为定义好的 精度。
if((fTestVal >= -EPSINON) && (fTestVal <= EPSINON));
volatile
volatile 关键字告诉编译器 i 是随时可能发生变化的,每次使用它的时候必须从内存中取出 i 的值,因而编译器生成的汇编代码会重新从 i 的地址处读取数据放在 k 中。
这样看来,如果 i 是一个寄存器变量或者表示一个端口数据或者是多个线程的共享数 据,就容易出错,所以说 volatile 可以保证对特殊地址的稳定访问。
extern
extern 可以置于变量或者函数前,以 标示变量或者函数的定义在别的文件中,下面的代码用到的这些变量或函数是外来的,不 是本文件定义的,提示编译器遇到此变量和函数时在其他模块中寻找其定义
空结构体占用空间大小
struct student {
}stu;
sizeof(stu)
的值是多少呢?
Visual C++ 6.0上为 1
编译器认为你构造一个结构体数据类型是用来打包一些数据成员的,而最小的数据成员需要 1 个 byte,编译器为每个结构体类型数据至少预留 1 个 byte 的空间。所以,空结构体的大小就定位 1 个 byte。
struct 与 class 的区别
struct 的成 员默认情况下属性是 public 的,而 class 成员却是 private 的。
union 关键字
union 维护足够的空间来置放多个数据成员中的“一种”,而不是为每一个数据成员配置 空间,在 union 中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所 有的数据成员具有相同的起始地址。
union StateMachine {
char character;
int number;
char *str;
double exp;
};
一个 union 只配置一个足够大的空间以来容纳最大长度的数据成员,以上例而言,最大 长度是 double 型态,所以 StateMachine 的空间大小就是 double 数据类型的大小。
另外,注意大小端模式对 union 类型数据存储的空间有影响
typedef
关键字
typedef struct student {
//code
}Stu_st,*Stu_pst;
A),struct student stu1;和 Stu_st stu1;没有区别。
B),struct student *stu2;和 Stu_pst stu2;和 Stu_st *stu2;没有区别。 这个地方很多初学者迷惑,B)的两个定义为什么相等呢?其实很好
const
const int *p; //p指向的对象不可变(*p不可变)
int const *p; //p指向的对象不可变(*p不可变)
int *const p; //p不可变,p指向的对象可变
const int *const p; //前一个 const 修饰*p,后一个 const 修饰 p,指针 p 和 p 指向的对象 都不可变
void Fun(const int i); //不希望这个参数值被函数体内意外改变。
const int Fun (void); //返回值不可被改变。
运算符
SQR(8)
输出的是:
The square of 8 is 64.
预算符
运算符可以用于宏函数的替换部分。这个运算符把两个语言符号组 合成单个语言符号。
#define XNAME(n) x ## n
如果这样使用宏:
XNAME(8)
则会被展开成这样:
x8
指针和数组
A)
int* p1[10]; // 指针数组,数组的每个值都是指针
“[]”的优先级比“*”要高。p1 先与“[]”结合,构成一个数组的定义,数组名为 p1,int * 修饰的是数组的内容,即数组的每个元素。那现在我们清楚,这是一个数组,其包含 10 个 指向 int 类型数据的指针,即指针数组。
B)
int (*p2)[10]; //数组指针,可以理解为 int (*)[10] p2,实际上就是二维数组p[][10];
“()”的优先级比 “[]”高,“*”号和 p2 构成一个指针的定义,指针变量名为 p2,int 修饰的是数组的内容, 即数组的每个元素。数组在这里并没有名字,是个匿名数组。那现在我们清楚 p2 是一个指 针,它指向一个包含 10 个 int 类型数据的数组,即数组指针。
函数指针
A)
char * fun3(char * p1,char * p2); //fun3是函数名,p1,p2是参数,其类型为char*型,函数的返回值为char * 类型。
B)
char * *fun2(char * p1,char * p2); //与 C)表达式相比,唯一不同的就是函数的返回值类型为 char**
C)
char * (*fun1)(char * p1,char * p2); //fun1 不是什么函数名,而是一个 指针变量,它指向一个函数。这个函数有两个指针类型的参数,函数的返回值也是一个指 针。我们把这个表达式改写一下:char * (*)(char * p1,char * p2) fun1; 这样子是不 是好看一些呢?只可惜编译器不这么想。
函数指针数组
char * (*pf)(char * p) //函数指针
char * (*pf[3])(char * p); //这是定义一个函数指针数组。它是一个数组,数组名为 pf,数组内存储了 3 个指向函数的 指针。pf是数组名
函数指针数组的指针
char * (*(*pf)[3])(char * p); //pf是指针,这个指针指向一个包含了 3 个元素的数组;这个数字里 面存的是指向函数的指针;这些指针指向一些返回值类型为指向字符的指针、参数为一个 指向字符的指针的函数。
实战练习
- 参考答案:
a) int a;
b) int a;
c) int a;
d) int a[10];
e) int * a[10];
f) int (a)[10];
g) int (func)(int a);
h) int (func[10])(int a);
网友评论