Professional Documents
Culture Documents
第十章: C 语言的指针
授课 师习之
湘潭大学物理与光电工程学院
本章内容
1 、指针的定义、引用;
2 、指针与数组、动态数组;
3 、指针作为函数参数;
4 、指针数组与主函数参数;
什么是指针
计算机内存相当于一个巨大的一维数组,以字节为单位。
每个字节的序号,称为内存地址。
运算器
控制器
int b; | | | | | | | | | | | | | | | | | | | | | |
double c; 存储器
float d[2][3];
内 … …
存
地 …
这里
址 int 1000 1004 double 1012
类型占 4 个字节, 1016float 占
占 8 字节, 1020 1024
4 字节。 1028 1032 …
指针:保存内存地址的变量。
C 语言中指针
1 、指针变量的定义: 类型 * 指针名 ;
指针的类型:用于区分地址处所存放的是什么类型的数据。
2 、指针变量的引用: 指针名
对其中保存的地址进行操作:
3 、指针指向的内容的引用:
* 指针 对指针所指向位置的数据进行操作;
名
指针名 [ 偏移 对距离所指向位置一定偏移处的数据进行操作。
量]
4 、指针的运算: +, -, ++, --, +=, -=
指针的加、减法运算,用于改变所指向的位置,进行前后移动。
C 语言中指针
获取可用地址的常用方式:
1 、使用取地址运算符 & 取得已定义的变量的地址:
int a; // 定义变量 a // 也可以简写为:
int *p; // 定义指针变量 p int a, *p=&a;
p=&a; // 令 p 指向变量 a
2 、数组名,不加方括号索引时表示数组的起始地址:
int a[10], *p; // 定义数组 a, 以及指针 p
p=a; // 令指针 p 指向 a 的数组 a 的起始位置。
//p=a; 等价于语句: p=&a[0];
int main()
{
float a=1.23; // 定义变量 a 并赋初始值
float * p; // 定义指针 p
return 0;
}
指针与数组
【 10.2 】演示通过指针访问数组。
#include <stdio.h>
int main()
{
int i, a[5]={1,2,3,4,5}, *p=a; // 指针 p 初始指向 a 的起始位置
*p=123; // 或者: p[0]=123; 等价于 : a[0]=123;
*(p+2)=456; // 或者: p[2]=456; 等价于 : a[2]=456;
p=p+2; // 将 p 的位置向后移动 2 ,即指向 a[2]; 等价于: p=&a[2];
printf("%d\n", *p); // 显示 a[5] 的值 456
for(p=a; p-a<5; p++) // 通过指针 p 遍历数组 a
printf("%d ", *p);
printf("\n");
// 上面的 for 循环又等价于:
for(i=0; i<5; i++)
printf("%d ", a[i]);
return 0;
}
指针与数组
【 10.3 】通过指针操作数组:将字符串中井号 # 及之后的内容删掉。
#include <stdio.h> #include <stdio.h>
#include <string.h>
int main()
{ int main()
char s[10], *p; {
scanf("%s", s); char s[10], *p;
for(p=s; *p != '\0'; p++) scanf("%s", s);
if(*p=='#') if( (p=strchr(s,'#')) !=
break; 0 )
*p='\0'; *p='\0';
printf("%s", s); printf("%s", s);
return 0; return 0;
} }
注意: strchr 用于在字符串中查
注意:字符串通过结束符 '\0' 来标 找一个字符首次出现的位置,返回
记结束的位置。 指向它的指针。如果没找到,则返
回空指针:地址 0 。
动态数组
【 10.4 】使用动态数组:根据输入的大小创建数组,并向其中填入随机数。
#include <stdio.h>
#include <stdlib.h> 注意:
#include <time.h> 1 、 malloc 的参数为要分配的内存
int main() 区域大小,以字节为单位;
{ 2 、 malloc 的返回值为空类型指针
int i, n, *a; void * ,必须用强制类型转换来转
scanf("%d", &n); 换为需要的类型;
a=(int *)malloc(n*sizeof(int)); 3 、用 malloc 获取的内存在不使用
srand(time(0)); 时要用 free 函数释放。
for(i=0;i<n;i++) 4 、对 malloc 的调用有可能会失败
a[i]=rand(); // 对数组 a 赋值 (比如当内存不足),此时返回值等
for(i=0;i<n;i++) 于 0 ,表示空指针;
printf("%d ", a[i]); 5 、还有其他分配内存的函数。比如
free(a); realloc 用于改变已分配的内存区域
return 0; 的大小。
}
指针作为函数参数
函数的参数也可以是指针类型:
函数名 ( 类型 * 参数名 , 等
等 );
通过指针参数,函数可以访问定义在外面的变量。
【 10.5 】设计函数 swap ,交换两个 int 变量中的值。
#include <stdio.h>
2 、在 windows 系统中,可以通过程序快捷
方式的属性对话框指定其运行时参数。
3 、在 windows 系统中,将文件用鼠标拖
到程序文件上松开,则表示以该文件的文
件名(包含路径)为第一个参数来运行该
程序。多数应用程序默认会将第一个参数
作为需要处理的文件进行打开。
主程序参数——程序的命令行参数
C 语言中通过主函数的参数引用程序参数:
int main() // 忽略了参数的主函数
注意:
1 、由于系统规则,所有程序参数均为字符串,所以这里用 sscanf 将其转换为数
字。 2 、 sscanf 与 scanf 功能类似,但不是从键盘、而是从字符串读取数据;
3 、也可以用 C 语言库函数 atof 来将字符串转换为数字,如将 "1.23" 变为
1.23 。
4 、用户运行程序时输入的参数个数或类型可能与代码设计时的可能不一致,会导
致程序出错。所以,一个完善的程序应该在处理参数前对参数格式进行检查!
主程序参数——程序的命令行参数
【例 10.8 】编写一个小程序,通过参数读取一个正整数,计算其阶乘。
#include <stdio.h>
int main(int an, char *ap[])
{
int n, s;
if(an!=2) // 检查参数个数。
{
printf(" 需要一个参数! \n");
return -1; // 程序设计中一般约定:主程序返回非 0 值表示运行时出错
}
if(1 != sscanf(ap[1], "%d", &n) || n<0) // 转换为数字,并检查格式
{ // 如果参数不是一个数字, sscanf 会失败: sscanf 的返回值表示成功读取的个
数。
printf(" 需要一个正整数! \n");
return -2;
}
for(s=1; n>1; n--) // 计算其阶乘
s*=n;
printf("%d\n", s); // 输出结果
return 0; // 返回 0 表示程序成功结束
}
练习题
1 、通过指针来查找数组中的最大值。