C语言指针讲解(适用于初学者)

本文详细介绍了C语言中的指针概念,包括一级指针和二级指针的使用,以及如何通过指针引用变量。文中通过实例代码展示了如何通过指针操作变量的值,特别讨论了如何正确交换两个变量的值,强调了使用指针作为函数参数的重要性。

本文参考视频: https://b23.tv/xLOG6SV,相当于学习笔记,这样概念混淆的时候也可以看看。

一.*p,**p

1.一级指针

以下图表示的意思是:

a的地址为0XA0,定义一个指针p,指向a的地址,计算机也会给p一个内存空间&p:0XB0

图中:p=0XA0,&p=0XB0,*p=3

来看代码:

#include<stdio.h>
void test(int *p1){
	*p1=114514;
}

int main()
{
   int *p1=NULL;
   int p=2333;
   p1=&p;
   printf("*p1=%d,p1=%d,&p1=%d,&(*p1)=%d,\np=%d,&p=%d\n",*p1,p1,&p1,&(*p1),p,&p);
   test(p1);
   printf("*p1=%d,p1=%d,&p1=%d,&(*p1)=%d,\np=%d,&p=%d\n",*p1,p1,&p1,&(*p1),p,&p);
   getchar();
   return 0;
}

 得到的结果一个一个看:

*p1=p这个变量的值

p1=p的内存地址,即(p1=&p)

&p1=计算机给p1的内存地址

&(*p1)=(*p1)这个变量的内容的地址,所以我们得到&(*p1)=&p=p1,多画图理解下就不难了。

2.二级指针(**p)

按照之前一级指针的说法,*p存放的是一级指针的地址,**p存放的就是*p的地址

以此类推***p存放的就是比他第一级指针的地址:用图理解下:

 &p1=0xc0(计算机给p1分配的地址)

p1=&p=0xb0(一级指针自身的地址)

*p1=0xa0(相当于对p1所指向的地址(0xb0)进行解析,我们找到(0xb0),发现他代表的是p的地址,而p指针所指向的是地址是(0xa0) )

注意区别:p1本身的地址和p1所指向的地址

**p1=3(同理,继续解析,得到变量a的值为3),不难发现:**p1=*p

来看代码:

#include<stdio.h>
void test2(int **p){
	printf("**p2=%d,&(*p2)=%d,*p2=%d,p2=%d,&p2=%d\n",**p,&(*p),*p,p,&p);
} 
int main(){
	int *p1=NULL;
	int p=114514;
	p1=&p;
	printf("*p1=%d,p1=%d,&p1=%d,&(*p1)=%d\n",*p1,p1,&p1,&(*p1));
	test2(&p1);
	getchar();
	return 0;
}

结果:

 其中p2代表二级指针,p1代表一级指针

●p2=&p1(p2=p1的地址)

●*p2=p1

●**p2=*p1

我们可以看到p2对p1的逐步解析(从p1的地址>到p1所指的地址>p1所指的地址的内容)

●&p2代表计算机给p2分配的地址

●&(*p2)=p2=&p1

指针确实较难理解,学习时多画图多分析

再看两段代码

#include<stdio.h>
int main()
{
    char *p="abcdf";//"abcdf"是一个常量字符串
    printf("%c\n",*p);//输出a,a是字符串的首地址 
    //printf("%s\n",*p);//错误,*p是一个"char"类型的变量 
    printf("%s",p);//输出指针p所指向的字符串的值,即"abcdf" 
    return 0; 

}
#include<stdio.h>
int main()
{
	char *a="abcdef";
	char *p=a;
	char **pp=&p;
	printf("%s\n",p);//输出abcdef ,输出指针p所指向的字符串"abcdef" 
	printf("%c",**pp); //输出a ,**pp=&p,**p指向p的地址,*pp指向的就是指针p的值,其第一个字符是'a' 
	return 0; 
}

 可以自己多写代码分析结果

二.指针的引用

来看一段代码

