谭浩强C语言-10
10 指针
10.1 地址指针的基本概念
在计算机中,所有的数据都是存放在存储器中的。一般把存储器中的一个字节称为一个内存单元,不同的数据类型所占用的内存单元数不等,如整型量占
图中,设有字符变量C,其内容为
严格地说,一个指针是一个地址,是一个常量。而一个指针变量却可以被赋予不同的指针值,是变量。但常把指针变量简称为指针。为了避免混淆,我们中约定:“指针”是指地址,是常量,“指针变量”是指取值为地址的变量。定义指针的目的是为了通过指针去访问内存单元。
10.2 变量的指针和指向变量的指针变量
变量的
为了表示指针变量和它所指向的变量之间的关系,在程序中用“
因此,下面两个语句作用相同:
i=3;
*i_pointer=3;
第二个语句的含义是将3赋给指针变量
10.2.1 定义一个指针变量
对指针变量的定义包括三个内容:
(1)
(2)
(3)
其一般形式为:
其中,*表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。
例如:
表示p1是一个指针变量,它的值是某个整型变量的地址。或者说
再如:
int *p2;
char*p4; /*p4是指向字符变量的指针变量*/
应该注意的是,一个指针变量只能指向同类型的变量,如
10.2.2 指针变量的引用
指针变量同普通变量一样,使用之前不仅要定义说明,而且必须赋予具体的值。未经赋值的指针变量不能使用,否则将造成系统混乱,甚至死机。指针变量的赋值只能赋予地址,决不能赋予任何其它数据,否则将引起错误。在C语言中,变量的地址是由编译系统分配的,对用户完全透明,用户不知道变量的具体地址。
两个有关的运算符:
1)
2)
C语言中提供了地址运算符&来表示变量的地址。
其一般形式为:
如&a表示变量
设有指向整型变量的指针变量p,如要把整型变量
(1)
(2)
p=&a;
不允许把一个数赋予指针变量,故下面的赋值是错误的:
int *p;
p=1000;
被赋值的指针变量前不能再加“
假设:
int i=200, x;
int *ip;
我们定义了两个整型变量i,x,还定义了一个指向整型数的指针变量
ip=&i;
此时指针变量ip指向整型变量
以后我们便可以通过指针变量
x=*ip;
运算符*访问以
x=i;
另外,指针变量和一般变量一样
inti,j,*p1,*p2;
i='a';
j='b';
p1=&i;
p2=&j;
则建立如下图所示的联系:
这时赋值表达式:
p2=p1
就使p2与
如果执行如下表达式:
则表示把p1指向的内容赋给
通过指针访问它所指向的一个变量是以间接访问的形式进行的
指针变量可出现在表达式中,设
int x,y,
指针变量px指向整数
y=*px+5;
y=++*px;
y=*px++;
【例10.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);
}
对程序的说明:
1)
2)
3)
4)
请对下面再的关于“&”和“
1)
2)
3)
【例10.2】输入a和
main()
{ int *p1,*p2,*p,a,b;
scanf("%d,%d",&a,&b);
p1=&a;p2=&b;
if(a<b)
printf("\na=%d,b=%d\n",a,b);
printf("max=%d,min=%d\n",*p1, *p2);
}
10.2.3 指针变量作为函数参数
函数的参数不仅可以是整型、实型、字符型等数据,还可以是指针类型。它的作用是将一个变量的地址传送到另一个函数中。
【例10.3】题目同例10.2,即输入的两个整数按大小顺序输出。今用函数处理,而且用指针类型的数据作函数参数。
swap(int *p1,int *p2)
{int temp;
}
main()
{
int a,b;
int*pointer_1,*pointer_2;
scanf("%d,%d",&a,&b);
pointer_1=&a;pointer_2=&b;
if(a<b) swap(pointer_1,pointer_2);
printf("\n%d,%d\n",a,b);
}
对程序的说明:
swap是用户定义的函数,它的作用是交换两个变量(
接着执行if语句,由于a〈
接着执行执行swap函数的函数体使
函数调用结束后,p1和
最后在main函数中输出的
请注意交换*p1和
swap(int *p1,int *p2)
{int *temp;
}
请考虑下面的函数能否实现实现a和b互换。
swap(int x,int y)
{int temp;
}
如果在main函数中用
【例10.4】请注意,不能企图通过改变指针形参的值而使指针实参的值改变。
swap(int *p1,int *p2)
{int *p;
}
main()
{
int a,b;
int *pointer_1,*pointer_2;
scanf("%d,%d",&a,&b);
pointer_1=&a;pointer_2=&b;
if(a<b) swap(pointer_1,pointer_2);
printf("\n%d,%d\n",*pointer_1,*pointer_2);
}
其中的问题在于不能实现如图所示的第四步(d)。
【例10.5】输入a、
swap(int *pt1,int *pt2)
{int temp;
}
exchange(int *q1,int *q2,int *q3)
{ if(*q1<*q2)swap(q1,q2);
if(*q1<*q3)swap(q1,q3);
if(*q2<*q3)swap(q2,q3);
}
main()
{
inta,b,c,*p1,*p2,*p3;
scanf("%d,%d,%d",&a,&b,&c);
p1=&a;p2=&b; p3=&c;
exchange(p1,p2,p3);
printf("\n%d,%d,%d \n",a,b,c);
}
10.2.4 指针变量几个问题的进一步说明
指针变量可以进行某些运算,但其运算的种类是有限的。它只能进行赋值运算和部分算术运算及关系运算。
1.
1)
2)
需要注意的是指针运算符*和指针变量说明中的指针说明符
【例10.6】
main(){
int a=5,*p=&a;
printf ("%d",*p);
}
2.
1)
①
②
例如:
③
如:
由于
④
例如:
也可写为:
当然也可采取初始化赋值的方法:
⑤
例如:
或用初始化赋值的方法写为:
这里应说明的是并不是把整个字符串装入指针变量,而是把存放该字符串的字符数组的首地址装入指针变量。在后面还将详细介绍。
⑥
例如:
2)
pa=pa+2;
指针变量的加减运算只能对数组指针变量进行,对指向其它类型变量的指针变量作加减运算是毫无意义的。
3)
①
②
例如:
pf1==pf2表示
pf1>pf2表示
pf1<pf2表示
指针变量还可以与0比较。
设p为指针变量,则
p!=0表示
空指针是由对指针变量赋予0值而得到的。
例如:
对指针变量赋
【例10.7】
main(){
int a=10,b=20,s,t,*pa,*pb; /*说明pa,pb为整型指针变量
pa=&a;
pb=&b;
s=*pa+*pb;
t=*pa**pb;
printf("a=%d\nb=%d\na+b=%d\na*b=%d\n",a,b,a+b,a*b);
printf("s=%d\nt=%d\n",s,t);
}
【例10.8】
main(){
int a,b,c,*pmax,*pmin;
printf("input three numbers:\n");
scanf("%d%d%d",&a,&b,&c);
if(a>b){
else{
if(c>*pmax) pmax=&c;
if(c<*pmin) pmin=&c;
}
10.3 数组指针和指向数组的指针变量
一个变量有一个地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。所谓数组的指针是指数组的起始地址,数组元素的指针是数组元素的地址。
10.3.1 指向数组元素的指针
一个数组是由连续的一块内存单元组成的。数组名就是这块连续内存单元的首地址。一个数组也是由各个数组元素
定义一个指向数组元素的指针变量的方法,与以前介绍的指针变量相同。
例如:
int *p;
应当注意,因为数组为int型,所以指针变量也应为指向
p=&a[0];
把a[0]元素的地址赋给指针变量p。也就是说,
C语言规定,数组名代表数组的首地址,也就是第
p=&a[0];
p=a;
在定义指针变量时可以赋给初值:
int*p=&a[0];
它等效于:
int *p;
p=&a[0];
当然定义时也可以写成:
从图中我们可以看出有以下关系:
数组指针变量说明的一般形式为:
类型说明符 *指针变量名;
其中类型说明符表示所指数组的类型。从一般形式可以看出指向数组的指针变量和指向普通变量的指针变量的说明是相同的。
10.3.2 通过指针引用数组元素
C语言规定:如果指针变量
引入指针变量后,就可以用两种方法来访问数组元素了。
如果p的初值为
1)
2)
3)
根据以上叙述,引用一个数组元素可以用:
1)
2)
【例10.9】输出数组中的全部元素。(下标法)
main(){
int a[10],i;
for(i=0;i<10;i++)
for(i=0;i<5;i++)
}
【例10.10】输出数组中的全部元素。(通过数组名计算元素的地址,找出元素的值)
main(){
int a[10],i;
for(i=0;i<10;i++)
for(i=0;i<10;i++)
}
【例10.11】输出数组中的全部元素。(用指针变量指向元素)
main(){
int a[10],I,*p;
p=a;
for(i=0;i<10;i++)
for(i=0;i<10;i++)
}
【例10.12】
main(){
int a[10],i,*p=a;
for(i=0;i<10;){
}
}
几个注意的问题:
1)
2)
【例10.13】找出错误。
main(){
int *p,i,a[10];
p=a;
for(i=0;i<10;i++)
for(i=0;i<10;i++)
}
【例10.14】改正。
main(){
int *p,i,a[10];
p=a;
for(i=0;i<10;i++)
*p++=i;
p=a;
for(i=0;i<10;i++)
}
3)
4)
5)
6)
7)
*(p--)相当于
*(++p)相当于
*(--p)相当于
10.3.3 数组名作函数参数
数组名可以作函数的实参和形参。如:
main()
{intarray[10];
……
}
f(intarr[],int n);
……
}
array为实参数组名,
【例10.15】
float aver(float *pa);
main(){
float sco[5],av,*sp;
int i;
sp=sco;
printf("\ninput 5 scores:\n");
for(i=0;i<5;i++) scanf("%f",&sco[i]);
av=aver(sp);
printf("average score is %5.2f",av);
}
float aver(float *pa)
{
int i;
float av,s=0;
for(i=0;i<5;i++) s=s+*pa++;
av=s/5;
return av;
}
【例10.16】将数组a中的
算法为:将a[0]与
程序如下:
void inv(int x[],int n) /*形参
{
int temp,i,j,m=(n-1)/2;
for(i=0;i<=m;i++)
{j=n-1-i;
temp=x[i];x[i]=x[j];x[j]=temp;}
return;
}
main()
{int i,a[10]={3,7,9,11,0,6,7,5,4,2};
printf("The originalarray:\n");
for(i=0;i<10;i++)
printf("%d,",a[i]);
printf("\n");
inv(a,10);
printf("The array has benninverted:\n");
for(i=0;i<10;i++)
printf("%d,",a[i]);
printf("\n");
}
对此程序可以作一些改动。将函数inv中的形参
【例10.17】对例10.16可以作一些改动。将函数
程序如下:
void inv(int *x,int n) /*形参
{
int *p,temp,*i,*j,m=(n-1)/2;
i=x;j=x+n-1;p=x+m;
for(;i<=p;i++,j--)
{temp=*i;*i=*j;*j=temp;}
return;
}
main()
{int i,a[10]={3,7,9,11,0,6,7,5,4,2};
printf("The originalarray:\n");
for(i=0;i<10;i++)
printf("%d,",a[i]);
printf("\n");
inv(a,10);
printf("The array hasbenn inverted:\n");
for(i=0;i<10;i++)
printf("%d,",a[i]);
printf("\n");
}
运行情况与前一程序相同。
【例10.18】从0个数中找出其中最大值和最小值。
调用一个函数只能得到一个返回值,今用全局变量在函数之间“传递”数据。程序如下:
int max,min;
void max_min_value(int array[],int n)
{int *p,*array_end;
else if (*p<min)min=*p;
}
main()
{int i,number[10];
说明:
1) 在函数max_min_value中求出的最大值和最小值放在
2) 函数max_min_value
max=min=*array;
array是数组名,它接收从实参传来的数组
*array相当于
3) 在执行
4) 函数max_min_value
【例10.19】程序可改为:
int max,min;
void max_min_value(int *array,int n)
{int *p,*array_end;
}
main()
{int i,number[10],*p;
归纳起来,如果有一个实参数组,想在函数中改变此数组的元素的值,实参与形参的对应关系有以下4种:
1) 形参和实参都是数组名。
main()
{int a[10];
f(intx[],int n)
{
}
}
a和x指的是同一组数组。
2) 实用数组,形参用指针变量。
main()
{int a[10];
f(int*x,int n)
{
}
}
3) 实参、型参都用指针变量。
4) 实参为指针变量,型参为数组名。
【例10.20】用实参指针变量改写将
void inv(int *x,int n)
{int *p,m,temp,*i,*j;
m=(n-1)/2;
i=x;j=x+n-1;p=x+m;
for(;i<=p;i++,j--)
{temp=*i;*i=*j;*j=temp;}
return;
}
main()
{int i,arr[10]={3,7,9,11,0,6,7,5,4,2},*p;
p=arr;
printf("The originalarray:\n");
for(i=0;i<10;i++,p++)
printf("%d,",*p);
printf("\n");
p=arr;
inv(p,10);
printf("The array hasbenn inverted:\n");
for(p=arr;p<arr+10;p++)
printf("%d,",*p);
printf("\n");
}
注意:main函数中的指针变量p是有确定值的。即如果用指针变作实参,必须现使指针变量有确定值,指向一个已定义的数组。
【例10.21】用选择法对10个整数排序。
main()
{int *p,i,a[10]={3,7,9,11,0,6,7,5,4,2};
printf("The originalarray:\n");
for(i=0;i<10;i++)
printf("%d,",a[i]);
printf("\n");
p=a;
sort(p,10);
for(p=a,i=0;i<10;i++)
{printf("%d
printf("\n");
}
sort(int x[],int n)
{int i,j,k,t;
for(i=0;i<n-1;i++)
{k=i;
for(j=i+1;j<n;j++)
if(x[j]>x[k])k=j;
if(k!=i)
{t=x[i];x[i]=x[k];x[k]=t;}
}
}
说明:函数sort用数组名作为形参,也可改为用指针变量,这时函数的首部可以改为:
sort(int *x,int n) 其他可一律不改。
10.3.4 指向多维数组的指针和指针变量
本小节以二维数组为例介绍多维数组的指针变量。
1.
设有整型二维数组a[3][4]如下:
0
8
它的定义为:
inta[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}}
设数组a的首地址为
前面介绍过,C语言允许把一个二维数组分解为多个一维数组来处理。因此数组
例如a[0]数组,含有
数组及数组元素的地址表示如下:
从二维数组的角度来看,a是二维数组名,
a[0]是第一个一维数组的数组名和首地址,因此也为
同理,a+1是二维数组
由此可得出:a+i,
此外,&a[i]和
另外,a[0]也可以看成是
由a[i]=*(a+i)得
【例10.22】
main(){
inta[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
printf("%d,",a);
printf("%d,",*a);
printf("%d,",a[0]);
printf("%d,",&a[0]);
printf("%d\n",&a[0][0]);
printf("%d,",a+1);
printf("%d,",*(a+1));
printf("%d,",a[1]);
printf("%d,",&a[1]);
printf("%d\n",&a[1][0]);
printf("%d,",a+2);
printf("%d,",*(a+2));
printf("%d,",a[2]);
printf("%d,",&a[2]);
printf("%d\n",&a[2][0]);
printf("%d,",a[1]+1);
printf("%d\n",*(a+1)+1);
printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1));
}
2.
把二维数组a分解为一维数组
它表示p是一个指针变量,它指向包含
二维数组指针变量说明的一般形式为:
类型说明符 (*指针变量名)[长度]
其中“类型说明符”为所指数组的数据类型。“*
【例10.23】
main(){
inta[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
int(*p)[4];
int i,j;
p=a;
for(i=0;i<3;i++)
{for(j=0;j<4;j++)printf("%2d ",*(*(p+i)+j));
printf("\n");}
}
10.4 字符串的指针指向字符串的针指变量
10.4.1 字符串的表示形式
在C
1) 用字符数组存放一个字符串,然后输出该字符串。
【例10.24】
main(){
char string[]=”
printf("%s\n",string);
}
说明:和前面介绍的数组属性一样,
2) 用字符串指针指向一个字符串。
【例10.25】
main(){
char *string=”
printf("%s\n",string);
}
字符串指针变量的定义说明与指向字符变量的指针变量说明是相同的。只能按对指针变量的赋值不同来区别。对指向字符变量的指针变量应赋予该字符变量的地址。
如:
表示p是一个指向字符变量
而:
则表示s是一个指向字符串的指针变量。把字符串的首地址赋予
上例中,首先定义string是一个字符指针变量,然后把字符串的首地址赋予
char*ps="C Language";
等效于:
char *ps;
ps="CLanguage";
【例10.26】输出字符串中n个字符后的所有字符。
main(){
char *ps="this is a book";
int n=10;
ps=ps+n;
printf("%s\n",ps);
}
运行结果为:
book
在程序中对ps初始化时,即把字符串首地址赋予
【例10.27】在输入的字符串中查找有无
main(){
char st[20],*ps;
int i;
printf("input a string:\n");
ps=st;
scanf("%s",ps);
for(i=0;ps[i]!='\0';i++)
if(ps[i]=='\0') printf("There is no 'k' in the string\n");
}
【例10.28】本例是将指针变量指向一个格式字符串,用在
main(){
static int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
char *PF;
PF="%d,%d,%d,%d,%d\n";
printf(PF,a,*a,a[0],&a[0],&a[0][0]);
printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]);
printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]);
printf("%d,%d\n",a[1]+1,*(a+1)+1);
printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1));
}
【例10.29】本例是把字符串指针作为函数参数的使用。要求把一个字符串的内容复制到另一个字符串中,并且不能使用
cpystr(char *pss,char *pds){
while((*pds=*pss)!='\0'){
main(){
char *pa="CHINA",b[10],*pb;
pb=b;
cpystr(pa,pb);
printf("string a=%s\nstring b=%s\n",pa,pb);
}
在本例中,程序完成了两项工作:一是把
{while(*pdss++=*pss++);}
表达式的意义可解释为,源字符向目标字符赋值,移动指针,若所赋值为非
【例10.30】简化后的程序如下所示。
cpystr(char *pss,char *pds){
}
main(){
char *pa="CHINA",b[10],*pb;
pb=b;
cpystr(pa,pb);
printf("string a=%s\nstring b=%s\n",pa,pb);
}
10.4.2 使用字符串指针变量与字符数组的区别
1.
2.
可以写为:
ps="CLanguage";
而对数组方式:
不能写为:
而只能对字符数组的各元素逐个赋值。
前面说过,当一个指针变量在未取得确定地址前使用是危险的,容易引起错误。但是对指针变量直接赋值是可以的。因为
因此,
或者
都是合法的。
10.5 函数指针变量
函数指针变量定义的一般形式为:
类型说明符 (*指针变量名)();
其中“类型说明符”表示被指函数的返回值的类型。“(* 指针变量名
例如:
表示pf是一个指向函数入口的指针变量,该函数的返回值
【例10.31】本例用来说明用指针形式实现对函数调用的方法。
int max(int a,int b){
if(a>b)return a;
else return b;
}
main(){
int max(int a,int b);
int(*pmax)();
int x,y,z;
pmax=max;
printf("input two numbers:\n");
scanf("%d%d",&x,&y);
z=(*pmax)(x,y);
printf("maxmum=%d",z);
}
1)
2)
3)
4)
使用函数指针变量还应注意以下两点:
a)
b)
10.6 指针型函数
定义指针型函数的一般形式为:
{
}
其中函数名之前加了“*”号表明这是一个指针型函数,即返回值是一个指针。类型说明符表示了返回的指针值所指向的数据类型。
如:
}
表示ap是一个返回指针值的指针型函数,它返回的指针指向一个整型变量。
【例10.32】本程序是通过指针函数,输入一个
main(){
int i;
char *day_name(int n);
printf("input Day No:\n");
scanf("%d",&i);
if(i<0) exit(1);
printf("Day No:%2d-->%s\n",i,day_name(i));
}
char *day_name(int n){
static char *name[]={ "Illegal day",
return((n<1||n>7) ? name[0] : name[n]);
}
本例中定义了一个指针型函数day_name,它的返回值指向一个字符串。该函数中定义了一个静态指针数组
应该特别注意的是函数指针变量和指针型函数这两者在写法和意义上的区别。如
int (*p)()是一个变量说明,说明
int *p()则不是变量说明而是函数说明,说明
对于指针型函数定义,int*p()只是函数头部分,一般还应该有函数体部分。
10.7 指针数组和指向指针的指针
10.7.1 指针数组的概念
指针数组说明的一般形式为:
其中类型说明符为指针值所指向的变量的类型。
例如:
int *pa[3]
表示pa是一个指针数组,它有三个数组元素,每个元素值都是一个指针,指向整型变量。
main(){
inta[3][3]={1,2,3,4,5,6,7,8,9};
int*pa[3]={a[0],a[1],a[2]};
int *p=a[0];
int i;
for(i=0;i<3;i++)
for(i=0;i<3;i++)
}
本例程序中,pa是一个指针数组,三个元素分别指向二维数组
应该注意指针数组和二维数组指针变量的区别。这两者虽然都可用来表示二维数组,但是其表示方法和意义是不同的。
二维数组指针变量是单个的变量,其一般形式中
例如:
表示一个指向二维数组的指针变量。该二维数组的列数为
表示p是一个指针数组,有三个下标变量
指针数组也常用来表示一组字符串,这时指针数组的每个元素被赋予一个字符串的首地址。指向字符串的指针数组的初始化更为简单。例如在例
指针数组也可以用作函数参数。
【例10.34】指针数组作指针型函数的参数。在本例主函数中,定义了一个指针数组
main(){
static char *name[]={ "Illegal day",
char *ps;
int i;
char *day_name(char *name[],int n);
printf("input Day No:\n");
scanf("%d",&i);
if(i<0) exit(1);
ps=day_name(name,i);
printf("Day No:%2d-->%s\n",i,ps);
}
char *day_name(char *name[],int n)
{
char *pp1,*pp2;
pp1=*name;
pp2=*(name+n);
return((n<1||n>7)? pp1:pp2);
}
【例10.35】输入5个国名并按字母顺序排列后输出。现编程如下:
#include"string.h"
main(){
void sort(char *name[],int n);
void print(char *name[],int n);
static char *name[]={"CHINA","AMERICA","AUSTRALIA",
int n=5;
sort(name,n);
}
void sort(char *name[],int n){
char *pt;
int i,j,k;
for(i=0;i<n-1;i++){
}
}
void print(char *name[],int n){
int i;
for (i=0;i<n;i++) printf("%s\n",name[i]);
}
说明:
在以前的例子中采用了普通的排序方法,逐个比较之后交换字符串的位置。交换字符串的物理位置是通过字符串复制函数完成的。反复的交换将使程序执行的速度很慢,同时由于各字符串
本程序定义了两个函数,一个名为
10.7.2 指向指针的指针
在前面已经介绍过,通过指针访问变量称为间接访问。由于指针变量直接指向变量,所以称为“单级间址”。而如果通过指向指针的指针变量来访问变量则构成“二级间址”。
从下图可以看到,
怎样定义一个指向指针型数据的指针变量呢?如下:
p前面有两个*号
从下图可以看到,
如果有:
p=name+2;
printf(
printf(
则,第一个printf函数语句输出
【例10.36】使用指向指针的指针。
main()
{char *name[]={"Follow me","BASIC","GreatWall","FORTRAN","Computer desighn"};
char **p;
int i;
for(i=0;i<5;i++)
{p=name+i;
printf("%s\n",*p);
}
}
说明:
p是指向指针的指针变量。
【例10.37】一个指针数组的元素指向数据的简单例子。
main()
{static int a[5]={1,3,5,7,9};
int*num[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};
int **p,i;
p=num;
for(i=0;i<5;i++)
{printf("%d\t",**p);p++;}
}
说明:
10.7.3 main函数的参数
前面介绍的main函数都是不带参数的。因此
C语言还规定argc(第一个形参)必须是整型变量
DOS提示符下命令行的一般形式为:
例如有命令行为:
由于文件名E24本身也算一个参数,所以共有
【例10.38】
main(int argc,char *argv){
while(argc-->1)
}
本例是显示命令行中输入的参数。如果上例的可执行文件名为
则运行结果为:
BASIC
foxpro
FORTRAN
该行共有4个参数,执行
10.8 有关指针的数据类型和指针运算的小结
10.8.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是一个指针变量,它指向一个指向整型数据的指针变量 |
10.8.2 指针运算的小结
现把全部指针运算列出如下:
1) 指针变量加(减)一个整数:
例如:p++
一个指针变量加(减)一个整数并不是简单地将原值加(减)一个整数,而是将该指针变量的原值(是一个地址)和它指向的变量所占用的内存单元字节数加(减)。
2) 指针变量赋值:将一个变量的地址赋给一个指针变量。
p=&a;
p=array;
p=&array[i];
p=max;
p1=p2;
注意:不能如下:
p=1000;
3) 指针变量可以有空值,即该指针变量不指向任何变量:
p=NULL;
4) 两个指针变量可以相减:如果两个指针变量指向同一个数组的元素,则两个指针变量值之差是两个指针之间的元素个数。
5) 两个指针变量比较:如果两个指针变量指向同一个数组的元素,则两个指针变量可以进行比较。指向前面的元素的指针变量“小于”指向后面的元素的指针变量。
10.8.3 void指针类型
ANSI新标准增加了一种“
文章来自 : 谭浩强C语言-10

浙公网安备 33010602011771号