一、指针常量
如何给内存中某个特定地址的值赋值:
*(int *)100 = 25 //通过强制类型转换把值100从“整型”转换为“指向整型的指针”,该表达式表示把25赋值给地址为100的地方。
二、字符串长度
以下表达式是不相等的:
if( strlen(x) >= strlen(y) ) ....
if( strlen(x) - strlen(y) >= 0) ...
第1句可以按照你预想的那样工作,但2句结果将永远为真。因为strlen的结果是个无符号数,所以>=左边的表达式也是无符号数,而无符号数绝不可能是负的。
如果一定要使用第2条语句那种写法,可以把strlen的返回结果强制转换为int。
三、结构声明
struct {
int a;
char b;
float c;
}x; //创建了一个变量x,包含三个成员:一个整数,一个字符和一个浮点数
struct {
int a;
char b;
float c;
}y[20], *z; //y是一个结构体数组,包含了20个结构,z是一个指针,指向这个类型的结构
注意:两个声明被编译器当做两种不同的类型,因此z = &x是非法的。
要使这两个声明都是同一类型,需要使用标签(tag)字段:
struct SIMPLE{
int a;
char b;
float c;
};
struct SIMPLE x;
struct SIMPLE y[20], *z;
四、结构的自引用
在一个结构内部不能包含一个类型为该结构本身的成员:
struct SELF_REF1{
int a;
struct SELF_REF1 b;
int c;
};
因为编译器在结构体声明时无法确定结构体的大小,所以这样是错误的。
但可以包含一个该结构体类型的指针变量:
struct SELF_REF2{
int a;
struct SELF_REF2 *b;
int c;
};
指针的长度是确定的,因此编译器能确定结构体的大小,该声明时合法的。
typedef struct {
int a;
SELF_REF3 *b;
int c
}SELF_REF3 ;
类型名直到声明的末尾才定义,所以在结构体内部它尚未定义。
解决方案是定义一个结构标签来声明b:
typedef struct TAG{
int a;
struct TAG *b;
int c
}SELF_REF3 ;
五、不完整声明(和类的提前声明类似)
struct B;
struct A {
struct B *partner;
/* other declaration */
};
struct B {
struct A *partner;
/* other declaration */
};
六、访问结构成员
typedef struct {
int a;
short b[2]
}EX2;
typedef struct EX{
int a;
char b[3];
EX2 c;
struct EX *d;
}EX;
EX x = {10, "Hi", {5, {-1, 25}}, 0};
EX *px = &x;
几个问题:
1、比较*px和px->a,a的地址和结构的地址是一样的,但是类型不同,*px的结果是整个结构,而不是它的第一个成员。
2、->的优先级
int *pi; pi = &px->a; // ->的优先级高于&操作符的优先级,所以这个表达式表示把结构体成员a的地址赋值给指针pi;
px->b[1]; //访问数组b的元素
px->c.a; //访问结构体c的成员a
*px->c.b; //访问结构体c的数组成员b的第1个元素
七、联合的初始化
联合变量可以被初始化,但这个初始值必须是联合的第1个成员的类型,而且必须位于一对花括号里面
union {
int a;
float b;
char c[4];
}x = {5};
x.a初始化为5