2019年7月11日星期四(C语言)

一、复杂指针定义

1、简单指针   -> 指向基本数据类型  char int long..

    复杂指针   -> 指向非基本数据类型  指针/数组/函数/结构体

2、二级指针?

指向指针的指针。

int a;

int *pa = &a;   pa就是一级指针

int **p = &pa;  p就是二级指针

3、数组指针?

指向整个数组的基地址指针就是“数组指针”

1)如何定义数组指针?

方法与定义简单指针一致。

int a;

int *p = NULL;

p = &a;  -> 整型指针   -> 指针类型:int*   -> 代表该指针指向一个整型数据。

int A[3];

int(*p)[3] = &A;  -> 数组指针  -> 指针类型:int(*)[3]   -> 代表该指针指向一个具有3个int类型数据的数组

2)数组中&AA有什么区别?

&A  -> 代表这个数组的地址        int(*)[3]

A   -> 代表这个数组首元素的地址  int *

int A[3];

int(*p)[3]=A;   -> 不能把int*类型数据赋值给int(*)[3],因为类型不匹配!

3)解引用

int A[3] = {100,200,300};

int(*p)[3] = NULL;

p=&A;

请问*p得到什么?

*p = *(&A) = A = &A[0]  -> 解引用数组指针,得到数组首元素的地址。

请问p[0]/p[1]是什么?

p[0] = *(p+0) = *(p) = *(&A) = A = &A[0]

p[1] = *(p+1)  p+1已经越界,访问未知区域。

请问(*p)[1]得到什么?

(*p)[1] = (*&A)[1] = A[1] = 200

练习1:若有以下说明:

int B[10];

int (*p)[10]=&B;

int *px=B;

则下列能正确引用数组的元素的是?

A. *p+1  B.*(p[1])  C.(px+3)[2]  D.(*px)[3]  E. (*p)[0]  F. *(px+1)

4、函数指针?

指向函数的一个指针。

1)如何定义函数指针?

例子:

int a;

int *p = &a;

int fun(int x,int y);   -> 指向该函数指针怎么写?

int(*p)(int,int) = &fun;

结果:int(*p)(int,int)

变量名:p

数据类型:int(*)(int,int)

2)在linux C语言中,函数名字就是函数的地址,所以:  fun 等价于 &fun

int fun(int x,int y); 

int(*p)(int,int) = &fun;  等价于   int(*p)(int,int) = fun;

练习2:求出两个数字最大值,要求使用函数指针完成。

#include <stdio.h>

int fun(int x,int y)

{

       int z;

       z = (x > y ? x : y);

       return z;

}

int main()

{

       int max;

       int(*p)(int,int) = NULL;

       p = &fun;

       max = p(100,200);

       printf("max = %d ",max);

       return 0;

}

二、数组作为函数的参数时,在内存中的变化情况?

1、学习过传递类型

例子1:传递int类型数

void fun(int x)  //x = a;

fun(a);

例子2:传递指针地址

void fun(int *x)  x = &a;

fun(&a);

例子3:传递函数

void fun(void (*x)(int))  x = &myfun  /  x = my_fun

void my_fun(int a);

fun(my_fun);

2、数组作为实参时,其实将数组首元素传递过去。

例子:

以下三种写法完全等价

void fun(int x[])   // x = A = &A[0]

void fun(int x[3])  // x = A = &A[0]

void fun(int *x)    // x = A = &A[0]

int main()

{

       int A[3];

       fun(A);  //在这里,A不是作用sizeof(),所以代表首元素地址  int*

       //等价于fun(&A[0]);

}

练习:

10、有以下程序

void swap1(int c0[], int c1[])

           int t ;

       t=c0[0]; c0[0]=c1[0]; c1[0]=t;

}

 

void swap2(int *c0, int *c1)

       int t;

       t=*c0; *c0=*c1; *c1=t;

}

main()

{

       int a[2]={3,5}, b[2]={3,5};

       swap1(a, a+1);

       swap2(&b[0], &b[1]);

       printf(“%d %d %d %d ”,a[0],a[1],b[0],b[1]);

}

程序运行后的输出结果是( D )

