算法笔记之第二章 函数、指针

函数

void print1(){
    printf("Haha,\n");
    printf("Good idea!\n");
}

void是返回类型,含义是“空”,即不返回任何东西
print1后面小括号没有任何参数,即无参函数

int main(){
    print1();
    return 0;
}

输出结果:
Haha,
Good idea!

有参函数的例子:

int judge(int x){
    if(x > 0) return 1;
    else if(x == 0) return 0;
    else return -1;
}

judge()函数有了返回类型,即int型

局部变量:定义在函数内部,函数结束时局部变量销毁

再谈main函数

整个程序一定是从主函数的第一个语句开始执行

以数组作为函数参数

参数中数组的第一维不需要填写长度,如果是二维数组,那么第二维需要填写长度
数组作为参数时,在函数中对数组元素的修改就等同于是对原数组元素的修改,这与普通的局部变量不同

函数的嵌套调用

int max_2(int a, int b){
    if(a > b) return b;
    else return b;
}

int max_3(int a, int b, int c){
    int temp = max_2(a, b);
    temp = max_2(temp, c);
    return temp;
}

int main(){
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    printf("%d\n", max_3(a,b,c));
    return 0;
}

函数的递归调用

即函数自己调用自己的过程

int F(int n) {
    if(n ==0) return 1;
    else return F(n - 1) * n;
}
int main(){
    int n;
    scanf("%d",&n);
    printf("%d\n",F(n));
    return 0;
}

输入3
输出6 即3!=6

指针

指针就是变量(房间)的地址(房间号)
只要在变量前面加上&,就表示变量的地址

输出变量地址

int a = 1;
printf("%d, %d\n", &a, a);
return 0;

输出结果2686748,1

指针是一个unsigned类型的整数

指针变量

用来存放指针(地址)
*可以放在变量前或后

需要挨个定义

int *p1, *p2, *p3;

给指针变量赋值的方式一般是把变量的地址取出来,然后赋给对应类型的指针变量

把星号视为一把开启房间的钥匙,将其加在p前面,这样*p就能把房间打开,然后获取a的值

int a
int* p = &a;
a = 233;
printf("%d\n", *p);
return 0;

但地址&a的值是赋给了p而不是*p,记住星号是类型的一部分

直接对*p进行赋值:令指针变量p存放a的地址,然后直接对*p进行赋值。于是 *p和a都会输出那个值

int a;
int* p = &a;
*p = 233;
printf("%d, %d\n, *p, a);
return 0;

输出结果
233,233

对int*型指针变量p来说,p+1是指所指的int型变量的下一个int型变量地址(跨越了一整个int型(即4Byte))

指针变量支持自增自减操作

指针与数组

数组名称也作为数组的首地址使用

int a[10] = {1};
int* p = a;
printf("%d\n",*p);
return 0;

输出结果 1,因此输出*p就是输出a[0]

指针变量可加减则a+i等于&a[i],但若要访问元素则要加上星号变为*(a+i)才和a[i]等价

输出数组元素

scanf("%d", a + i);

枚举数组中的元素

int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(int*p = a; p < a + 10; p++){
    printf("%d ", *p);
    }
    return 0;

输出结果:1 2 3 4 5 6 7 8 9 10

两个指针相减,等价于两个指针之间相差几个int(两个地址间的距离)

int* p = a;
int* q = &a[5];
printf("q - p = %d\n", q - p)
return 0;

输出结果为5

使用指针变量作为函数参数

把变量的地址传入函数,如果在函数中对这个地址地元素进行改变,原先的数据就会改变

void change(int* p){
    *p = 233;
}

int main(){
    int a = 1;
    int* p = &a;
    change(p);
    printf("%d\n", a);
    return 0;
}

输出结果233,即使用*p修改地址中存放的数据。这种传递方式被称为地址传递。

交换功能如果不使用地址写成函数,无法影响main函数,因为它是单项一次性的值传递

只有在获取地址的情况下对元素进行操作,才能真正地修改变量。如下:

void swap(int* a, int* b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main(){
    int a = 1, b = 2;
    int *p1 = &a, *p2 = &b;
    swap(p1, p2);
    printf("a = %d, b = %d\n", * p1, *p2);
    return 0;
}

解释:&a,&b(即ab的地址)作为参数传入,使swap函数中int*型指针变量a存放&a、指针变量b存放&b。
swap函数中的ab都是地址,而*a和*b就是地址中的数据

错误一:

void swap(int* a, int* b){
    int* temp;
    *temp = *a;
    *a = *b;
    *b = *temp;
}

这是因为temp没有被初始化,所以指针变量temp中存放的地址是随机的。改为:

void swap(int* a, int* b){
    int x;
    int* temp = &x;
    *temp = *a;
    *a = *b;
    *b = *temp;
}

错误二:

void swap(int* a, int* b){
    int* temp = a;
    a = b;
    b = temp;
}

这样做不能修改main函数里的地址
而能使main函数里的数据发生变化的只能是swap函数中对地址指向的数据进行的修改

引用

是C++中的语法,引用不产生副本,相当于一个人的两个名字,且对引用变量的操作就是对于原变量的操作。

使用方式:在哈数参数类型后面加一个&

void change(int&x){
    x = 1;
}
int main(){
    int x = 10;
    change(x);
    printf("%d\n", x);
    return 0;
}

输出结果1

不管是否使用引用,函数的参数名和实际传入的参数名可以不同。比如上述main函数中的x也可以写成a

注意虽然符号相同,但引用并不是取地址的意思

指针的引用

错误写法二可改为

void swap(int* &p1, int* &p2){
    int* temp = p1;
    p1 = p2;
    p2 = temp;
}
int main(){
    int a = 1, b = 2;
    int *p1 = &a, *p2 = &b;
    swap(p1, p2);
    printf("a = %d, b = %d\n, *p1, *p2);
    return 0 ;
}

可以把int*型理解成unsigned int型
由于引用式产生变量的别名,因此常量不可使用引用,所以不能写成swap(&a,&b),必须用指针变量p1和p2存放&a,&b,然后把指针变量作为参数传入
如果理解遇到困难,可以先把引用去掉,看看原意是什么,再加上引用

你可能感兴趣的:(算法笔记)