#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("*pointer_1=%d,*pointer_2=%d",*pointer_1,*pointer_2);
    return 0;

}

结果

a=100,b=10

*pointer_1=100,*pointer_2=10

第四行的*pointer_1,*pointer_2,表示定义两个指针变量pointer_1和pointer_2

而printf函数中的*pointer_1,*pointer_2则代表指针变量pointer_1和pointer_2所指向的变量

指针变量中只能存放地址,不能将一个整数赋给一个指针变量

*pointer_1=100;//pointer_1是指针变量,100是整数,不合法

从形式上看100是整常数,而整常数只能赋给整型变量,而不能赋给指针变量

那么应该如何正确引用指针呢?

1.给指针变量赋值

p=&a;//指针变量p的值是变量a的地址,p指向a

2.引用指针变量指向的变量

printf(“%d”,*p);   //以整数形式输出指针变量p所指向的变量的值,即变量a的值

如果有以下赋值语句:

*p=1,那么相当于把1赋值给a,a=1;//注意与上面区别,这是在p=&a的前提下

3.引用指针变量的值

printf("%o",p);   //以8进制形式输出指针变量p的值,如果p指向了a,就是输出a的地址(&a)

举个例子,来看以下代码

#include<stdio.h>
int main()
{
    int *p1,*p2,*p,a,b;
    printf("输入两个整数:");
    scanf("%d,%d",&a,&b);
    p1=&a;
    p2=&b;
    if(a<b)
    {
        p=p1;
        p1=p2;
        p2=p;
    }
    printf("a=%d,b=%d\n",a,b);
    printf("max=%d,min=%d\n",*p1,*p2);
    return 0;

}

结果

输入两个整数:5,9

a=5,b=9

max=9,min=5

 注:a和b的值并未交换,他们仍保持原值,但是p1和p2的值改变了

修改这段代码

•可以直接对p1和p2赋以新值,不必定义中间变量p

p1=&b,p2=&a;

•定义一个swap函数,实现交换两个变量的值

void swap(int *p1,int *p2)
{
    int temp;
    temp=*p1;
    *p1=*p2;
    *p2=temp;

}

在函数调用时,将实参变量(pointer_1,pointer_2)的值传送给形参变量,所以p1的值为&a,p2的值为&b,接着执行swap函数的函数体,使*p1,*p2的值互换,也就是a,b值互换,函数调用后,形参p1,p2释放(如图所示)

所以完整代码

#include<stdio.h>

void swap(int *p1,int *p2)
{
    int temp;
    temp=*p1;
    *p1=*p2;
    *p2=temp;

}

int main()
{
    int a,b;
    int *pointer_1,*pointer_2;
    printf("输入两个整数:");
    scanf("%d,%d",&a,&b);
    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;

}

*temp是指针变量temp所指向的变量,但是没有给temp赋值,所以*temp指向未知的存储单元,而这个未知的存储单元中可能存储着一个有用的数据,这样就可能破坏系统正常工作状况。

如果这样写

void swap(int x,int y)
{
    int temp;
    temp=x;
    x=y;    
    y=temp;

}

那么调用后是这样的结果

x,y的值互换了,但并未影响到a,b的值,所以x,y释放后,a,b并未交换,所以应该使用指针变量作为函数参数,在函数执行过程中,指针变量所指向的变量值发生变化,函数调用后,这些变量值的变化依然保留

注:不能通过改变形参的值而使指针实参的值改变

#include<stdio.h>

void swap(int *p1,int *p2)
{
    int *p;
    p=p1;
    p1=p2;
    p2=p;

}

int main()
{
    int a,b;
    int *pointer_1,*pointer_2;
    printf("输入两个整数:");
    scanf("%d,%d",&a,&b);
    pointer_1=&a;
    pointer_2=&b;
    if(a<b)    swap(pointer_1,pointer_2);
    printf("max=%d,min=%d\n",a,b);
    return 0;

}

 第(d)步是不能完成的,不可能通过执行调用函数来改变实参指针变量的值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dulu~dulu

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值