对使用字符指针变量和字符数组的讨论:
虽然用字符数组和字符指针变量都能实现字符串的存储和运算,但他们二者之间是有区别的,不应混为一谈。
主要概括下来有以下几点:
1、字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第一个字符的地址)。
2、赋值方式的不同:对字符数组只能对各个元素赋值,不能用这种方法:
char str[20];
str = "I love China!";
而对于字符指针变量,可以采用这种方法:
char *a;
a="I love China!"
但是要注意赋给a的不是字符,而是字符串第一个元素的地址。
3、对字符指针变量赋初值:
char *a="I love China!";
等价于
char *a;
a="I love China!";
而对数组的初始化:
char str[20]={"I love China!"};
不等价于
char str[20];
str[ ]="I love China!";
4、如果定义了一个字符数组,在编译时为它分配内存单元,它有确定的地址。而定义一个字符指针变量时,给指针变量分配内存单元,在其中可以放一个字符变量的地址,也就是说该指针变量可以指向一个字符型数据,但如果未对它赋予一个地址值,则它并未具体指向一个确定的字符数据。
5、指针变量的值是可以改变的。
例如:
#include<stdio.h>
int main()
{
char *a="I love China!";
printf("%s\n",a);
a+=7;
printf("%s\n",a);
}
另外需要说明的是,若定义了一个指针变量,并使他指向了一个字符串,就可以用下标形式引用指针变量所指的字符串中的字符。
例如:
#include<stdio.h>
int main()
{
char *a="I love China!";
int i;
printf("The sixth character is %c\n\n",a[5]);
for(i=0;a[i]!='\0';i++)
{
printf("%c",a[i]);
}
printf("\n");
}
指向函数的指针:
一个函数在编译时被分配给一个入口地址。这个函数的入口地址就称为函数的指针。
例题:比较a和b的大小,求出谁大:
#include<stdio.h>
int main()
{
int max(int ,int );
int (*p)(int ,int ); //指向函数的指针
int a,b,c;
p=max;
scanf("%d%d",&a,&b);
c=(*p)(a,b);
printf("a = %d, b = %d, max = %d\n\n",a,b,c);
}
int max(int x,int y)
{
int z;
if(x>y)
{
z=x;
}
else
{
z=y;
}
return z;
}
指向函数的指针也可以作为参数,用来实现函数地址的传递。
例如:
f1 f2
void sub(int(*x1)(int),int(*x2)(int,int))
{ int a,b,i,j;
a=(*x1)(i);
b=(*x2)(i,j);
......
}
它的原理可以简述如下:有一个函数名为sub,它有两个形参(x1和x2),定义x1和x2为指向函数的指针变量。在调用函数sub时,实参为两个函数名f1和f2,给形参传递的地函数f1和f2的地址。这样在函数sub中就可以调用f1和f2函数了。
一个函数可以带回一个整型值、字符值、实型值等,也可以带回指针型的数据,即地址。
这种带回指针值的函数,一般定义为: 类型名 *函数名(参数表列); 例如: int *a(int x,int y);
例题:有若干个学生的成绩(每个学生有4门课程),要求在用户输入学生序号以后,能输出该学生的全部成绩,用指针函数实现。
#include<stdio.h>
int main()
{
double score[][4]={{60.0,70.0,80.5,90.5},{56.0,89.0,67.0,88.0},{34.2,70.5,90.0,87.5}};
double *search(double (*pointer)[4],int n);
double *p;
int i,m;
printf("Please enter the number of student: ");
scanf("%d",&m);
printf("The scores of No.%d are:\n",m);
p=search(score,m);
for(i=0;i<4;i++)
{
printf("%5.2lf\t",*(p+i));
}
printf("\n\n\n");
}
double *search(double(*pointer)[4],int n)
{
double *pt;
pt=*(pointer+n);
return pt;
}
指针函数和函数指针的区别:
指针函数是指带指针的函数,即本质是一个函数;
函数指针是指向函数的指针变量,因而函数指针本身首先应该是指针变量,只不过该指针变量指向函数。
指针数组的定义:
类型名 *数组名[数组长度]; 例如: int *name[4];
例题:
#include<stdio.h>
int main()
{
int a[5]={1,3,5,7,9};
int *name[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};
int i;
for(i=0;i<5;i++)
{
printf("%d ",*name[i]);
}
printf("\n");
}
例题:将下面的字符串按首字母排列顺序(由小到大)输出。
char *name[]={"I love China","It is what it is","Sherlock Holmes","fuck you","who are you"};
#include<stdio.h>
#include<string.h>
int main()
{
void sort(char *name[],int n); //排序函数
void print(char *name[],int n); //打印函数
char *name[]={"I love China","who are you","Sherlock Holmes","It is what it is"};
int n=4;
sort(name,n);
print(name,n);
}
void sort(char *name[],int n)
{
char *temp;
int i,j,k;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
{
if(strcmp(name[k],name[j])>0)
{
k=j;
}
if(k!=i)
{
temp=name[i];
name[i]=name[k];
name[k]=temp;
}
}
}
}
void print(char *name[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("%s\n",name[i]);
}
}
指向指针的指针:
定义如: char **p;
p的前面有两个*。*运算符的结合性是从右到左,因此**p相当于*(*p)。
例题:打印字符串:
#include<stdio.h>
int main()
{
char *name[]={"I love China","who are you","Sherlock Holmes","It is what it is"};
char **p;
int i;
for(i=0;i<4;i++)
{
p=name+i;
printf("%s\n",*p);
}
}
指针数组作main函数的形参:
指针数组的一个重要应用是作为main函数的形参。例如:int main(int argc,char *argv[])
argc和argv就是main函数的形参。
main函数是由操作系统调用的,实际上实参是和命令一起给出的,也就是在一个命令行中包括命令名和需要传给main函数的参数。
命令行的一般形式为: 命令名 参数4 参数2......参数n
例题:
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{
int i;
printf("the number of string is:%d\n",argc-1);
for(i=1;i<argc;i++)
{
printf("the string %d is:%s\n",i,argv[i]);
}
}
有关指针的数据类型的小结:
指针运算小结:
指针变量加(减)一个整数就是指向下一个(上一个)元素。
指针变量赋值:
p=&a;(将变量a的地址赋给p)
p=array;(将数组array首元素地址赋给p)
p=&array[i];(将数组array第i个元素的地址赋给p)
p=max;(max为已定义的函数,将max的入口地址赋给p,也就是指向函数的指针)
p1=p2;(p1和p2都是指针变量,将p2的值赋给p1)
指针变量可以有空值,即该指针变量不指向任何变量,可以这样表示:p=NULL;
两个指针变量可以相减,如果两个指针变量都指向同一个数组中的元素,则两个指针变量值之差是两个指针之间的元素个数。
若两个指针指向同一个数组的元素,则可以进行比较。指向前面的元素的指针变量“小于”指向后面元素的指针变量。
关于void类型:
void真正发挥的作用在于:对函数返回的限定,对函数参数的限定。
例如:void abc(void);
void指针和const指针:
ANSI C新标准增加了一种“void”指针类型,即不指定它是指向哪一种类型数据的指针变量。
例如:void *p;
表示指针变量p不指向一个确定的类型数据,它的作用仅仅是用来存放一个地址。
void指针它可以指向任何类型数据,也就是说,可以用任何类型的指针直接给void指针赋值。单数,如果需要将void指针的值赋给其他类型的指针,则需要进行强制类型转换。
谈谈const:
#include<stdio.h>
int main(void)
{
const char *str = "aaa";//声明指针变量,指向一个字符型常量,初始化str为指向字符串
printf("\n%s\n",str);
#if(0)
str[0]='w'; //这条语句是错误的,但可以改变str的值
#endif
str="bbb\n";
printf("\n%s",str);
}
下面这个代码语法没有错误,由于在Windows下编译,禁止常量被重写,所以不能运行。
#include<stdio.h>
int main(void)
{
char * const str = "aaa";//常量指针是一个固定的指针,不可以改变它的值
str[0]='w';
#if(0)
str="bbb"; //非法
#endif
printf("\n%s",str);
}
#include<stdio.h>
int main(void)
{
const char * const str = "aaa";
//str[0]='w';//非法
//str="bbb"; //非法
printf("\n%s\n",str);
}