【C语言】指针基础

运算符&

获得变量的地址,操作数必须是变量
int i;
printf("%p",&i);
比如定义一个整型数组

#include <stdio.h>

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

输出
在这里插入图片描述
我们发现相邻整型数组元素之间的地址差是4,如果数组改成double的会是多少呢?

指针

保存地址的变量称为指针
int i;
int* p = &i;
int* p,q;int *p,q; //p是指针,q是int变量

指针获取变量的地址后可以直接对变量进行读取或修改(比如在其他子函数内修改主函数中的变量)
*p == i
例如

#include <stdio.h>

void f(int* p);

main()
{
        int i = 6;
        int* p = &i;
        f(p);
        printf("%d\n",i);
        return 0;
}

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

运行结果如下
在这里插入图片描述
&*符号作用相反
&符号区变量值所保存的地址,*符号取地址保存的变量值;
指针应用场景
1、函数需要返回多个值,某些值就只能通过指针返回;
2、 函数返回运行状态,指针返回函数结果;
指针做除法运算实例:

#include <stdio.h>

int f(int a,int b,int* result);

main()
{
        int a,b;
        printf("请输入分子分母a b:");
        scanf("%d %d",&a,&b);
        int result = 0;
        int* p = &result;
        if ( f(a,b,p) ){
                printf("a/b=%d\n",result);
        }else{
                printf("运算失败\n");
        }
        return 0;
}

int f(int a,int b,int* result){
        int ret = 1;
        if ( b == 0 ){
                ret = 0;
        }else {
                *result = a/b;
        }
        return ret;
}

指针与const
方式一
int* const q =&i; //指针地址q是const
*q = 26; //OK
q++; //ERROR
方式二
const int *p = &i; //(*p)是const,指针地址里面的值不能修改,与int const *p一样,关键看*号位置
*p = 26; //ERROR
i = 26;
p = &j;

const数组
const int a[] = {1,2,3,4,};
表明数组的每个单元都是const int,必须通过初始化进行赋值。

指针运算

指针q+1,对于char类型的是加1,int类型的是加4
sizeof(char)=1;sizeof(int)=4
指针的数据类型要与变量的数据类型一致,要不会发生类型转换,输出结果可能会不符合预期。
结合数组使用指针加法,要不得到的地址没有实际应用意义
*p = a[0]
*(p+n)=a[n]

#include <stdio.h>

main()
{
        int a[] = {0,1,2,};
        double b[] = {0,1,2,};
        int *p = a;
        printf("  p=%p\n",p);
        printf("p+1=%p\n",p+1);
        double *q = b;
        printf("  q=%p\n",q);
        printf("q+1=%p\n",q+1);
        return 0;
}

在这里插入图片描述
使用*p++输出数组(速度比较快)

#include <stdio.h>

main()
{
        int a[] = {0,1,2,-1};
        int *p = &a[0];
        while ( *p != -1 ){
                printf("*p=%d\n",*p++);
        }
        return 0;
}

在这里插入图片描述

0地址

物理内存0地址通常是不能随便碰的地址,程序运行的时候都会又一个虚拟0地址;指针不应该具有0值。
一般用NULL符号表示0地址,当指针定义为NULL表示
1、返回的指针是无效的;
2、指针没有真正的初始化(先初始化为0)
试图往0指针地址写东西会导致程序崩溃。

指针类型转换

void* 表示不知道指针地址存储内容的数据类型
指针强制类型转换
int *p = &i;void q = (void)p;
实例演示

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

在这里插入图片描述

指针应用

1、需要传入较大的数据时使用指针做参数
2、传入数组后对数组做操作
3、函数返回不止一个结果
–>需要函数来修正不止一个变量
4、动态申请内存时

动态内存分布

int *p = (int*)malloc(n*sizeof(int));
给p分配了100个int字节空间的地址
如果是Linux环境可以通过man malloc查看用法
在这里插入图片描述
malloc应用实例1
定义大小可变的数组
更规范的可变数组定义请参考链接中的可变数组章节
https://blog.csdn.net/Sudley/article/details/94338680

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

main()
{
        int n;
        printf("请输入数组大小:");
        scanf("%d",&n);

        //int a[n];   //C99可以直接用变量n定义数组大小

        int* a;
        a = (int*)malloc(n*sizeof(int));   //借用内存,使用动态内存方式定义大小

        int i;
        for (i=0;i<n;i++){
                printf("输入第%d个值",i);
                scanf("%d",&a[i]);
        }
        printf("输入的第3个值为:%d\n",a[3]);

        free(a);    //释放内存
        return 0;
}

如果系统空间不够,malloc申请失败会返回0或者NULL
测试系统提供给C程序的可支配内存大小

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

main()
{
        int count=0;
        void *p;
        while ( (p=malloc(100*1024*1024))  ){
                count++;
        }
        printf("内存大小%dG\n",count);
        return 0;
}

这个值在不同计算机以及不同运行状态下都是不一样的,下面是我windows下分别开了一个Linux虚拟机和两个Linux虚拟机的运行结果
在这里插入图片描述
free
free内存只能释放malloc定义的首地址,当指针发生运算后无法归还,下面的q可以归还,p++后无法释放p,以为此时的指针不是malloc动态分配的。

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

main()
{
        void *p=0;
        void* q=0;
        p=malloc(1*1);
        q = p;
        p++;
        printf("p=%p\n",p);
        printf("q=%p\n",q);
        free(q);
        free(p);
        return 0;
}

常见问题
1、申请了没free(忘记或者没找到合适的free时机)、长时间运行导致内存下降甚至是溢出
2、double free
解决要点:
地址变了直接free

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C语言指针基础知识点: 1.指针的定义和初始化 指针是一个变量,其值为另一个变量的地址。定义指针变量时需要指定指针所指向的变量类型,然后使用*运算符来声明指针变量。指针变量的初始化可以为其赋值为另一个变量的地址,也可以将其初始化为NULL。 2.指针的运算 指针可以进行加、减、自增、自减等运算。指针加上一个整数n时,指向的地址会增加n个存储单元的大小,减去一个整数n时,指向的地址会减少n个存储单元的大小。 3.指针的比较 指针可以进行相等、大于、小于等比较运算。当两个指针指向同一个变量时,它们相等;当两个指针指向同一数组中的不同元素时,它们可以进行大小比较。 4.指针的类型转换 指针可以进行类型转换,但需要注意转换后的指针类型必须与指向的变量类型相同,否则可能会导致程序出错。 5.指针和数组 数组名本身就是一个指针,指向数组的第一个元素。可以使用指针来访问数组中的元素,也可以将指针作为函数参数来传递数组。 以下是一个例子,演示了指针的定义、初始化、运算和比较: ```c #include <stdio.h> int main() { int a = 10; int *p = &a; // 定义指向整型变量a的指针p printf("a的值为:%d\n", a); // 输出:a的值为:10 printf("p指向的变量的值为:%d\n", *p); // 输出:p指向的变量的值为:10 printf("p的值为:%p\n", p); // 输出:p的值为:0x7ffeeb5f8a2c printf("p+1的值为:%p\n", p+1); // 输出:p+1的值为:0x7ffeeb5f8a30 printf("p的地址为:%p\n", &p); // 输出:p的地址为:0x7ffeeb5f8a28 printf("p和&a的比较结果为:%d\n", p == &a); // 输出:p和&a的比较结果为:1 return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值