C 指针
学习 C 语言的指针既简单又有趣。通过指针,可以简化一些 C 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的。所以,想要成为一名优秀的 C 程序员,学习指针是很有必要的。
正如您所知道的,每一个变量都有一个内存位置,每一个内存位置都定义了可使用 & 运算符访问的地址,它表示了在内存中的一个地址。
请看下面的实例,它将输出定义的变量地址:
举例:
#include <stdio.h>
int main ()
{
int var_runoob = 10;
int *p; // 定义指针变量
p = &var_runoob;
printf("var_runoob 变量的地址: %p\n", p);
return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
var_runoob 变量的地址: 0x7ffeeaae08d8
当函数需要返回多个结果
由于C语言是使用传值的方式将参数值传递给被调用的函数,所以在C语言中无法在被调用的函数中修改main函数里的值,可以通过将main函数中变量的地址值传给被调用的函数,从而在被调用的函数中通过地址访问到变量的值,并且可以改变变量的值。
①交换函数值的例子
void swap(int a,int b){
int temp;
temp=a;
a=b;
b=temp;
}
不使用指针变量,我们不能同时将改变后的a和b的值传回;这个时候我们就可以通过指针作为参数,通过地址访问变量的值,从而去实现。
#include<stdio.h>
void swap(int *a,int *b){
int temp;
temp=*a;
*a=*b;
*b=temp;
}
int main(){
int a=1;
int b=3;
swap(&a,&b);
printf("a=%d b=%d",a,b);
return 0;
}
运行结果:
a=3 b=1
--------------------------------
Process exited after 0.03594 seconds with return value 0
请按任意键继续. . .
可以看出,主函数里将变量的地址传入swap函数,我们在swap函数中直接通过指针访问到了主函数里变量的值,并交换了数值,同时在主函数里能打印出交换的值。
数组和指针
C语言中数组和指针有着很大的关联,具体的我们往下看:
①定义一个a数组
int a[5]={1,2,3,4,5};
int类型的五个对象存在上述五块区域中;
②现在我们声明一个指针:int *p; 并且对指针赋值;p=&a[0];
#include<stdio.h>
int main(){
int a[]={1,2,3,4,5};
int i=0;
int *p; //声明了一个指针变量
p=&a[0]; //给指针p赋了a[0]的地址值给指针
for(i=0;i<5;i++){
printf("%d ",a[i]); //通过for循环将数组里的值打印出来了
}
printf("\n");
for(i=0;i<5;i++){
printf("%d ",*p); //第一次循环的时候通过指针访问到了a[0]的值,并输出了
p++; //对地址加1。我们第一次对地址+1得到了a[1]的地址,第二次+1得到a[2]的地址.......
}
printf("\n");
return 0;
}
运行结果:
1 2 3 4 5
1 2 3 4 5
--------------------------------
Process exited after 0.04136 seconds with return value 0
请按任意键继续. . .
③升入探究一下,指针p储存的地址+1是怎么变成a[1].......的地址的
输出地址
#include<stdio.h>
int main(){
int a[]={1,2,3,4,5};
printf("%p\n",&a[0]);
printf("%p\n",&a[1]);
return 0;
}
运行结果:
000000000062FE00
000000000062FE04
--------------------------------
Process exited after 0.04234 seconds with return value 0
请按任意键继续. . .
我们得到了a[0]的地址空间是000000000062FE00;a[1]的地址空间是000000000062FE04;
我们发现a[0]和a[1]之间的地址值相差了4;那为什么一开始p指针储存的值是000000000062FE00,我们对其+1的时候不应该是000000000062FE01吗?而实际我们发现我们得到的是a[1]的地址000000000062FE04。
这是因为,p指针它指向的int类型的数组中的a[0];在进行p++的时候,我们+的一个sizeof(int)=4;所以*(p+1)指向的是a[1];那么如果是对于char类型的数组,指针p++的时候,才是真的是加了1;因为sizeof(char)=1;
总之无论数组是什么类型,指针加一都是意味着它指向了数组中的下一个对象;
④指针和数组关系
一般输出:
#include<stdio.h>
int main(){
int a[]={1,2,3,4,5};
int i=0;
for(i=0;i<5;i++){
printf("%d ",a[i]);
}
return 0;
}
运行结果:
1 2 3 4 5
--------------------------------
Process exited after 0.04031 seconds with return value 0
请按任意键继续. . .
指针输出:
#include<stdio.h>
int main(){
int a[]={1,2,3,4,5};
int i=0;
for(i=0;i<5;i++){
printf("%d ",*(a+i));
}
return 0;
}
运算结果:
1 2 3 4 5
--------------------------------
Process exited after 0.03991 seconds with return value 0
请按任意键继续. . .
通过对比我们发现 printf("%d ",a[i]); 和 printf("%d ",(a+i)); 语句是完全等价的,即a[i]可以写成(a+i),可能比较难以理解,其实在C语言编译的时候,是先转化为*(a+i)的然后在进行运算的,其实我们还可换一个方面来理解,地址&a[i]和地址(a+i)是相同的。
现在我们发现其实数组和指针都是差不多的东西,但是值得我们注意的是,指针是一个变量,数组不是!而且当我们把一个数组传入函数的时候,其实我们实际传入的是数组中第一个元素的地址‘