2019年7月11日星期四

一、复杂指针定义

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)数组中&A与A有什么区别?

&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\n",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\n”,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\n",A);

printf("%s\n",A);

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

}

int main()

{

char *p = NULL;

p = fun();

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

printf("%s\n",p);

}

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

解决方案:

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

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

四、二维数组

1、二维数组的基本概念

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

例子:

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

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

2、如何定义二维数组?

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

定义数组的方式:

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

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\n”,a[1][2]);

}

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

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

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

时间: 2024-07-30 15:06:22

2019年7月11日星期四的相关文章

2019年2月11日-日记

2019年2月11日, 星期一 感想之歌 new soul,静悄悄. Some monster,说爱你. 飞云之下,雪落下来的声音,舒伯特玫瑰. 探清水河,胡广生,童话镇,至少还有你. 远走高飞,九张机,月牙湾,心动了没有. 海绵宝宝,你一定要幸福,将来的东西,再见,光年之外. 给我一个吻,拜托,请先说你好. 带你去旅行,江南,全部都是你. 遥远的她,月半小夜曲,从天而降. 九门回忆,all falls down,right now. 洪荒之力,遇见,乌云中. superstar,出卖,小幸运.

2019年8月15日星期四(系统编程)

2019年8月15日星期四 一. 线程互斥方式 - 互斥锁. 1. 什么是互斥锁?特点如何? 互斥锁是专门用于处理线程互斥的一个方式,它有两种状态:上锁状态/解锁状态. 特点:如果处理上锁状态,则不能再上锁,直到解锁为止才能再上锁.如果是处于解锁状态,则不能再解锁了,直到上锁了才能再解锁. 2. 关于线程互斥锁API函数接口? 0)定义互斥锁的变量(pthread_mutex_t-> 互斥锁的数据类型) pthread_mutex_t mutex; 1)初始化互斥锁  -> pthread_m

2019年9月19日星期四(STM32)

一.RTC(实时时钟) 1.背景 时间在计算机系统中是一个非常重要的参数,在很多应用场景下都需要使用时间.RTC就是一个专门记录时间的设备,本质上是一个1Hz定时器. 为了计时准确,计时系统掉电也要能够正常计时.为了到达这个目的,RTC需要独立的时钟源,独立的供电电源 stm32f407的RTC的时钟源是低速晶振(LSE---32.768KHz),使用纽扣电池单独供电 2.stm32f407的RTC RTC进行2次预分频,一次7位异步和15位的同步,最终得到1hz的时钟,为了降低功耗,异步预分频

2016年8月11日 星期四 --出埃及记 Exodus 16:11-12

The LORD said to Moses,"I have heard the grumbling of the Israelites. Tell them, `At twilight you will eat meat, and in the morning you will be filled with bread. Then you will know that I am the LORD your God.'" 耶和华晓谕摩西说,我已经听见以色列人的怨言.你告诉他们说,到黄昏

2019年5月11日-linux就该这么学-第5课

第4章 Vim编辑器与Shell命令脚本 4.1 Vim文本编辑器编辑器的三种模式:输入模式和末行模式必须通过命令模式才能进行转换. 命令模式:控制光标的移动,可对文本进行复制.粘贴.删除和查找等,运行时默认进入命令模式: 输入模式:正常文本的录入和编辑等:在命令模式下按a.i.o键进入,按Esc键退回到命令模式: 末行模式:命令模式下按:进入末行模式.保存.退出.设置编辑环境. 4.2 缩写Shell脚本Shell脚本的工作方式:交互式.批处理: Shell脚本的编写:(1)脚本名称:*.sh

2019年7月18日星期四(交叉工具链)

一.交叉工具链? 1.什么是交叉工具链? 我们已经学习过的编译器是gcc编译器,gcc可以将高级语言转换目标程序. gcc编译器特点:在Ubuntu编译,在Ubuntu运行.  -> 在同一个平台上编译运行,这个gcc编译器又称之为本地编译. 这个gcc编译器是Ubuntu中自带,gcc所的路径:/usr/bin/gcc. 其实交叉工具链就是一个编译器,但是交叉工具链在Ubuntu中是没有的,所以想使用交叉工具链,就必须要自己移植. 交叉工具链面向平台不是Ubuntu,而是ARM平台.交叉工具链

2019年7月18日星期四(linux基础)

一.linux文件种类 1.如何查看linux下文件类型?如何决定文件类型? 使用"ls -l"查看文件的详细属性,其中第一个字母就是文件类型,是由创建方式来决定文件的类型.例如:使用mkdir命令来创建,就一定是目录文件. 2. 在linux下,一共有多少种文件类型 有7种.分别是: 文件类型        创建方式       字母 ====================================== 普通文件   ->    touch          - 目录文

2019年8月22日 星期四(怎样成为PHP大牛)

1.服务器方面,各种PHP部署方案烂熟,Lvs,keepalived,nginx,apache,docker,换句话说其战力值相当于一个高级运维,迅速定位并排除PHP运行中的各种问题. 2.数据库方面,mysql,red is,memcache,mongodb等常见PHP有关的数据库通杀,性能调优方案信手拈来,大数据高并发处理方案如数家珍. 3.编程能力上,除PHP外,还至少精通C语言.有开源PHP扩展贡献.各种设计模式精通,代码精炼无懈可击.熟悉各种算法.写个PHP框架不在话下.熟悉常见的PH

2019年8月22日 星期四(总结重要的)

WebSocket 比如A,B,C3人同时在一个页面上浏览,A对B进行了评论,并且提到了C.传统的架构,B,C将无法感知到,只有B,C再次拉取内容时,才会得到此信息.显然B ,C错过了与A交互的最佳时机,而且得知信息的时间延后了很多. 传统的PULL模式,也可以通过定时轮询的方式来尝试拉取数据.但这种技术 1是并不是实时的,信息还是需要到了一定时间间隔才可以得到. 2,这种方式可能大部分请求是无效的,白白浪费了一次网络请求.还造成了web Server的负载大大增高. 真正的PUSH技术目前有3