1.数组与函数
1) 数组元素作参数
large(int x, int y){...};
large(a[2], a[3]);
1) 数组名作参数
计算数组中用户6个月的积分平均值
float aver(float b[6]) {....}
float a[6]...;
av = aver( a );
a. 数组名作函数参数,两个数组分别定义。
b. 实参数组和形参数组类型保持一致。
c. 形参数组大小不起任何作用,因为C语言不对形参数组大小作检查,只是将实参数组的地址传递给了形参数组名,即在空间上为形参数组分配了一个指针大小空间。形参数组和实参数组共用存储单元,a[2]和b[2]指的同一个元素。
数组形式:double fun(double b[5]);
地址形式:double fun(double *b );
d. 形参数组可以不指定大小,定义时保留空方括号即可。
float aver(float b[]);
e. 实参数组大小可以用另一个形参进行传递。
float aver(float b[], int n);
2) 多维数组名作参数
a. 函数调用时只需要传递数组名。
b. 形参数组的一维可以省略,括号不可以省略。二维不可省略,因为二维数组在内存中是按照行存放的,必须指定列数。
int array[3][10]
int array[ ][10]
c. C语言不检查第一维大小,在第二维数组相同的情况下,形参一维可以与实参大小不同。
实参: int marks[5][10];
形参: int array[2][10];
练习:对二维数组a[4][3]分析,求出最大值。
2.指针函数
整型函数是返回一个整型值的函数;
指针函数是返回一个地址(指针)值的函数。
1) 定义形式:
<数据类型> *<函数名称> (<参数说明>) {...}
char *mystring (void) {}
int * fun(int x, int y);
函数名先和优先级高的()结合组成函数。
3.函数指针
函数地址是函数的入口地址。函数指针变量是用来存放函数地址的指针变量。
函数名代表函数的地址。
PS:
函数可以通过函数名(表示函数地址)调用;也可以通过函数指针调用。
当一个整型指针指向一个整型变量,则可以通过指针去访问整型变量;
当一个函数指针指向一个函数,则可以通过这个指针调用函数。
1) 函数指针形式:
<数据类型> (*<函数指针名>) (<参数列表>);
数据类型是其指向函数的返回值类型。
int (*p)(int x, int y);
p先和* 结合,组成指针变量,然后和()结合组成指向函数的指针变量,p指向函数入口处,不能指向函数中的某一条指令,不能用*(p+1)表示函数下一条指令。
3) 函数指针的赋值:
p = max; //直接给出函数名,不用给出参数。(因为是把函数地址赋值给p,与参数无关)。
4) 函数指针调用函数:
调用时,用(*p)代替函数即可,且要在(*p)加上实参。
c = max(a, b);
c = (*p)(a, b);
Ps:
函数指针指向函数入口地址,p+n, p++,p--等没有意义。
5) 函数指针作为函数参数
void sub(int (*x1)(int), int (*x2)(int , int ))
{
int a, b, i, j;
a = (*x1)(i);
b = (*x2)(j);
}
4.函数指针数组
函数指针数组是包含多个函数地址的数组;
1) 定义形式:
<数据类型> (*<函数指针数组名> [<大小>]) (<参数列表>);
int (*pFunc[2]) (int a, int b);
6) 赋值:
pFunc[1] = fun1;
pFunc[2] = fun2;
7) 调用:
a = (*pFunc[i])(6, 7)
一、结构体
结构体是数据类型
数据类型可以分为系统定义的类型(int/char/float...)和用户定义类型。
当多个信息由不同的类型组合在一起的来描述一个事物的时候,开发者会根据自己的要求构造一个数据类型----结构体(structure)/结构。
结构体是用户自己定义的一种数据类型。
5.定义结构体
struct 结构体名 //用户自己决定类型名
{
.......//成员列表
} ; //用分号 ;作为结束符,且不能省略。
Ø 结构体类型是用户自定义的一种数据类型。
Ø 由不同基本数据类型的数据构成。
Ø 定义类型不分配空间,声明变量才分配空间。
6.结构体类型变量定义
定义一个变量,先要有数据类型,然后再定义变量
定义结构体类型的变量有三种方式:
① 先定义结构体类型,再定义
struct 结构体名/数据类型名 struct Mytype
{ {
成员列表; int id; char name[N]; char sex;
} ; } ;
struct 结构体名 变量名; struct Mytype man1, man2;
man1和man2是变量,它们的类型是 struct Mytype 类型。
//Mac头部,总长度14字节 TCP/IP协议头部结构体
typedef struct _eth_hdr
{
unsigned char dstmac[6]; //目标mac地址
unsigned char srcmac[6]; //源mac地址
unsigned short eth_type; //以太网类型
}eth_hdr;
技巧1: #define MYTYPE stuct Mytype. MYTYPE man1, man2; 技巧2: typedef struct student { char name[10] ; int age ; int s1, s2 ; } SD; SD st1, st2;//书写简单, 移植性增强
|
② 定义类型同时定义变量
struct 结构体名
{
成员列表;
} 变量名;
③ 直接定义结构体变量
struct
{
成员列表;
}变量名;
7.引用、初始化、赋值
1) 引用
结构体变量名.成员名 //“ . ”是分量运算符(成员运算符),优先级最高。
Ø 直接引用单个成员student1.id = 121; //不能整体引用。
Ø 成员又是一个结构体类型
student2.birthday.month
Ø 成员可以同普通变量一样进行运算。
student2.age++;//age先和studen2结合。
Ø 可以引用 结构体变量成员 地址,也可以引用 结构体变量 地址。但不能整体引用结构体变量。
scanf(“%d”, &student2.id);
printf(“%p”, &student2);
scanf(“%d,%s,%f,%s...”, &student1);
8) 初始化
定义同时初始化
9) 赋值
相同结构体类型的结构体变量可以相互赋值,不同类型不可以。(数组完全不可以相互赋值)。
8.结构体的大小
9.结构体数组
具有相同结构体类型的结构体变量组成的数组。
定义:和结构体变量定义方法相仿,要说明是数组。
(旧标准中只能对全局和静态存储类别结构体初始化)。
成员引用:stu[1].name
相同类型的结构体可以相互赋值,结构体数组元素可以直接对同类型元素赋值。
同样不能对整个结构体操作。
举例:
10.结构体指针
指向结构体变量的指针变量称为结构体指针。
定义形式:
struct 结构体名 *结构体变量名
struct storage *p; //系统为指针本身分配内存空间。
成员引用:
struct message
{
uint8_t type; //数据类型
uint8_t slave_address;
uint8_t machine_num;
}infor1;
struce message *p = &infor1;
(*p).type = char //每次使用括号为编写带来不便,C给出了另一种方法:
p->type。-> 为指向运算符。 和分量运算符 . 拥有较高的优先级。
小结: 结构体成员引用方式: stu.name (*p).name p->name //p为结构体指针变量。 |
struct usr { char name[10]; int num; flaot score; }; struct usr staff[100], *p; p = staff; p++或p = staff+1指向哪里? |
11.结构体变量作参数
返回结构体类型值的函数
结构体类型名 函数名(形参...){...}
struct staff func(int x, char name[N]){...};
举例:求学生成绩总分和平均分(分别用结构体变量作为参数和结构体指针做参数)<结构体作参数.c>
二、共用体
不同数据类型使用同一段空间的构造类型称为共用体。(省空间)
共用体(union)在定义、说明和使用形式和结构体相似。
union foo
{
int i;
char c;
};
i = 5;
c = ‘a’;
printf(“%d %c”, i, c);
① union用同一个内存空间存储不同数据类型,即不能同时存下每个成员的数据,同时只有一个成员。
② union变量中的数据时最后一次存放进去的数据,之前的数据会失去作用。
③ union变量地址和其他成员的地址是同一地址
不能对共用体变量名赋值,也不能企图引用变量名来得到一个值,并且,不能在定义共用体变量时对它进行初始化(可以, 仅仅对第一个成员初始化,后面的成员会覆盖前面的数据)。共用体变量的初始化[1] 。
(1)union data a=b; //把共用体变量初始化为另一个共用体
(2)union data a={123}; //初始化共用体为第一个成员
(3)union data a={.ch='a'}; //指定初始化项目,按照C99标准
与结构体的比较: 存储空间的区别 结构体变量可以作为函数参数,函数也可返回一个结构体指针变量。联合体不可以作为函数参数。 |
例1:
a的大小为结构体大小,x,y,z分别为4,5,6. 对k赋值,k要共享内存,union从首地址开始存放数据,x的位置。
《格列佛游记》中把人类按照敲鸡蛋的方向分为两类人,计算机在数据存储的时候也有两种存储机制,分别为大小端。 编写代码测试系统大小端 <Endianness.c> |