指针详细概念知识点及运用,指针与常量,指针的运算,scanf()中的&有什么用?你想知道的,都在这儿~ 1.1.4

简介: f函数里的*p保存了i的地址,在这个函数指向i,此时对*p赋值,也就相当于对i值进行了改变,实现了对外链接,i的值变为了26,就是芥末神奇。此时以*q = 26为例,是可以做的,因为i不是const,i可以赋初值,使 i=26,但因为q是const,所以q++的做法是错误的。表示不能通过p这个指针去修改i这个变量,即*p=26是错误的,不能让 i=26,此时的*p是const。无论指向什么类型,所有指针的大小都是一样的,因为都是地址,但指向不同类型的指针是不能直接相互赋值的。......

 目录

运算符&的“前世今生”

指针

修改外部的值

指针的应用

返回多个值

指针与数组

指针与常量

①int *const q = &i        

②const int *p = &i

指针的运算

指针计算

指针比较

指针类型


运算符&的“前世今生”

刚开始接触C语言时,我们就得记住一件事,scanf()中输入一个变量,变量前必须加“&”,否则就会报错,而printf()中却不用。

要知道它的作用,就先从变量入手。image.gif编辑

C语言的变量放在内存里,因此有一个占据的地方,就是地址。而“&”就是把变量的地址拿出来,告诉你这个变量放在哪里,然后取出调用

&也有地址,在printf() 中可用%p求出

#include<stdio.h>intmain(){
inti=0;
printf("%p\n",&i);
return0;
}

image.gif

而地址的大小是否与int相同,则取决于编译器

取地址时&右边必须是明确的变量,不能为表达式image.gif编辑

相邻地址间的差距永远是4

#include<stdio.h>intmain(void) {
inta[10];
printf("%p\n",&a);
printf("%p\n",a);
printf("%p\n",&a[0]);
printf("%p\n",&a[1]);
return0;
}

image.gif

image.gif编辑

指针

需要一个参数保存变量的地址,则可以使用指针

指针类型的变量就是保存地址的变量image.gif编辑

int* p = &i; 就是把i的地址保存到指针p中,其中*可以靠近int 也可以靠近p

int* p,q;等价于int *p,q;我们就可以说p指向了q

指针变量的值是具有实际值的变量的地址,而普通变量的值是实际的值      

#include<stdio.h>voidf(int*p);
intmain(void)
{
inti=6;
printf("&i=%p\n",&i);
f(&i);
system("pause");
return0;
}
voidf(int*p)
{
printf("p=%p\n",p);
}

image.gif

可见输出结果中p已经保存了i的地址,使得f函数拥有访问外面i的能力了,可是该怎么访问,即怎样读或写?

其实只需使用*加指针变量即可,同上代码,可以把*p理解成一个整数

在f函数中加入一句

printf("*p = %d\n",*p);

image.gif

这时输出的数值即为6,就是i的初值,可见使用*加上指针变量就能访问这个地址

修改外部的值

按照之前的课程,我们知道函数是独立程序模块,不能将外部定义的值修改,而此时有了指针,在函数中获取了地址,则情况就不一样了

#include<stdio.h>voidf(int*p);
voidg(intk);
intmain(void)
{
inti=6;
printf("&i=%p\n",&i);
f(&i);
g(i);
system("pause");
return0;
}
voidf(int*p)
{
printf("p=%p\n",p);
printf("*p = %d\n",*p);
*p=26;
}
voidg(intk)
{
printf("k =%d",k);
}

image.gif

f函数里的*p保存了i的地址,在这个函数指向i,此时对*p赋值,也就相当于对i值进行了改变,实现了对外链接,i的值变为了26,就是芥末神奇image.gif编辑

指针的应用

一、交换两个变量的值

当我们学到函数时,尝试过利用函数交换两个数,结果可想而知,无法改变函数外a,b的取值

image.gif编辑

但这却可以用指针来解决

#include<stdio.h>voidswap(int*pa,int*pb);
intmain()
{
inta=5;
intb=6;
swap(&a, &b);
printf("a=%d,b=%d",a,b);
return0;
}
voidswap(int*pa, int*pb)
{
intt=*pa;
*pa=*pb;
*pb=t;
}

image.gif

运行后a与b 的值发生了互换

返回多个值

函数中return语句只能传出一个变量值,函数结果不止一个时可以用指针传出

#include<stdio.h>voidminmax(inta[],intlen,int*max,int*min);
intmain(void)
{
inta[] = {1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55,};
intmin,max;
minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);
printf("min=%d,max=%d",min,max);
return0;
}
voidminmax(inta[],intlen,int*min,int*max)
{
inti;
*min=*max=a[0];
for(i=1;i<len;i++){
if(a[i]<*min){
*min=a[i];
        }
if(a[i]>*max){
*max=a[i];
        }
    }
}

image.gif

以此代码为例,在minmax函数中找出素数最大与最小值,用指针便可传递两值离开函数,并在主函数中printf输出

指针与数组

函数参数表中的数组实际上是指针,但可以用数组的运算符 [ ] 进行运算

sizeof(a)==sizeof(int*)

数组变量本身表达地址,所以在数组无需用&取地址即int a[10];        int *p=a;

但数组的单元表达是变量,如a[0],a[1]···等等,需要用&取地址


a==&a[0]        运算符 [ ] 可以对数组做,也可以对指针做:*p<==>p[0]

                                                   相反,*也可以对数组做:*a<==>a[0]

指针这个知识点是真滴生涩,看不懂啊喂 QwQ

image.gif编辑

数组变量是const的指针,所以不能被赋值,数组变量间不能做赋值

错误示范:a[ ]=b或者int a[ ];a=b;


