第八天(坚持就是胜利)
指针和二维数组关系
int a[2][3]; <==> int (a[2])[3] ==> int (*)[3];
int (*)[3] p; //符合c的变量定义语法,不符合编译器的要求
||
\/
int (*p)[3];
因为是行序优先,所以我们可以将每行看成一个元素。
xxx a[2] = {a[0],a[1]};
xxx是12个字节的类型(本质是包含了3个int的一维数组)
a 指向了 a[0]元素 a + 1指向了a[1]元素
所以 a + 1跳过了一行
a + i 指向 a[i] *(a + i)操作a[i]数据,a[i]是每行数据的首地址
a[i] + j每次跳过一个具体元素
行指针
a + i
&*(a + i) <==> &a[i]
列指针
a[i] + j
*(a + i) + j
指针和指针数组关系
char *str[3] = {"abc","easd","unsi"};
char * *p = str;
int (*str[2])[3];
int (*)[3] str[2];
int (*)[3]*p;
int (**p)[3] = str;
函数:
什么是函数?将一系列的语句封装之后的一个集合。
为什么使用函数?理论上没有函数可以,但是会增加很大的工作量。
实际上使用函数为了减少工作量(使程序模块化)
函数的基本特性:
函数声明:照着函数定义的原型抄,同时去掉参数名称留下参数类型。
函数定义:返回值 函数名(形式参数);
返回值可以有也可以没有,如果没有用void代替
形式参数可以有可以没有,如果不存在使用void代替(或者什么都不用写),如果有形参(包含数据类型 变量名)
注意:多个参数之间使用逗号分隔
函数调用:
引用方法:
1、没有返回值:函数名(实参);
2、有返回值:变量 = 函数名(实参);
注意:1、一般情况,函数声明出现在函数调用的前面,函数的定义出现在函数的调用后面。
2、很多时候也可以将函数声明和函数定义放在一起使用,这时函数定义一定要出现在函数调用的前面
什么是实参,什么是形参?
实参专门给函数调用使用的,可以是变量可以是常量
形参出现在函数的定义中,必须是变量
实参和形参之间是什么关系?所谓的函数传参
传参的本质就是一个赋值语句。
赋值运算符左端必须是变量(作为形参),右端可以是变量可以是常量(实参)。
函数传参的方式:
针对于基本类型的:
1、复制传参 将原有数据做了一个备份,在函数调用中使用的是备份的值
2、地址传参 将原有数据的地址做了一个备份。
针对于构造类型的:
1、复制传参
2、地址传参
数组的复制传参和地址传参本质都是传递地址,只是格式不同
了解:指针函数(所有资料上提到的指针函数都是胡扯)
就是一个函数,返回值是一个地址。
int fun(int a)
{
操作
return a;
}
char *fun1(char *p)
{
return 指针;
}
main()
{
int x;
x = fun(10);
char a;
char *q;
q = fun1(&a);
}
非常重要:函数指针
函数名:函数名在内存中代表了函数空间的入口地址(地址常量)。
函数空间不连续,数组空间连续。
可以使用某种指针来存放函数名,这种指针就叫做函数指针变量。
如何定义函数指针?看起来好像很难,其实有一条规则:在函数的声明中,将函数名转变为(*),其他位置不变。
函数声明:int test(int,char);
函数指针:int (*)(int,char);这就是一个函数指针类型。
定义指针变量:int (*)(int,char) p;//这种格式编译器不识别,真正用法:int (*p)(int,char);
例如:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
int (*p)(pthread_t *,const pthread_attr_t *,void *(*start_routine) (void *),void *);
p = pthread_create;
void (*fun(int,void (*)(int)))(int);<==> void (*)(int) fun(int,void (*)(int));
fun是一个函数原型,有两个参数,第一个参数是int,第二个参数是void (*)(int).返回值是void (*)(int)
函数递归:一个函数调用其本身
内联函数
作业:
1、在终端输出字符串,然后封装一个函数,这个函数的功能是:去掉输入的字符串中的空格
gets(str); //在终端输入a b c d e
输出结果为abcde
2、在终端输入一个字符串,假设为:"hello world china"
输出结果是:china world hello
提示:使用两次逆序操作。
anihc dlrow olleh
再以空格为分隔符分别逆序单词
int a[2][3]; <==> int (a[2])[3] ==> int (*)[3];
int (*)[3] p; //符合c的变量定义语法,不符合编译器的要求
||
\/
int (*p)[3];
因为是行序优先,所以我们可以将每行看成一个元素。
xxx a[2] = {a[0],a[1]};
xxx是12个字节的类型(本质是包含了3个int的一维数组)
a 指向了 a[0]元素 a + 1指向了a[1]元素
所以 a + 1跳过了一行
a + i 指向 a[i] *(a + i)操作a[i]数据,a[i]是每行数据的首地址
a[i] + j每次跳过一个具体元素
行指针
a + i
&*(a + i) <==> &a[i]
列指针
a[i] + j
*(a + i) + j
指针和指针数组关系
char *str[3] = {"abc","easd","unsi"};
char * *p = str;
int (*str[2])[3];
int (*)[3] str[2];
int (*)[3]*p;
int (**p)[3] = str;
函数:
什么是函数?将一系列的语句封装之后的一个集合。
为什么使用函数?理论上没有函数可以,但是会增加很大的工作量。
实际上使用函数为了减少工作量(使程序模块化)
函数的基本特性:
函数声明:照着函数定义的原型抄,同时去掉参数名称留下参数类型。
函数定义:返回值 函数名(形式参数);
返回值可以有也可以没有,如果没有用void代替
形式参数可以有可以没有,如果不存在使用void代替(或者什么都不用写),如果有形参(包含数据类型 变量名)
注意:多个参数之间使用逗号分隔
函数调用:
引用方法:
1、没有返回值:函数名(实参);
2、有返回值:变量 = 函数名(实参);
注意:1、一般情况,函数声明出现在函数调用的前面,函数的定义出现在函数的调用后面。
2、很多时候也可以将函数声明和函数定义放在一起使用,这时函数定义一定要出现在函数调用的前面
什么是实参,什么是形参?
实参专门给函数调用使用的,可以是变量可以是常量
形参出现在函数的定义中,必须是变量
实参和形参之间是什么关系?所谓的函数传参
传参的本质就是一个赋值语句。
赋值运算符左端必须是变量(作为形参),右端可以是变量可以是常量(实参)。
函数传参的方式:
针对于基本类型的:
1、复制传参 将原有数据做了一个备份,在函数调用中使用的是备份的值
2、地址传参 将原有数据的地址做了一个备份。
针对于构造类型的:
1、复制传参
2、地址传参
数组的复制传参和地址传参本质都是传递地址,只是格式不同
了解:指针函数(所有资料上提到的指针函数都是胡扯)
就是一个函数,返回值是一个地址。
int fun(int a)
{
操作
return a;
}
char *fun1(char *p)
{
return 指针;
}
main()
{
int x;
x = fun(10);
char a;
char *q;
q = fun1(&a);
}
非常重要:函数指针
函数名:函数名在内存中代表了函数空间的入口地址(地址常量)。
函数空间不连续,数组空间连续。
可以使用某种指针来存放函数名,这种指针就叫做函数指针变量。
如何定义函数指针?看起来好像很难,其实有一条规则:在函数的声明中,将函数名转变为(*),其他位置不变。
函数声明:int test(int,char);
函数指针:int (*)(int,char);这就是一个函数指针类型。
定义指针变量:int (*)(int,char) p;//这种格式编译器不识别,真正用法:int (*p)(int,char);
例如:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
int (*p)(pthread_t *,const pthread_attr_t *,void *(*start_routine) (void *),void *);
p = pthread_create;
void (*fun(int,void (*)(int)))(int);<==> void (*)(int) fun(int,void (*)(int));
fun是一个函数原型,有两个参数,第一个参数是int,第二个参数是void (*)(int).返回值是void (*)(int)
函数递归:一个函数调用其本身
内联函数
作业:
1、在终端输出字符串,然后封装一个函数,这个函数的功能是:去掉输入的字符串中的空格
gets(str); //在终端输入a b c d e
输出结果为abcde
2、在终端输入一个字符串,假设为:"hello world china"
输出结果是:china world hello
提示:使用两次逆序操作。
anihc dlrow olleh
再以空格为分隔符分别逆序单词