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

目录

运算符&的“前世今生”

指针

修改外部的值

 指针的应用

返回多个值

指针与数组

指针与常量

①int *const q = &i        

②const int *p = &i

指针的运算

指针计算

指针比较

指针类型


运算符&的“前世今生”

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

要知道它的作用,就先从变量入手。

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

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

#include<stdio.h>
int main(){
    int i = 0;
    printf("%p\n",&i);
    return 0;
}

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

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

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

#include<stdio.h>

int main(void) {
	int a[10];
	
	printf("%p\n",&a);
	printf("%p\n",a);
	printf("%p\n",&a[0]);
	printf("%p\n",&a[1]);
	return 0;
}

指针

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

指针类型的变量就是保存地址的变量

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

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

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

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

void f(int *p)
{
    printf("p=%p\n",p);
}

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

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

在f函数中加入一句

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

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

修改外部的值

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

#include<stdio.h>
void f(int *p);
void g(int k);

int main(void)
{
    int i = 6;
    printf("&i=%p\n",&i);
    f(&i);
    g(i);
    system("pause");
    return 0;
}

void f(int *p)
{
    printf("p=%p\n",p);
    printf("*p = %d\n",*p);
    *p = 26;
}

void g(int k)
{
    printf("k =%d",k);
}

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

 指针的应用

一、交换两个变量的值

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

 但这却可以用指针来解决

#include<stdio.h>

void swap(int *pa,int *pb);

int main()
{
    int a = 5;
    int b = 6;
    swap(&a, &b);
    printf("a=%d,b=%d",a,b);

    return 0;
}

void swap(int *pa, int *pb)
{
    int t = *pa;
    *pa=*pb;
    *pb=t;
}

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

返回多个值

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

#include<stdio.h>

void minmax(int a[],int len,int *max,int *min);

int main(void)
{
    int a[] = {1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55,};
    int min,max;
    minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);
    printf("min=%d,max=%d",min,max);

    return 0;
}

void minmax(int a[],int len,int *min,int *max)
{
    int i;
    *min=*max=a[0];
    for(i=1;i<len;i++){
        if(a[i]<*min){
            *min = a[i];
        }
        if(a[i]>*max){
            *max = a[i];
        }
    }
}

以此代码为例,在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

 数组变量是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);

指针与常量

指针是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>

int main()
{
    char ac[]={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);
    char ai[]={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);

    return 0;
}

让指针加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>

int main()
{
    char ac[]={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));

    return 0;
}

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

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

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


指针计算

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

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

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

#include<stdio.h>
#include<stdlib.h>

int main()
{
    char ac[]={0,1,2,3,4,5,6,7,8,9,};
    char *p=ac;
    char *p1=&ac[5];
    printf("p1-p=%d\n",p1-p);
    char ai[]={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");
    return 0;
}

*p++

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

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

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

#include<stdio.h>

int main(void)
{
    char a[]={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);
    }

    return 0;
}

指针比较

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

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

指针类型

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小泥人Hyper

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

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

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

打赏作者

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

抵扣说明:

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

余额充值