一个数组是常量指针,即const的指针,所以不能被赋值

int a[ ]<==>int *const a=···

const int a[]={1,2,3,4,5,6};数组变量本身是const指针

这里的const表明数组的每个单元都是const int,所以必须通过初始化进行赋值,否则接下来将不能进行赋值操作

希望数组在函数中不被破坏,可以设置参数为const

int sum(const int a[],int length);

image.gif

指针与常量

指针是const时,表示一旦得到了某个变量的地址,不能再指向其他变量,即关系一定,指针一定指向某个变量,不会被改变

①int *const q = &i        

(q是const)q指向了i这个事实不可改变,它们之间的关系是永久的

此时以*q = 26为例,是可以做的,因为i不是const,i可以赋初值,使 i=26,但因为q是const,所以q++的做法是错误的


②const int *p = &i

表示不能通过p这个指针去修改i这个变量,即*p=26是错误的,不能让 i=26,此时的*p是const

但i不是const,可以单独给i赋值,i=26而不能通过*p去改变。同时p不是const,它也可以指向其他地址,p = &j;是成立的

总的来说,有两种意思:一是指针不可修改,另一是不可通过指针修改

const在*前,表面它所指的东西不能修改

const在*后,表面指针不能被修改

指针的运算

#include<stdio.h>intmain()
{
charac[]={0,1,2,3,4,5,6,7,8,9,};
char*p=ac;
printf("p=%p\n",p);
printf("p+1=%p\n",p+1);
charai[]={0,1,2,3,4,5,6,7,8,9,};
char*q=ai;
printf("q=%p\n",q);
printf("q+1=%p\n",q+1);
return0;
}

image.gif

让指针加1:sizeof(char)=1,sizeof(int)=4

由上面的代码运行可知,char的指针地址加1,而int时,变成了加4。所以指针加1,并不是在地址值上加1,而是在地址值上加一个sizeof那个指针所指的类型

int一个单元占4个字节,所以2c加1后单元地址为30,再加1,则为34

对指针做加一,实际上是我们把它移到下一个单元去

*p ->ac[0] 所以*(p+1)->ac[1]

#include<stdio.h>intmain()
{
charac[]={0,1,2,3,4,5,6,7,8,9,};
char*p=ac;
printf("*p=%d\n",*p);
printf("*(p+1)=%d\n",*(p+1));
return0;
}

image.gif

运行代码可见,*p确实输出为0与ac[0]相同

而*(p+1)为1,与ac[1]相同===================》》》》》*(p+n)与a[n]是一回事儿

如果指针不是指向一片连续分配的空间,如数组,则这种运行没有意义


指针计算

1.给指针加减一个整数(+,+=,-,-=)

2.递增递减(++,--)

3.两个指针相减(所得结果不是两个地址的差,而是差,除以sizeof的类型,表示在这两者间有多少个单元在里面)

#include<stdio.h>#include<stdlib.h>intmain()
{
charac[]={0,1,2,3,4,5,6,7,8,9,};
char*p=ac;
char*p1=&ac[5];
printf("p1-p=%d\n",p1-p);
charai[]={0,1,2,3,4,5,6,7,8,9,};
char*q=ai;
char*q1=&ai[5];
printf("q1-q=%d\n",q1-q);
system("pause");
return0;
}

image.gif

*p++

取出*p所指的那个数据来,再顺便把p移到下一位

*优先级虽然高,但没有++高,所以不需要再加括号变成*(p++)

*p++常用于数组类的连续空间操作

#include<stdio.h>intmain(void)
{
chara[]={0,10,25,37,49,52,65,76,83,95,-1};
char*p=&a[0];
for(p=a;*p!=-1;*p++){
printf("%d\n",*p);
    }
return0;
}

image.gif

指针比较

<,<=,==,>=,>,!=都可以对指针进行比较内存中的地址

数组中的单元地址肯定是线性递增

指针类型

无论指向什么类型,所有指针的大小都是一样的,因为都是地址,但指向不同类型的指针是不能直接相互赋值的

image.gif编辑

相关文章
|
1月前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
45 7
|
2月前
|
自然语言处理 前端开发 JavaScript
深入理解前端中的 “this” 指针:从基础概念到复杂应用
本文全面解析前端开发中“this”指针的运用,从基本概念入手,逐步探讨其在不同场景下的表现与应用技巧,帮助开发者深入理解并灵活掌握“this”的使用。
|
8月前
|
编译器 C语言
C语言进阶⑪(指针上)(知识点和对应练习)回调函数模拟实现qsort。(下)
C语言进阶⑪(指针上)(知识点和对应练习)回调函数模拟实现qsort。
63 0
|
8月前
|
存储 编译器 C语言
C语言初阶⑦(指针初阶)知识点+笔试题(上)
C语言初阶⑦(指针初阶)知识点+笔试题
53 0
|
3月前
|
人工智能
魔法指针 之 指针变量的意义 指针运算
魔法指针 之 指针变量的意义 指针运算
28 0
|
7月前
|
存储 C++
有关【指针运算】的经典笔试题
有关【指针运算】的经典笔试题
40 4
|
7月前
|
C语言
C语言----关于二维数组传参的本质相关的知识点(数组指针、指针数组)
C语言----关于二维数组传参的本质相关的知识点(数组指针、指针数组)
|
8月前
|
C语言
在引用数组元素时指针的运算
在引用数组元素时指针的运算
61 0
|
8月前
|
C语言 C++
C语言:指针运算笔试题解析(包括令人费解的指针题目)
C语言:指针运算笔试题解析(包括令人费解的指针题目)
|
8月前
|
存储 编译器 数据库
指针(1)--对于指针基本概念的介绍
指针(1)--对于指针基本概念的介绍
94 0