7.1、指针变量的定义和引用:
指针变量的定义: 基类型 *指针变量名;
例如: int =2,*pa =&a;
#include <stdio.h>
int main(){
int a=2;
int *pa;
pa=&a;
printf("指针变量a的值为:%d",*pa);//指针变量的引用。
return 0;
}
格式说明:
(1)、 *是指针类型标志符。指针变量定义时必须在变量名前面加上 " * ";
定义指针变量时 * 前后可以加空格也可以不加空格
int *ptr; // 不加空格
int* ptr2; // 加了空格
(2)、基类型是指针变量所指向的变量的类型。比如上面指针变量pa的基类型是int,指向int类型的变量,给它赋值也只能是int类型。
(3)、定义指针变量后,可以将另一变量的地址赋给它,使之指向改变量。例如pa=&a;也可以将另一指针变量的值赋给它,例如pb=pa;这样是的pb和pa两个指针变量都指向变量a。
(4)、在定义指针变量的时候可以同时给它赋初值,称为指针变量的初始化。例如:int a=2, *pa=&a;
指针变量赋值需要注意:
(1)、对指针变量赋值时,另一变量的类型必须和指针变量的类型相同。
例如下面是错误的: int *pa; float f; pa=&f; //指针变量的基类型是int,它只能指向int 类型变量,不能指向float 类型变量。
(2)、指针变量中只能存放地址(地址也称为指针),不能将整数或其他非地址类型的数据赋给指针变量。例如 pa =1000; 是错误的。
(3)、给指针变量赋值时,变量名前不能加 " * " 。例如 * p =&a;
例子: 前面函数部分我们知道函数参数传递分为传递地址和传递参数,如果调用函数是传递的是变量的值,则称为传值调用。 由于swap()函数的形参为指针变量,因此该函数必须传递地址。这种也是传递调用。
#include <stdio.h>
void swap(int *pa,int *pb);
int main(){
int a=2;
int* pa;
pa=&a;
printf("指针变量a的值为:%d\n",*pa);
puts("");
int m=3,n=5,*pm=&m,*pn=&n;
swap(pm,pn);
return 0;
}
void swap(int *pa,int *pb){
printf("交换前指针变量pa的值为:%d,pb的值为:%d\n",*pa,*pb);
int tmp=0;
tmp = *pa;
*pa =*pb;
*pb=tmp;
printf("交换后指针变量pa的值为:%d,pb的值为:%d\n",*pa,*pb);
}
指针变量a的值为:2
交换前指针变量pa的值为:3,pb的值为:5
交换后指针变量pa的值为:5,pb的值为:3
7.2、指向一维数组的指针
通常数组变量名代表数组的第一个元素的地址,比如a,a是地址常量,不能对其进行赋值。
a=a+1;或者a++;都是错误的,因为赋值语句左侧必须为变量。
printf("*************指向一维数组的指针:************************\n");
int b[]={1,2,3,5,7,8,22,6};
int *p=&b[0];
int *p_1;
p_1=&b[5];
printf("指针变量p=%d,p_1=%d\n",*p,*p_1);
*************指向一维数组的指针:************************
指针变量p=1,p_1=8
指针变量存放的是地址,由于这一特点,指针变量的运算不同于普通变量,它只允许进行有限的几种运算。除了取地址运算符 " & " ,取内容运算符 " * " ,和赋值运算符 " = ",C语言还允许对指针变量进行算术运算和关系运算。
1、加减整数运算:
例如 int a[10] , * p ;
p =a;
p= p+9;
指针变量加上或者减去一个整数,实际上就是将这个指针变量从当前位置向前或者向后移动i个元素。
注意:p+1并不是将p的值(即地址)简单的加i,而是将p的值加上sizeof(p的基类型)*i。 这里可以看到int 的基类型 +1 实际上是地址+4
printf("指针变量p=%d,p的地址是=%d,p+1=%d\n",*p,p,p+1);
指针变量的直接运算指针变量p=1,p的地址是=6421952,p+1=6421956
2、自增自减运算
p++或者p-- 作用是使指针变量指向当前位置的上一个存储单元。
3、两个指针变量相减
两个指针变量相减,其差等于两个指针变量所指向的存储单元之间的元素之和。
#include <stdio.h>
void main(){
int i=0,a[6]={1,2,3,4,5,6},*p=a;//a即数组首元素地址,*p定义的时候马上赋值可以写*p=&a[0];
puts("通过数组下标访问数组:");
for (; i < 6; i++) {
printf("%d ",a[i]);
}
puts("");
puts("通过数组名访问数组:");
for(int i=0; i < 6; i++) {
printf("%d ",*(a+i)); //*为取内容运算符 a地址移动
}
puts("");
puts("通过指针变量访问:");
for(int i=0; i < 6; i++) {
printf("%d ",*(p+i)); //*为取内容运算符 a地址移动
}
puts("");
puts("通过指针变量访问方法2:");
for(p=a; p < a+ 6; p++) {
printf("%d ",*p); //*为取内容运算符 a地址移动
}
puts("");
puts("通过指针变量采用下标访问:"); //既然数组名这个地址常量可以带下标访问,那么同样为地址的指针变量当然也可以带下标访问。
p=a;
for(int i=0; i < 6; i++) {
printf("%d ",p[i]);
}
puts("");
}
7.2.4、指向字符串的指针变量
char * 指针变量名;
定义字符指针变量后需要对其赋值。通过指针变量访问字符串的方法如下:
(1)、对于存放在字符数组的字符串,可讲数组的首地址赋给指针变量。
(2)、字符指针变量不但可以指向字符数组,而且可以指向字符串常量。对于字符串常量,可以直接将其赋给字符指针变量。
字符串常量作为一个数组,被储存在内存中,内存是按地址来分配空间的,当调用一个字符串常量的时候,就会得到这个字符串它的地址值。也就是这个意思。
void main(){
puts("对于存放在字符数组的字符串,可讲数组的首地址赋给指针变量。");
char a[] ="China"; //定义字符数组a,并初始化
char *p =a; //定义字符指针变量p,并初始化
printf("%s",p);
char *p; //定义字符串指针变量p
p="China";
//“china”是个字符串常量,它存储在内存中某个位置,字符串常量就代表这个起始位置地址值,所以
//p="china"
//这句相当于将这个数值赋值给了p,即p的值是
//“china“ 的首地址!
//也可以简写成初始化的形式:
char *p = "China";
}
void main(){
char str1[30],str2[30];
//char *p_4 = "豪哥";
//char *p_5 = "--> 你好";
strcpyCustome(str1,"ha");
printf("strcpyCustome********,*pb=%s\n",str1);
}
void strcpyCustome(char *pa,char *pb){
while (*pb != '\0'){
*pa =*pb; //代表将指针变量pb所指向的地址的数值赋值给pa,*就是取内容符
pa++;
pb++;
}
*pa = '\0';
printf("strcpyCustome********,*pb=%s\n",*pa);
}
(2)取内容运算符*
取内容运算符是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量在运算符之后跟的变量必须是指针变量。需要注意的是指针运算符和指针变量说明中的指针说明符不是一回事。在指针变量说明中,“ * ”是类型说明符,表示其后的变量是指针类型。而表达式中出现的“ * “则是一个运算符用以表示指针变量所指的变量。
main(){
int a=5,*p=&a;
printf("%d"*p)
....
表示指针变量p取得了整型变量a的地址本语句表示输出变量a的值。