char (*j)[20];//j是一个指向数组的指针,数组内有20个char元素
j = (char(*)[20])malloc(20);
如果把星号两边的括号删除,代码会变成非法的。
- 函数的返回值不能是一个函数,像foo()()是非法的;
- 函数的返回值不能是一个数组,像foo()[]是非法的;
- 数组里面不能有函数,像foo[]()是非法的;
但像下面这样则是合法的:
- 函数的返回值允许是一个函数指针,如:int(*fun())();
- 函数的返回值允许是一个指向数组的指针,如:int(*f00())[];
- 数组里面允许有函数指针,如:int(*foo[])();
- 数组里面允许有其他数组,如:int foo[][];
结构体申明
struct {内容...}
我们可以在结构的定义后面跟一些变量名,表示这些变量的类型是这个结构,如
struct {内容...} plum,pomegranate,pear;
另外我们还可以在struct后面加一个可选的“结构标签”,如
struct fruit_tag {内容...} plum,pomegranate,pear;
so,可以在以后的申明中用struct fruit_tag作为struct {内容...}的简写形式。
结构的通常形式:
struct 结构标签(可选){
类型1 标识符1;
类型2 标识符2;
.。。。
}变量定义(可选);
我不喜欢把结构的申明和变量的定义混合在一起,考虑代码容易阅读些,变量的声明应该与变量的声明分开
struct veg{int weight,price_per_lb;};
struct veg onion,radish,turnip;
最后,还有两个跟结构有关的参数传递问题,
参数在传递的时候首先尽可能地存放到寄存器中(追求速度)。
注意,int 型变量i跟只包含一个int型成员的结构变量s在参数传递时的方式可能完全不同。
一个Int型参数一般会被传递到寄存器中,而结构参数则很可能被传递到堆栈中。
在结构中放置数组,如:
struct s_tag{int a[100];};
struct s_tag orange,lime,lemon;
struct s_tag twofold(struct s_tag s){
int j;
for(j=0;j<100;j++) s.a[j]*=2;
return s;
}
main(){
int i;
for(i=0;i<100;i++)lime.a[i]=1;
lemon=twofold(lime);
orange = lemon;
}
如果需要对整个数组进行赋值操作,可以通过把他放入结构中实现。
struct node_tag(int datum;
struct node_tag *next;
};
struct node_tag a,b;
a.next=&b;//a,b链接在一起
a.next->next=NULL;
联合的申明
联合的成员都从偏移地址零开始存储,每个成员的位置都重叠在一起,在某一时刻,只有一个成员真正存储于该地址。
union 可选的标签{
类型1 标识符1;
类型2 标识符2;
类型3 标识符3;
}可选的变量定义;
枚举的声明
enum 可选标签{内容...}可选变量定义;
enum sizes { small =7,medium ,large=10,humungous};
枚举把一串名字与整型值联系在一起,缺省情况下,整型值从零开始,若某个被赋值,则其后标识符的值+1
#define定义的名字一般在编译时被丢弃,而枚举名字则一直在调试器中可见可用。
区分#define 和typedef
#define
typedef是给变量类型起一个别名,用typedef定义的类型能够保证声明中的所有的变量均为同一种类型,#define则无法保证
如:
#define int_ptr int*
int_ptr chalk,cheese;
经宏展开
int * chalk,cheese;
chalk是int指针,cheese是int。
再看
typedef char * char_ptr;
char_ptr Bentley,Rolls_Royce;
Bentley,Rolls_Royce的类型依然相同。
C中存在多种名字空间:
typedef struct fruit{ int weight,price_per_lb;}fruit;//语句1
struct veg{ int weight,price_per_lb;}veg;//语句2
struct fruit mandarin;//使用结构标签
fruit mandarin;//使用结构类型
区分定义和声明
定义 只能出现在一个地方 int my_array[10];为对象分配内存;
声明 可能出现多次 extern int my_array[]; 描述其他地方的创建的对象,并未再声明中为数组分配内存,所以不需要提供关于数组长度的信息。