C语言第八章 地址和指针

合集下载

c语言八1

c语言八1
出现在定义 时:说明符
• int *p,i=10,j; • p=&i; • j=*p;
1.间接访问运算符 * 是单目运算符。 2.运算对象:必须是指针变量或地址。 j=*(&i); 3.作用:*在赋值号的右边时,取指针p 所指向的存储单元的值。(即*p==10)
间接访问运算符
8.4对指针变量的操作
例如有变量定义语句:char a, short int b, float c; 编 译系统给变量分配的存储空间如图8-1所示。
图8.1 变量分配的存储单元与地址
5001 5002 5003 5004 5005 5006 5007
a
b
c
C语言规定,当一个变量占用一个字节时,该字节 的地址就是该变量的地址,如果变量占用连续的 多个字节,那么第一个字节的地址就是该变量的 地址。
int num=100, *p; p = # *p=15;
num 100 15 FF7C
p
FF7C
指针
内存
一个指针变量可以通过以下三种方式获得一 个确定的地址,从而指向一个具体的对象。 (1)通过求地址运算(&)获得地址值 一般格式为: 指针变量名=地址表达式 例如:int k, *p, *q; q=&k;(‘&’为求地址 运算符) 此时,变量k的地址赋予了q,也可以说q指向 了k。
8.1 变量的地址和指针 1.变量及其地址 在C的程序中要定义许多变量,用来保存程序 中用到的数据,包括输入的原始数据、加工的中 间结果及最终数据。C编译系统会根据定义中变 量的类型,为其分配一定字节数的内存空间(如 字符型占1个字节,整型占2字节,实型占4字节, 双精度型占8字节等),此后这个变量的地址也就 确定了。

C语言 第八章

C语言 第八章

p
printf(“%d,%d\n”,a,b); printf(“%d,%d\n”,*p1,*p2);}
三、指针变量作为函数参数 作用:将一个变量的地址传送到另一个函数中。 作用:将一个变量的地址传送到另一个函数中。 例1:编写实现两个数的交换的函数 : swap(int *p1, int *p2) *p2) void swap(int *p1, int swap(int x,int y) {{ int temp; 定义为*temp? ? int temp; 定义为 { int temp; temp=*p1; temp=x; temp=*p1; *p1=*p2; x=y; *p1=*p2; y=temp; } *p2=temp; } *p2=temp; } main() main() main() { int a,b,*p1,*p2; { int a,b; { int a,b p1=&a;p2=&b; scanf("%d,%d",&a,&b); scanf(“%d%d”,&a,&b); scanf(“%d%d”,p1,p2); swap(a,b); swap(&a,&b); swap(p1,p2); printf("\n%d,%d\n",a,b); printf("%d, %d\n",a,b); printf("%d, %d\n",a,b); }} }
个字节的问题) 个字节的问题)
二、指针变量的引用 “&”(地址运算符 取变量的存储地址。如:&a求变量 的地址。 地址运算符) 取变量的存储地址。 地址运算符 求变量a的地址 求变量 的地址。 “*” (引用运算符 取指针所指向变量的内容。&与*优先级相同, 引用运算符) 取指针所指向变量的内容。 与 优先级相同 引用运算符 优先级相同, 但按自右至左的结合方向。 但按自右至左的结合方向。 例如: 例如:int i=3,*p; p=&i;

全的C语言指针详解PPT课件

全的C语言指针详解PPT课件

