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

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

一.*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)步是不能完成的,不可能通过执行调用函数来改变实参指针变量的值


目录
相关文章
|
1月前
|
存储 C语言
【C语言篇】深入理解指针3(附转移表源码)
【C语言篇】深入理解指针3(附转移表源码)
36 1
|
19天前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
44 0
|
18天前
|
C语言
【c语言】指针就该这么学(3)
本文介绍了C语言中的函数指针、typedef关键字及函数指针数组的概念与应用。首先讲解了函数指针的创建与使用,接着通过typedef简化复杂类型定义,最后探讨了函数指针数组及其在转移表中的应用,通过实例展示了如何利用这些特性实现更简洁高效的代码。
13 2
|
18天前
|
C语言
如何避免 C 语言中的野指针问题?
在C语言中,野指针是指向未知内存地址的指针,可能引发程序崩溃或数据损坏。避免野指针的方法包括:初始化指针为NULL、使用完毕后将指针置为NULL、检查指针是否为空以及合理管理动态分配的内存。
|
18天前
|
C语言
C语言:哪些情况下会出现野指针
C语言中,野指针是指指向未知地址的指针,通常由以下情况产生:1) 指针被声明但未初始化;2) 指针指向的内存已被释放或重新分配;3) 指针指向局部变量,而该变量已超出作用域。使用野指针可能导致程序崩溃或不可预测的行为。
|
25天前
|
存储 C语言
C语言32位或64位平台下指针的大小
在32位平台上,C语言中指针的大小通常为4字节;而在64位平台上,指针的大小通常为8字节。这反映了不同平台对内存地址空间的不同处理方式。
|
24天前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
25天前
|
存储 C语言
C语言指针与指针变量的区别指针
指针是C语言中的重要概念,用于存储内存地址。指针变量是一种特殊的变量,用于存放其他变量的内存地址,通过指针可以间接访问和修改该变量的值。指针与指针变量的主要区别在于:指针是一个泛指的概念,而指针变量是具体的实现形式。
|
25天前
|
C语言
C语言指针(3)
C语言指针(3)
11 1
|
25天前
|
C语言
C语言指针(2)
C语言指针(2)
13 1
下一篇
无影云桌面