C语言入门-5.指针

指针的本质(间接访问原理)

指针的定义

  1. 按变量地址存取变量值的方式称为**“直接访问”**,如printf(”%d”,i);scanf(”%d”,i);
  2. 间接访问:即讲变量i的地址存放到另一个变量中。
  3. 说某个变量的地址,都是说起始地址。
  4. 指针变量是一种特殊的变量,它用来存放变量地址。
  5. 🦑 指针变量的定义格式: 基类型 *指针变量名;
  6. 指针与指针变量是两个概念,一个变量的地址称为该变量的“指针”。例如,地址2000是变量i的指针。如果一个变量专门用来存放另一个变量的地址(即指针),那么称它为“指针变量”。
    1. 编写的程序是64位应用程序,寻址范围为64即8字节。sizeof(i_pointer)=8;
    2. 编写的程序是32位应用程序,寻址范围为32即4字节。(考研中往往会强调程序是32位的程序)

取地址操作符与取值操作符,指针本质

#include <stdio.h>

int main() {
    int i = 5;
    //指针变量的初始化是某个变量取地址来赋值,不能随机写个数
    int *i_pointer;
    i_pointer=&i;//定义一个指针变量,i_pointer是指针变量名
    printf("i=%d\n",i);//直接访问
    printf("*i_pointer=%d",*i_pointer);//间接访问
    return 0;
}

 

✍️ 注意:

  1. 指针变量前面的”*”表示该变量为指针型变量。
  2. 在定义指针变量时必须指定其类型。注意:只有整型变量的地址才能放到指向整型变量的指针变量中。
  3. pointer_1=&a; & 和*两个运算符的优先级别相同,但要按自右向左的方向结合。&*pointer_1与&按相同,都表示变量a的地址,也就是pointer_1. 

指针的传递使用场景

#include <stdio.h>
//在子函数内去改变主函数中某个变量的值
void change(int j){//j是形参
    j = 5;
}
int main() {
    int i = 10;
    printf("before change i = %d\n",i);
    change(i);//C语言的函数调用是值传递,实参赋值给形参,j = i
    printf("after change i = %d\n",i);
    return 0;
}

解释值传递:进程地址空间图 

❓ 如何再子函数中修改main函数的某个变量的值?

✔️

#include <stdio.h>
//在子函数内去改变主函数中某个变量的值
void change(int *j){//j是形参
    *j = 5;//*j等价于变量i,只是间接访问
}
int main() {
    int i = 10;
    printf("before change i = %d\n",i);
    change(&i);//传递变量i的地址
    printf("after change i = %d\n",i);
    return 0;
}
//输出
before change i = 10
after change i = 5

指针的偏移使用场景

指针的偏移

#include <stdio.h>
//指针的偏移使用场景,也就是指针的加减

#define N 5
int main() {
    int a[N] = {1,2,3,4,5};//数组名内存储了数组的起始地址,a中存储的就是一个地址值
    int *p;//定义指针变量p
    p = a;
    int i;
    for(i = 0;i < N;i++){
        printf("%3d",*(p+i));//这里和写a[i]是等价的
    }
    printf("\n");
    printf("---------------------\n");
    p = &a[4];//指针变量p指向了数组的最后一个元素
    for(i = 0;i < N;i++){
        printf("%3d",*(p-i));
    }
    return 0;
}

 

p的地址是0x61fdf0,p+1的地址时0x61fdf

👩‍💻 偏移的长度是其基类型的长度,也就是偏移sizeof(int),这样通过*(p+1)就可以得到元素a[1]

指针与一维数组

#include <stdio.h>
//指针与一维数组的传递
//数组名作为实参传递给子函数,是弱化为指针的
void change(char *d){
    *d = 'H';
    d[1] = 'E';//等价于*(d + 1) = 'E'
    *(d + 2) = 'L';
}
int main() {
    char c[10] = "hello";
    change(c);
    puts(c);
    return 0;
}
//输出
HELlo

指针与malloc动态内存申请,栈与堆的差异

指针与动态内存申请

C语言的数组长度固定是因为其定义的整型、浮点型、浮点型变量、数组变量都在栈空间中,而栈空间的大小再编译时是确定的。

❓ 动态内存申请

✔️

#include <stdio.h>
#include <stdlib.h>//malloc使用的头文件
#include <string.h>
int main() {
    int size;//size代表我们要申请多大字节空间
    char *p;//void*类型的指针不能偏移,因此不会定义无类型指针
    scanf("%d",&size);//输入要申请的空间大小
    //malloc返回的void*代表无类型指针
    p = (char*)malloc(size);
    strcpy(p,"malloc success");
    puts(p);
    free(p);//释放申请的空间
    printf("free success\n");
    return 0;
}

 👩‍💻 要注意指针本身大小和其指向的空间大小,是两码事!

栈空间与堆空间的差异(了解)

  1. 栈是计算机系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈操作、出栈操作都有专门的指令执行,这就决定了栈的效率表较高。
  2. 堆是C\C++函数库提供的数据结构,它的机制很复杂,例如分配了一块内存,库函数会按照一定的算法再堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间,那么就有可能调用系统共嗯那个去增加程序数据段的内存Jon关键,这样就有机会分到足够大小的内存,然后返回。
  3. 堆的效率要比栈低得多。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//堆和栈的差异
char *print_stack(){
    char c[100] = "I am print_stack func";
    char *p;
    p = c;
    puts(p);
    return p;
}

char *print_malloc(){
    char *p =(char*) malloc(100);//堆空间再整个进程中一直有效,不因为函数结束而消亡
    strcpy(p,"I am print_stack func");
    puts(p);
    return p;
}

int main() {
    char *p;
    p = print_stack();
    puts(p);
    p = print_malloc();
    puts(p);
    free(p);//只有free时,堆空间才会释放
    return 0;
}
//输出
I am print_stack func
I am print_stack lk
I am print_stack func
I am print_stack func
  • 23
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Annabelle.02

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

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

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

打赏作者

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

抵扣说明:

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

余额充值