在函数中使用指针参数
03
使用指针参数来访问和修改指针所指向的内容,需要使用“-
>”或“*”运算符。
05
指针的高级应用
指向指针的指针(二级指针)
定义与声明
二级指针是用来存储另一个指 针的地址的指针。在声明时, 需要使用`*`操作符来声明二级
指针。
初始化与使用
通过使用`&`操作符获取一个指 针的地址,并将该地址存储在 二级指针中。然后,可以通过 二级指针来访问和操作原始指
当使用malloc或calloc等函 数动态分配内存后,如果 不再需要该内存,必须使 用free函数释放它。否则, 指针将指向一个无效的内 存地址。
当一个指针在函数中定义 ,但该函数返回后仍然存 在并继续指向无效的内存 地址时,就会产生野指针 。
避免指针越界访问
总结词:指针越界访问是指试图访问数 组之外的内存,这是不安全的,可能会 导致程序崩溃或产生不可预测的结果。
指针与内存分配
通过指针来访问和操作动态分配的内存空间。指针可以 存储动态分配的内存地址,并用于读取和写入该地址中 的数据。
指向结构体的指针
01
定义与声明
指向结构体的指针是指向结构体类型的指针。在声明时,需要使用结
构体类型的名称来声明指向结构体的指针。
02 03
初始化与使用
通过使用`&`操作符获取结构体的地址,并将该地址存储在指向结构 体的指针中。然后,可以通过该指针来访问和操作结构体中的成员变 量。
```
பைடு நூலகம்
指向数组元素的指针
• 指向数组元素的指针是指向数组中某个具体元素的指针。通过将指针指向数组中的某个元素,可以访问该 元素的值。
• 指向数组元素的指针可以通过定义一个指向具体元素的指针来实现。例如,定义一个指向数组中第三个元 素的指针,可以使用以下代码

C语言 第八章.用户自定义数据类型

C语言   第八章.用户自定义数据类型
printf("%c,%c\n",u2.c[0],u2.c[1]); }
u2占2个字节
例:以下程序输出结果是?
union example { struct { int x,y; e.b e.a e.in.x }in; e.in int a; e.in.y int b; }e; void main() { e.a=1;e.b=2; e.in.x=e.a*e.b; e.in.y=e.a+e.b; printf("%d,%d",e.in.x,e.in.y); }
内存低地址 01100001 00001010
字符变量c占1个字节
整型变量i占2个字节 单精度实型变量f占4个字节
u1.i=10;
例:以下程序输出结果是?
union u_type { char c[2]; u1
p
内存高地址 内存低地址 ‘a’ ‘b’ c1 c2 c[1] c[0] u1占2个字节 内存高地址 内存低地址 ‘A’ ‘B’ ‘a’ ‘b’ c1 c2 c[1] c[0]
{"0208103322","lisi",19,'M'},{"0208103323","lili",20,'F'}, {"0208103324","xulin",21,'M'}};
学号(number) 姓名(name) 年龄(age) 性别(sex)
stu[0] stu[1] stu[2] stu[3]
char name[8];
int age; char sex;
定义结构体类 sizeof(stu) 型的同时创建 =? 结构体数组

c语言指针与地址的区别

c语言指针与地址的区别

c语⾔指针与地址的区别
指针由两部分组成,指针的类型和指针的值(也就是变量的地址)。

指针和地址的区别:
地址只是⼀堆⼗六进制的字符,对应着内存条的某段内存,⽽指针本⾝有地址,指针的值也是⼀个地址,指针本⾝还有类型,这与单纯的地址是不同的。

指针和地址的联系:
地址可以强转成⼀个指针,例如:
int a = 1;
//假设a的地址是0x7dfe88
int *p = (int *)0x7dfe88;
附:指针类型的作⽤:
指针的值只是存储了某个变量的⾸地址,但是变量是有类型的,⽐如char是1个字节,int是4个字节,单纯的知道某个变量的⾸地址并⽆法完整的获取整个变量的值,必须知道从⾸地址往下读取多少个字节,指针的类型标明了从⾸地址往下读取多少个字节。

C语言指针详解

C语言指针详解

C语言指针详解1 程序如何运行当我们打开电脑中的任何一个程序运行时,我们的操作系统会将该程序存在硬盘的所有数据装载到内存中,然后有CPU 进行读取内存中的数据并进行计算,并将计算的结果返回给我们的操作系统,然后操作系统将相应的动作交付给相应的硬件来完成。

如:将声音数据交给声卡,最后有音响输出来,将图像交给显卡最后有显示器输出……但是还会有一部分数据会返回给内存,以供程序下面的语句继续使用。

我们都知道内存的容量有很大,如:4G,8G, 16G,有时候我们会打开很多的程序,所有的程序的数据都存放到我们的内存中,那么CPU是如何正确的读取我们的不同程序的数据并加以计算的哪?2 内存的假设设计为了让我们的CPU 可以很好的读取内存中的数据,内存必须做优化设计,于是给内存设定了集合设计,将我们的内存分成很多大小相同的方格(盒子),所有的数据将放入这些小盒子中,将不同的程序的数据放入到不同的小盒子中,这样就出现的模块化的内存,当我执行程序的一个命令时,CPU就会从相应的盒子读数据然后计算,由于我们硬件所能访问或计算的最小单位是字节,所以内存中的这样的一个小盒子的大小就给他规定一个字节。

3 地址和指针一般我们声明一块内存空间的时候,会给他取一个名字,为的是我们在编写程序的时候方便使用空间中存放的值,但是CPU 读数据的时候会忽视这个名字,因为CPU无法理解这样的数据,CPU 只能执行0,1代码,那么CPU是如何知道从什么地方读取数据,又到什么地方地址数据的读取的那,所以必须对内存做2次设计,就是将内存中分成的很多小盒子下面标注一些顺序的序号,例如:从第一个盒子开始,标注1,2,3,4,5,6,7,……每一个数字对应一个盒子,但是真正的内存如中不是使用这些十进制数字的,而是使用16进制整数表示的,如0x16ffee。

这些我们标记的数字就叫做内存中的地址。

由于这些地址和盒子是对应的关系,所以只要知道了地址,就可以得到对应盒子中存放的数据了,形象的说,我们说这个地址指向对应的盒子,在C语言中可以通过地址得到对应盒子的数据是*地址。

C语言程序设计第八章 优化学生成绩分析系统指针.ppt

C语言程序设计第八章 优化学生成绩分析系统指针.ppt

C语言程序设计
1 指针与字符串(5)
1.2 使用字符串指针变量与字符数组的区别(续) 例2 分析下面程序的运行结果
main() { char *a="I Love China!";
a=a+7; printf(“%s\n",a); }
运行结果: China!
9
项目八 优化学生成绩分析系统-指针
C语言程序设计
int a,b,c;
例sc6an将f(给"%出d的,%程d"序,&修a,改&b为);使用函数指针变量定义
的c=方m式ax(a,b);
c=(*p)(a,b);
printf("a=%d,b=%d,max=%d",a,b,c);
}
max(int x,int y)
{
int z;
if(x>y) z=x;
else z=y;
指针数组,有4个元素,每个元素 都是指向整型变量指针变量
Int (*p)[4];
由4个整型变量组成的数组的指针
21
项目八 优化学生成绩分析系统-指针
#include <stdio.h> ma3in指()针数组 (2)
C语言程序设计
p[0]
11
{ 3.1 指针数组(续)
22
static int
33
a[3][4]={{11,22,33,44},{55,66,77,88},{99,110,1224,4133}};
【项目分析】
为了保存一个班的C语言成绩需要借助于一维数组,通过指针对其数 据进行操作。将本项目分成两部分,首先借助于指针对一维数组进 行访问,然后介绍一种新的排序算法—选择排序。

C语言程序设计(第八章)

C语言程序设计(第八章)
字符读写函数fgetc()和fputc()是以字符(字节)为单位
的读写函数。 每次可从文件读出或向文件写入一个字符。
第八章
1.读字符函数fgetc()
fgetc() 函数的功能是从指定的文件中读一个字符,函
数调用的形式为:
字符变量 = fgetc(文件指针);
例如:
ch = fgetc(fp);
的意义是从打开的文件fp中读取一个字符并送入ch中 。
(1)字符读/写函数 :fgetc()/fputc()
(2)字符串读/写函数:fgets()/fputs()
(3)数据块读/写函数:freed/()fwrite()
(4)格式化读/写函数:fscanf()/fprinf()
以上函数原型都在头文件stdio.h中加以声明。
第八章
8.5.1字符读/写函数 :fgetc()/fputc()
关闭文件则断开指针与文件之间的联系,禁止再对该文
件进行操作。
第八章
8.3.1 文件打开的函数fopen()
open函数用于打开一个文件,其调用的一般形式为: 文件指针名 = fopen(文件名, 使用文件方式);
“文件指针名”:必须是被说明为FILE 类型的指针变量。
“文件名”:被打开文件的文件名,“文件名”是字符串常 量、字符数组或字符指针。 “使用文件方式”:指文件的类型和操作要求。
/* 输出系统提示信息 */
上面程序段的意义是,如果返回的指针为空,表示不能 打开test.dat文件,则给出提示信息“打开文件test.dat出 错!”,然后输出系统提示信息,当用户从键盘敲任一键后 执行exit(1)退出程序 。
第八章
8.3.2 文件关闭的函数fclose()
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第八章 地址和指针
第一节 变量的地址和指针
1、计算机的内存是以字节为单位的一片连续的存储空间,每一个字节都有一个编号,这个编号就成为内存地址。

2、程序中定义了一个变量,c 编译系统就会根据定义中变量的类型,为其分配一定字节数的内存空间: Short int 2 Int float 4 Double 8 char 1 指针 4
图8.1 变量在内存中所占字节的地址示意图 每个变量的地址就是指该变量所占存储单元的第一个字节的地址。

3、直接存取:程序中我们对变量进行存取操作,实际上也
a 2001
p
3001
a
b
x
1012 1013 1015 1016 1201 1202 1203 1204
就是对某个地址的存储单元进行操作。

这种直接按变量的地址存取变量值的方式。

4、在c 语言中,还可以定义一种特殊的变量,这种变量只是用来存放内存地址的。

图8.2 存放地址的指针变量示意图
通过变量p 间接得到变量a 的地址,然后再存取变量a 的值的方式称为“间接存取”方式,通常变量p 指向了变量a ,变量a 是变量p 所指向的对象。

5、用来存放指针地址的变量就称作“指针变量”。

6、“变量p 指向变量a ”的含义就是指针变量p 中存放了变量a 的地址。

7、在某些场合,指针是使运算得以进行的唯一途径。

第二节 指针的定义赋值
一、 指针变量的定义和指针变量的基本类型 1、 定义指针变量的一般形式如下: 类型名 *指针变量名1,*指针变量名2…… 说明:1)类型名是基本类型。

2)*是说明符。

(而在调用的时候,代表的是存储单元中的值)
3)指针变量名是用户标识符。

2002
2002
1012 1013
p
a
p
例:1)int *pi,*pj; pi pj只能存放整型变量的地址int I,*pi;double *pj;
2)p为一个指向指针的指针变量
int **p,*s,k=20;
s=&k;p=&s;
*p代表存储单元s,*s代表存储单元k,因此**p 也代表存储单元k
2、为什么指针变量要有“基类型”呢?
一个指针变量中存放的是一个存储单元的地址值,一个存储单元的中的“一”所代表的字节数是不同的:int float
二、给指针变量的赋值
1、通过求地址运算符(&)获得地址值
1)&用来求出运算对象地址,用求地址运算可以把
一个变量的地址赋给指针变量
2)把变量k的地址赋予q,这时可以说:q指向了变
量k。

3)求地址运算符只能应用于变量和数组元素,不可
用于表达式、常量或被说明为register的变量。

&必须放在运算对象左边,且运算对象类型必须与指针变量的基类型相同。

4)调用scanf函数时,若q=&k 则scanf(“%d”,
&k)和scanf(“%d”,q)是等价的。

2、通过指针变量获得地址值
可以通过赋值运算,把一个指针变量中的地址赋给另外一个指针变量,从而使这两个指针指向同一地址。

p=q
注意:赋值号两边的指针变量的基类型必须相同。

3、通过标准函数获得地址值
可以通过调用库函数malloc和calloc在内存中开辟动态存储单元,并把开辟的动态存储单元的地址赋给指针变量。

4、给指针变量赋“空”值
p=NULL;
NULL代码值为0,当执行了以上的赋值语句后,称p 为空指针。

以上语句等价于:
p=’\0’p=0
企图通过一个空指针去访问一个存储单元时,将会出错。

三、对指针变量的操作
1、通过指针来引用一个存储单元
1)c语言中提供了一个称作“间接访问运算符”的单目运算符“*”。

当指针变量中存放了一个确切的地址值时,就可以用*p来引用该地址的存储单元。

int *p,i=10,j;
p=&i
j=*&i
j=*p+1 指针变量p所指存储单元中的内容加1后赋予j 2)int *p,k=0;
p=&k;
*p=100 把100存放在变量k中
*p=*p+1 p所指存储单元中的值加1后,再放入p所指存储单元中,即:k变为101
*p出现在赋值号左边时,代表的是指针所指的存储单元;当*p出现在赋值号右边时,代表的是指针所指的存储单元的内容。

*p+=1 ++*p (*p)++括号不能少
2、移动指针
a[0] a[1] a[2] a[3] a[4]
p q
q=p+2; /*使指针q指向存储单元a【2】*/
q++; /*q向高地址移动指针,指向a【3】*/
q++; /*q向高地址移动指针,指向a【4】*/
q--; /*q向低地址移动指针,指向a【3】*/
p++; /*p向高地址移动指针,指向a【1】*/
q-p=2
1)所谓移动指针就是对指针变量加上或减去一个整数,或
通过赋值运算,使指针变量指向相邻的存储单元。

因此只有当指针指向一串连续的存储单元时,指针的移动才有意义。

2)当指针指向一串连续的存储单元时,可以对指针变量进行加上或减去一个整数的运算,也可以对指向同一串连续存储单元的两个指针进行相减运算。

3)在对指针进行加、减运算中,数字1不代表整数1,而是指一个存储单元长度,至于一个长度占多少个字节的存储空间,则视指针的基类型而定。

4)当移动指针时,基类型为int的指针只能用来指向int变量,不能用以指向其他类型的变量。

3、指针的比较
在关系表达式中可以对两个指针进行比较。

通常两个或多个指针指向同一目标(如同一串连续的存储单元)时比较才有意义。

四、函数之间地址值的传递
1、形参为指针变量时实参和形参之间的数据传递
若函数的形参为指针类型,调用该函数时,对应的实参必须是基类型相同的地址值或者是已指向某个存储单元的指针变量。

例:编写函数myadd(int *a,int *b),函数中把指针a和b 所指存储单元中的两个值相加,然后将和值作为函数值返回。

程序如下:
#include <stdio.h>
myadd(int *a, int *b)
{ int sum;
sum=*a+*b;
return sum;
}
main()
{ int x,y,z;
printf("input x,y:\n");
scanf("%d%d",&x,&y);
z=myadd(&x,&y);
printf("%d+%d=%d\n",x,y,z);
}
2、通过传送地址值在被调用函数中直接改变调用函数中
的变量的值
例:调用swap函数,交换主函数中变量x和y中的数据。

#include <stdio.h>
void swap(int *a, int *b)
{
int t;
printf("2) a=%d,b=%d\n",*a,*b);
t=*a;*a=*b;*b=t;
printf("3) a=%d,b=%d\n",*a,*b);
}
main()
{
int x=30,y=20;
printf("1) x=%d,y=%d\n",x,y);
swap(&x,&y);
printf("4) x=%d,y=%d\n",x,y);
}
在c程序中可以通过传送地址的方式在被调用函数中直接改变调用函数中的变量的值,从而达到函数之间的数据传递。

3、函数返回地址值
函数值的类型不仅可以是简单的数据类型,而且可以是指针类型。

例:编写程序,把主函数中变量i和j中存放较大数的那个地址作为函数值传回。

#include <stdio.h>
int *fun(int *,int *);
main()
{
int *p,i,j;
printf("input two number:\n");
scanf("%d%d",&i,&j);
p=fun(&i,&j);
printf("i=%d,j=%d,*p=%d\n",i,j,*p); }
int *fun(int *a,int *b)
{
if(*a>*b) return a;
return b;
}。

相关文档
最新文档