C语言——数组、函数、指针
宗旨:技术的学习是有限的,分享的精神是无限的。
1、有什么作用?为什么要使用它们?
(1)数组:提供一段连续的存储空间,存数据和字符串很方便;
(2)函数:模块化程序的设计(返回值和参数);
(3)指针:使用灵活;
2、数组的内存布局
【数组和链表区别:数组顺序存储,大小固定;链表随机存储,大小不定。】
int a[5]; --- a作为右值时,代表数组首元素的首地址,而非数组的首地址
//分配了20字节的空间名字为a, a[0], a[1]为a的元素,并非元素的名字。只给数组取名,没给元素取名。
sizeof(a) --- sizeof(int) * 5 --- 20
sizeof(a[0]) --- sizeof(int) --- 4
sizeof(a[5]) --- sizeof(int) --- 4 并没出错,关键字求值是在编译的时候,虽不存在a[5],但这里并未真正访问a[5]。
sizeof(&a[0])--- 4
sizeof(&a)--- 4
&a[0]和&a ---- &a[0]代表数组首元素的首地址,&a是数组的首地址;值一样,意义不同。
右值:出现在“=”右边的值; 左值:出现在“=”左边的值。
a不能作为左值
初始化数组:memset(a,0, sizeof(a)); // 初始化为0
3、指针数组/数组指针,指针函数/函数指针
指针数组:int*a[10]; --- 实质就是个数组,只不过数组里面的元素全是指针。
数组指针:int(*a)[10]; --- 实质就是个指针,指向一个数组。
指针函数:int*a(int b, int c); --- 这就是个普通的函数,只不过返回值是int*类型的。
函数指针:int(*a)(int b, int c); --- a是个函数指针,指向一个函数,b,c是函数的参数,返回值为int【a = fun;】。
【typedefint (*potion_t)(int a, int b) --- potion_t相当于一个类型,可以直接用potion_t定义一个变量,只不过这个变量指向一个函数】
4、值传递和地址传递
值传递过程中,被调函数的形参作为被调函数的局部变量处理,即在内存的栈中开辟空间以存放由主调函数放进来的实参的值,从而成为了实参的一个拷贝。值传递的特点是被调函数对形参的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。
而在地址传递过程中,被调函数的形参虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。
5、菜单界面的设计
菜单一-- 菜单二-- 菜单三-- 菜单四-- 菜单
/* 将菜单的属性和操作“封装”在一起 */
#define MENUNUM 10;
typedef struct tag_sysmenu
{
char *text; /* 菜单的文本 */
char xpos; /* 菜单在LCD上的X坐标 */
char ypos; /* 菜单在LCD上的Y坐标 */
void (*on_ok_fun)(); /* 在该菜单上按下OK键的处理函数 */
void (*on_cancel_fun)(); /* 在该菜单上按下cancel键的处理函数 */
} sys_menu_t, *lpsys_menu_t;
static sys_menu_t menu[MENUNUM] =
{
{"menu1", 0, 48, menu1on_ok, nemu1on_cancel},
{"menu2", 7, 48, menu2on_ok, nemu2on_cancel},
{"menu3", 7, 48, menu3on_ok, nemu3on_cancel},
{"menu4", 7, 48, menu4on_ok, nemu4on_cancel}
...
};
OK和Cancel键的处理变成:
void onok_key()
{
menu[currentFocusMenu].on_ok_fun();
}
void on_cancel_key()
{
menu[currentFocusMenu].on_cancel_fun();
}