null第八章 指针第八章 指针教学目的要求:
1、重点掌握指针与指针变量
2、重点掌握并能灵活运用指针作为函数参数
3、了解指针函数和指向函数的指针
4、掌握指针与字符串以及指针数组
5、了解命令行参数
重点·难点:
1、指针与指针变量
2、指针作为函数参数
3、指针函数和指向函数的指针
4、指针与字符串以及指针数组
5、二维数组与多维数组的指针表示法null一、基本数据类型
整型、实型和字符型—单个数据处理。二、构造类型
数组—处理相同数据类型的数据集合。三、指针
是一种特殊的数据类型,通过它可以对
基本类型变量、数组变量等灵活的进行访问。数据类型回顾章节总览 指针是C语言中的一个重要的概念,也是C语言中的一个重要特色。正确灵活的使用指针:章节总览(1) 可以有效的表示复杂的数据结构;(2) 能动态分配内存;(3) 能方便使用字符串;(4) 有效而方便的使用数组;(5) 在调用函数时能得到多于1个的值,
能直接处理内存地址。 地址的概念(1)2.根据内存单元的地址访问内存单元的内容的方式(1)直接访问:
(2)间接访问: 变量的地址存放在另一个变量中
的方式称为“间接访问”方式。
如:i_pointer=&i;一、地址:地址的概念(1)指针变量另一个变量 按变量地址存取变量值的方式称为“直接访问”方式。1.定义:内存的每一个字节有一个编号,这就是地址。指针的概念(1 )指针的概念(1 )指针是存放另一个变量地址的变量
指针也是一种数据类型指针的概念( 2 )二、指针:
1.指针:
2.指针变量:
3.指针和指针变量的关系:
指针的概念( 2 )一个变量的地址称为该变量的“指针”。 如果有一个变量专门用来存放另一变量
的地 址,则它称为“指针变量” (即指针) 。 指针变量的值(指针变量中存 放的值)
是指针(地址)。指针变量(1)一、指针变量的定义和赋值:
1、概述:
(1)指针变量不同于整型变量和其他类型变量,它是用来
专门存放地址的。必须将它定义为“指针类型”。
(2)指针变量的基类型用来指定指针变量所指向的变量
的类型,不可缺少。
pointer_1,pointer_2用来指向整型变量,但不可以用来指向其他类型的变量。指针变量(1)例如: int i , j ;
int *pointer_1 , *pointer_2 ;指针变量(2)2 、定义的一般形式:基类型 *指针变量名
3、赋值:一个指针变量指向另一个变量:
如:pointer_1=&i;
pointer_2=&j;
变量i , j 的地址被分别存放到指针变量pointer_1和pointer_2
中,这样,pointer_1指向了变量i , pointer_2指向了变量j。指针变量(2)注意:定义时, “*”表示该变量的类型为指针类型;
而指针变量的名称为:pointer_1,pointer_2注意:指针变量中只能存放地址(指针),不能将任
何其他非 地址类型的数据赋给一个指针变量。 pointer_1=100; 是非法的。指针变量(3)指针变量(3)二、指针变量的使用:1、 两个有关的运算符:
(1)& 取地址运算符
(2)* 指针运算符(或称“间接访问”运算符),非定义
时出现,用于求指针(地址)所指向的变量。例如: int a , * p; p=&a; *p=3;
& a 为变量 a 的地址
* p 为指针变量p所指向的变量a变量的指针和指向变量
的指针变量总述:
1、变量的指针就是变量的地址。
2、存放变量地址的变量是指针变量,用来指向另一个
变量。
3、为了表示指针变量和它所指向的变量之间的联系,
在程序中非定义时用“*”表示“指向”。
例如:已知:int i , * p; p=&i ;下列两个语句作用相同
(1) i=3; (2)*i_pointer = 3;
变量的指针和指向变量
的指针变量指针变量i_pointer,与普通变量的区别;
*i_pointer是i_pointer所指向的变量
*i_pointer也是一个变量,它和所指向的普通变量是等价的指针变量举例(1)指针变量举例(1)main()
{
int a , b ;
int *pointer_1 , *pointer_2 ;
a=100 ; b=10 ;
pointer_1=&a;
pointer_2=&b;
printf("%d,%d\n", a , b );
printf("%d,%d\n", *pointer_1 , *pointer_2 );
}结果:
100,10
100,10/*把变量a的地址给pointer_1*//*把变量b的地址给pointer_2*/指针变量(4)关于& 和 * 的运算(& 和 * 的优先级相同)
(1)若有&*pointer_1
(2)若有*&a
(3)(*pointer_1) + +指针变量(4)再进行 * 运算,得到 & a 所指向的变量& a*pointer_ia先进行*pointer_i的运算,即为变量a;再进行&运算,即为&a;表达式的值最终为 a 的地址先进行 & a 运算,得到 a 的地址,即pointer_1或 &a;a+ +int a, *pointer_1;
pointer_1= &a;null(1) int *p=&a; (2)*p=a;
A.语句(1)和(2)中的*p含义相同,都表示给指针变量p赋值
B.(1)和(2)语句的执行结果,都是把变量a的地址值赋给指针变量p.
C.(1)在对p进行说明的同时进行初始化,使p指向a;(2)将变量a的值赋给指针变量p
D.(1)在对p进行说明的同时进行初始化,使p指向a;(2)将变量a的值赋给*p例 若已定义int a=5;下面对
(1)、(2)两个语句的正确解释是:答案:D指针变量举例(2)指针变量举例(2)main()
{
int *p1, *p2, *p, a, b;
p1=&a; p2=&b;
scanf("%d,%d",&a,&b);
if(a
q 若为真则表示p在数组中指向的数组元素排列在q所指向的元素之后。
注意:要求p、q为同类型的指针变量指 针 变 量(5)指 针 变 量(5)三、指针变量作为函数参数:
(1) 函数的形参的类型不仅可以是整型、实型、字
符型等数据,还可以是指针类型。
作用:是将一个变量的地址传送到函数中。
(2)函数的类型(返回值的类型)也可以是指针类型指 针 变 量 举 例(3)指 针 变 量 举 例(3)swap(int *p1,int *p2)
{ int temp;
temp=*p1;
*p1=*p2;
*p2=temp; }
main()
{ int a,b;
int *pointer_1,*pointer_2;
scanf("%d,%d",&a,&b);
pointer_1=&a; pointer_2=&b;
if(a方法:
(1)用字符数组存放一个字符串,然后输出该字符串。
main( )
{
char string[]="I love China!”;
printf(“%s\n”,string);
}
/* string是数组名,代表字符数组的首地址 */
字符串和指针(1)字符串和指针(2)(2)用字符指针指向一个字符串。
main( )
{char *string
printf(“%s\n”,string);}
在内存中开辟了一片存储单元来存放字符串常量,定义一个字符指针变量string,并把串首地址赋给这个变量。
注意:
(1)在内存中,字符串的最后被自动加了一个‘\0’,因此
在输出时能确定字符串的终止位置。
(2)通过数组名或字符指针可以直接输出一个字符串,而对数值型数组是不可以的。字符串和指针(2)= ”I love China!” ; 定义形式:类型名 *指针变量名=“字符串”;字 符 数 组 和 字 符 指 针 变 量(1)三、字符数组与字符指针变量都可以实现字符串的存储和运
算,但两者是有区别的:
1、字符数组由若干元素组成,每个元素中存放一个字符,
而字符指针变量中存放的是地址(字符串的首地址)。
2、赋值方式:对字符数组只能对各个元素赋值,而对字符
指针变量赋值时赋予的是字符串的首地址。字 符 数 组 和 字 符 指 针 变 量(1)字 符 数 组 和 字 符 指 针 变 量(2)字 符 数 组 和 字 符 指 针 变 量(2)(2)字符指针赋值:
char *a=”I love China!”;
等价于
char *a;
a=”I love China!”;(1)数组赋值:
char str[14]={“I love China!”};
不能改为 char str[14];str[]=”I love China!”; 数组可在变量定义时整体初始化,但不能在赋值语句中整体赋值。 字 符 数 组 和 字 符 指 针 变 量(3)字 符 数 组 和 字 符 指 针 变 量(3)3、定义一个字符数组时,编译时已经分配了内存单元,有确定的地址。而定义一个字符指针变量,给其分配内存单元,在其中只能存放地址,该指针变量可以指向一个字符型数据,但如果没有给它一个地址值,则它并未具体指向一个确定的字符数据。
例如:char *a; /*此时,指针没有指向任何变量*/
scanf(“%s”,a);
4、指针变量的值是可以改变的。
如:char *p=“I love china”;
printf(“%s”,p+7); 说明:若定义了一个指针变量,并使它指向一个字符串,就可以用下标形式引用指针变量所指向的字符串中的字符null二.用数组名作函数参数 数组名作形参时,接收实参数组的起始地址;作实参时,将数组的起始地址传递给形参数组。
引入指向数组的指针变量后,数组及指向数组的指针变量作函数参数时,可有4种等价形式
(1)形参、实参都用数组名
(2)形参、实参都用指针变量
(3)形参用指针变量、实参用数组名
(4)形参用数组名、实参用指针变量
nullEg:将数组a中n个整数按逆序存放12345678910
void inv(int *a,int n)
{
int t,i;
for(i=0;i<(n-1)/2;i++)
{
t=*(a+i);
*(a+i)=*(a+n-1-i);
*(a+n-1-i)=t;
}
}nullEg:用选择法对10个整数按从大到小的顺序排列指 针 数 组 (1) 指 针 数 组 (1) 一、指针数组的概念:
1、定义:一个数组的各个元素均为指针类型数据,称为指针数组。即指针数组中的每一个元素都相当于一个指针变量。2、一维数组的定义形式:
类型名 *数组名[数组长度] ;
例如:int *p[4] ;
由于[ ]比*优先级高,先有p[4]形式,是数组,有4个元素。再与p 前面的“*”结合,“*”表示此数组是指针类型的,每个数组元素(相当于一个指针变量)都可指向一个 int 型变量。指 针 数 组 (2) 指 针 数 组 (2) 注意:不要写成int(*p)[4],这是指向大小为4的一维数组
的单个指针变量。二、指针数组的运用指 针 数 组 作 main 函 数 的 形 参(1)指 针 数 组 作 main 函 数 的 形 参(1)1、定义形式
例如:
main(argc , argv)
argc , argv :
main函数的形参。main函数是由系统调用的。当处于
操作命令状态下,输入main所在的文件名(经过编译、连接
后得到的可执行文件名),系统就调用main函数。
实际上实参是和命令一起给出的。也就是一个命令行
中包括命令名和需要传给main函数的参数。
2、命令行的一般形式:
命令名 参数1 参数2 ……参数n指 针 数 组 作 main 函 数 的 形 参(2)指 针 数 组 作 main 函 数 的 形 参(2)注意:
(1)命令名和各参数之间用空格分开。
(2)main函数中行参argc是指命令行中参数的个数
(注意: 文件名也作为一个参数)。
(3)main函数的第二个行参argv是一个指向字符串的指针
数组,也就是说,带参数的main函数原型是
main(int argc,char *argv[ ]);
(4)命令行参数应当都是字符串,这些字符串的首地址构
成一个指针数组。指 针 数 组 作 main 函 数 的 形 参(3)指 针 数 组 作 main 函 数 的 形 参(3)3、echo命令:
(1)作用:实现“参数回送”,即将echo后面的各参数(各字
符串)在同一行输出。
(2)例
程序:(
254页)
小结:
利用指针数组作main函数的行参,可以向程序传送命令行参数(这些参数是字符串),这些字符串的长度不可知,而且各参数字符串的长度一般并不相同,命令行参数的数目也是任意的。用指针数组可以较好的满足上述要求。有关指针的数据类型和指针运算的小结 (1) 一、有关指针的数据类型的小结
int I; 定义整型变量I
int *p; p为指向整型数据的指针变量
int a[n]; 定义整型数组a,它有n个元素
int *p[n]; 定义指针数组p,它由n个指向整型数据的指针数
据组成
int (*p)[n]; p为指向含n个元素的一维数组的指针变量
int f(); f为带回整型函数值的函数
int *p(); p为带回一个指针的函数,该指针指向整型数据
int(*p)(); p为指向函数的指针,该函数返回一个整型值
int **p; p是一个指针变量,他指向一个指向整型数据的指
针变量有关指针的数据类型和指针运算的小结 (1) 有关指针的数据类型和指针运算的小结 (2) 有关指针的数据类型和指针运算的小结 (2) 二、指针运算小结
1. 指针变量加(减)一个整数
一个指针变量加(减)一个整数并不是简单的将指针
变量的原值加(减)一个整数,而是将该指针变量的
原值(是一个地址)和它指向的变量所占用的内存单
元字节数相加(减)。
2. 指针变量赋值:将一个变量地址赋给一个指针变量。
注意:不能将一个整数赋给指针变量,同样不能将指针变
量的值(地址)赋给一个整型变量。
有关指针的数据类型和指针运算的小结 (3) 有关指针的数据类型和指针运算的小结 (3) 3.指针变量可以有空值,即该指针变量不指向任何变量,表示为:
p=NULL;
4.两个指针变量可以加减
5.两个指针变量比较
三、void指针类型
void类型的指针,即可以定义一个指针变量,但不指定它
是指向哪一种数据类型。 有关指针的数据类型和指针运算的小结 (4) 有关指针的数据类型和指针运算的小结 (4) 3. 使用scanf函数时应注意的问题:
(1)scanf函数中的“
控制”后面应当是变量地址,而不应是变量名。
(2)如果在“格式控制”字符串中除了格式说明以外还有其他字符,则在输入数据时应输入与这些字符相同的字符。
(3)在用“%c”格式输入时,空格字符和“转义字符”都作为有效字符输入。
(4)在输入数据时,遇以下情况时该数据认为结束。
a.遇空格,或按“回车”或“跳格”(Tab)键。
b.按指定的宽度结束。
c.遇非法输入。null例有若干个学生的成绩(每一个学生有4门功课),要求在用户输入学生序号后,能输出学生的全部成绩。例对上例中的学生,找出其中不及格课程的学生及其学号。 2、例题
:null一、指向数组元素的指针变量
main()
{ int a[3][4] ={ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23 };
int *p;
for(p=a[0];p