A)3 5 5 3       B)5 3 3 5

C)3 5 3 5       D)5 3 5 3

9、有以下程序

void fun(int *a,int i,int j)

       int t;

           if(i<j)

       {

              t=a[i];

              a[i]=a[j];

              a[j]=t;

              fun(a,++i,--j);

       }

}

main()

{  

       int a[]={1,2,3,4,5,6},i;

           fun(a,0,5);

           for(i=0;i<6;i++) 

              printf(“%d”,a[i]);

执行后的输出结果是( A )

A) 6 5 4 3 2 1       B) 4 3 2 1 5 6

C) 4 5 6 1 2 3       D) 1 2 3 4 5 6

三、数组作为函数的返回值时,情况是如何的?

#include <stdio.h>

char *fun()

{

       char A[4] = {'a','b','c'};

       printf("A = %p ",A);

       printf("%s ",A);

       return A;   //-> 返回数组首元素的地址  类型: char*

}

int main()

{

       char *p = NULL;

       p = fun();

       printf("p = %p ",p);

       printf("%s ",p);

}

编译警告:warning: function returns address of local variable  -> 数组A再函数fun结束时,内存空间会释放。

解决方案:

1)将数组设置为全局变量

2)在数组前面加static修饰数组   -> 数组被static修饰后,不再存在与栈区,而是存在数据段。

四、二维数组

1、二维数组的基本概念

二维数组在内存中是线性规则,不存在行与列的关系,其实二维数组就是一个一维数组,只是一维数组中每一个成员都是数组。

例子:

整型数组: int A[5]  -> 该数组中每一个成员都是int类型数据。

二维数组: 数组 A[5] -> 该数组中每一个成员都是数组

2、如何定义二维数组?

只需要确定数组的元素个数与每一个元素的数据类型即可!

定义数组的方式:

例子1:定义具有5int类型数据的数组:

1)给一个数组名 A

2)确定数组中元素的个数,使用[]括住它,跟在数组名后面 A[5]

3)确定数组中每一个成员的数据类型是什么  int a;

4)将第3步结果的变量名去掉  int

5)将第4步结果写在第2步结果前面  int A[5]

例子2:定义二维数组

1)给一个数组名 B

2)确定数组中元素的个数,使用[]括住它,跟在数组名后面 B[2]

3)确定数组中每一个成员的数据类型是什么  int A[3]

4)将第3步结果的变量名去掉  int [3]

5) 将第4步结果结合到第2步结果中   int B[2][3]

 

结果:int B[2][3]

代表这个数组中有两个成员,每一个成员都是具有3个int类型数据的数组。

3、二维数组的赋值

int B[2][3] = {{1,2,3},{4,5,6}};

4、二维数组的数组名

例子:int B[2][3]

sizeof(B) = 24

&B            -> 代表整个二维数组的地址,              类型: int(*)[2][3]

B=&B[0]       -> 代表二维数组的首元素的地址,          类型: int(*)[3]

B[0]=&B[0][0] -> 代表二维数组的首元素的首元素的地址,   类型: int *

B[0][0]       -> 代表二维数组的首元素的首元素的值,     类型: int

5、解引用

1)请问解引用二维数组的名字得到什么?

得到二维数组的首元素的首元素的地址。

int B[2][3] = {{1,2,3},{4,5,6}};

*B=*(&B[0])=B[0]=&B[0][0]

2)请问解引用二维数组的首元素得到什么?

得到二维数组的首元素的首元素的值。

*B[0]=*(&B[0][0])=B[0][0]

练习2:

12、若有以下说明和语句:int c[4][5],(*p)[5];p=c;能正确引用c数组元素的是( D )

A) p+1    B) *(p+3)    C) *(p+1)+3    D) *(p[0]+2)

13、有以下程序

main()

{  

       int a[3][3],*p,i;

        p=&a[0][0];

        for(i=0;i<9;i++) 

              p[i]=i+1;

        printf(“%d ”,a[1][2]);

}

程序执行以后的输出结果是( B )

A) 3     B) 6     C) 9     D) 7

原文地址:https://www.cnblogs.com/zjlbk/p/11172159.html