@C语言指针@指针
这个要从直接访问与间接访问说起,在程序中一般通过变量名来引用变量的值,程序通过编译后就会把变量名转化为变量的地址,通过地址对数据进行存取操作。这种方式称为直接访问,而间接访问是将变量i的地址存放在另一变量中,然后通过该变量来找到变量i的地址,从而访问i变量。这就引入了指针。
#指针和指针变量
1)一个变量的地址称为该变量的"指针"。
2)一个变量专门用来存放另一变量的地址,则称这个变量为’‘指针变量’’。
3)指针是一个地址,而指针变量是存放地址的变量。
#include<stdio.h>
int main()
{
int a = 100,b = 10;
int *pointer_1,*pointer_2;
pointer_1 = &a;
pointer_2 = &b;
printf("a=%d,b=%d\n",a,b);
printf("*printer_1=%d,*printer_2=%d\n",*printer_1,*printer_2);
return 0;
}
//运行结果:
a = 100,b = 10;
*pointer_1=100,*pointer_2=10
注:pointer_1与pointer_2出现了俩次,意义不一样。
1 定义时,"*"只是表示该变量是指针变量,
2输出时,*pointer_1与 *pointer_2则代表指针变量pointer_1和pointer_2所指向的变量。
表示"指向",pointer_1表示指针变量pointer_1所指向的变量。pointer_2同理。
##定义指针变量
格式: 类型名 * 指针变量名;
eg: int * pointer_1, * pointer_2;
1)指针变量是基本数据类型派生出来的类型,它不能离开基本类型而独立存在。
2)指针变量前面的表示该变量的类型为指针型变量。
3)在定义指针变量时必须指定基类型,(原因:指针变量中存着地址,当取数据时可以根据地址(指针)找到变量的首地址,但是并不知道取几个字节呀,这时候就会根据指定的基类型取几个字节的数据。)
4)指向某种基类型就读做某种类型+指针 eg: int指针
5)指针变量中只能存放指针(地址),不要将一个整数赋给一个指针变量(臣妾做不到啊)
##引用指针变量
1)给指针变量赋值。
p=&a; //把a的地址赋给指针变量p
2)引用指针变量指向的变量。
printf("%d", p); //以整数形式输出指针变量p所指向的变量的值。
- p = 1;//表示将整数1赋给p当前所指向的变量,如果p指向a,则相当于a的值为1了。
3)引用指针变量的值。
printf("%o",p); //以八进制数形式输出指针变量p的值,如果p指向了a,就是输出了a的地址。
4)注意俩个运算符 取地址运算符(&)与指针运算符(*).
##指针变量作为函数参数
#include <stdio.h>
int main()
{
void swap(int *p1,int *p2);//对swap函数的声明
int a,b;
int *pointer_1,*pointer_2;
printf("please enter a and b:");
scanf("%d,%d",&a,&b);
pointer_1 = &a;//使pointer_1指向a
pointer_2 = &b;//同理
if(a<b) swap(pointer_1,pointer_2);
printf("max=%d,min=%d\n",a,b);
return 0;
}
void swap(int *p1,int *p2)
{
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
//运行结果
//please enter a and b : 5,9
//max=9.min=5
//这段程序是改变了内存中a,b的值,而没有改变指针变量的值。
##通过指针引用数组
数组元素的指针就是数组元素的地址。可以用一个指针变量指向一个数组元素。
int a[10] = {1,3,5,7,9,11,13,15,17,19};
int *p;
p=&a[0];
1)数组名不代表整个数组,只代表数组首元素的地址。而指针就是地址。
2)在一定条件下允许对指针进行加减的运算。就引用数组而言,当指针指向数组元素时可以对指针进行下面四类运算
1.加一个整数(用+或+=),如p+1;
2.减一个整数(-或-=),如p-1;
3.自加运算 p++,++p;
4.自减运算p–,--p;
3)若p1与p2都指向同一数组元素时,俩个指针可以相减。
4)执行p+1时并不是将p的值简单的加一,而是加上一个数组元素所占用的字节数
5)系统怎么知道把这个1转化为4,然后与p的值相加呢?在定义指针变量时要指定基类型,系统会根据p的基类型判断占几个字节数,然后乘几。
6)引用数组中各元素的值
1.下标法,编译系统将a[i]转化为*(a+i)处理,即:先计算元素地址,找出元素 的值
2.通过数组名计算数组元素的地址,找出元素的值。
3.用指针变量指向数组元素。用指针变量直接指向元素,不必每一次都重新计算地址,能大大提高执行效率。
7)两种方式比较:
1.下标法:比较直观知道是第几个元素。
2,用地址法或者指针变量的方法不直观,很难判断出当前处理的是哪一个元素。
#include<stdio.h>
int main(){
int a[10];
int *p,i;
printf("please enter 10 integer numbers:");
for(i=0;i<10;i++){
scanf("%d",&a[i]);
}
for(p=a;p<(a+10);p++){
printf("%d",*p);
}
printf("\n");
return 0;
}
8)可以通过改变指针变量的值指向不同的元素。
想输出a数组的100个元素,可以使用这段代码
p=a
while(p<a+100)
printf("%d",*p++);
##数组名作函数参数
-
C语言调用函数时虚实结合的方法都是采用’‘值传递’'方式,当用变量名作为函数参数时传递的是变量的值,当用数组名作为函数参数时,由于数组名代表的是数组首元素地址,因此传递的值是地址,所以要求形参为指针变量。
-
可以这样理解,有一个形参数组,它从实参数组那里得到起始地址,因此形参地址与实参地址共占同一段内存单元,在调用函数期间,如果改变了形参数组的值,也就改变了实参数组的值。
-
实参数组名代表一个固定的地址,或者说是指针常量,但形参数组名并不是一个固定的地址,按指针变量处理。
##通过指针引用多维数组
int a[3][4] = {{1,3,5,7},{9,11,13,15},{17,19,21,23}};
-
a代表的是首行的首地址。a+1代表序号为1的行的首地址。
-
a[0]代表一维数组a[0]中第0列的元素的地址。即&a[0][0]
-
a[0]+1的值代表的是一维数组中序号为1的元素的首地址。
-
*(a+i) 和a[i]是等价的。
-
a+1是二维数组a中序号为1的行的首地址(序号从0算起),而*(a+1)
并不是a+1单元的内容,因为a+1并不是一个变量的存储单元,也就谈不上它的存储内容了。(a+1)就是a[1],而a[1]是一维数组名,所以也是地址,它指向a[1][0].a[1]和(a+1)都是二维数组中地址的不同表达形式。
-
&a[i]或a+i指向行,而a[i]或*(a+i)指向列。