c语言初阶指针

对指针的基本认识

指针最基本的用法

int a = 10;
int* p = &a;

指针其实就是存储的地址,现在主流的机器有32位与64位,先来看32位的机器,由于有32个位,因此可以表示2^32字节的地址,因为一个地址小单元就是一个字节,所以表示2^32字节,注意,是字节,因此2^32 Byte =(2^32/2^10)MB = (2^32/2^10/2^10)GB = 2^2 GB, 也就是4G,因此它可以存储4GB的数据,于是,一个地址长度就为4字节,指针变量又是存储的地址,因此在32位系统中,指针变量长度为4字节。

同理可得,在64位操作系统中,指针变量长度为8字节

五个结论

接下来是五个结论,理解这四句话才能打好指针的基础

  1. 内存被划分为一个个的内存单元,每个内存单元的大小是1个字节
  2. 每个字节的内存单元都有一个编号,这个编号就是地址,地址在c语言中称为指针
  3. 地址要存储的话,存放在指针变量中
  4. 每个内存单元都有一个唯一的地址来标识
  5. 在32位机器上地址的大小是4个字节,所以指针变量的大小也是4个字节;同理,在64位机器上地址的大小是8个字节,所以指针变量的大小也是8个字节。

指针跳跃

但是,指针存储地址, 地址在同一个机器上位数不变,是不是指针类型的长度就是固定的呢?

请看VCR:

#include <stdio.h>

int main(int argc, const char * argv[]) {
    int a = 10;
    int *pa = &a;
    printf("%lu\n", sizeof((int*)pa));
    printf("%lu\n", sizeof((short*)pa));
    printf("%lu\n", sizeof((char*)pa));
    printf("%lu\n", sizeof((long*)pa));
    return 0;
}

运行结果:

那么,每个类型的指针大小都是固定不变的,需要int*, short*这些指针类型干什么呢?是不是他们就没有意义了呢?

其实

指针类型是有意义的

指针类型决定了指针+1 /-1跳过几个字节

客官请看VCR:

#include <stdio.h>

int main(int argc, const char * argv[]) {
    int a = 10;
    int *pa = &a;
    char* pc = &a;
    
    printf("pa = %p\n", pa);
    printf("pa = %p\n", pa+1);
    
    printf("pc = %p\n", pc);
    printf("pc = %p\n", pc+1);
    
    return 0;
}

运行结果

第一行第三行分别打印的是pa, pc存储的地址, 也就是变量a的地址

可以看到对于int*类型的 pa与pa+1, 他们之间的地址(0x)表示十六进制,地址相差了 e0-dc = 4字节,这也说明pa到下一个地址pa+1跳过了4个字节.

再看pc与pc+1, 他们之间的地址相差了dd-dc = 1字节,这说明pc到下一个地址pc+1跳过了一个字节,刚好是一个字符的大小

因此, 有结论

指针类型是有意义的

指针类型决定了指针+1 /-1跳过几个字节

指针解引用使用

先看指针解引用法最基础的用法:

#include <stdio.h>

int main(int argc, const char * argv[]) {
    int a = 10;
    int *pa = &a;
    *pa = 0;
    printf("%d\n", a);
    return 0;
}

可以看到, *符号是解引用符号, 可以将指针p存储的地址取出来使用, 这里进行了a的数值的更改

更进一步, 使用指针访问数组

int arr[] = {1,2,3,4,5,6,7,8,9,10};
    int *p = arr;

因为, arr是数组名,数组名表示数组首元素的地址等价于int* p = arr[0], 于是,

#include <stdio.h>

int main(int argc, const char * argv[]) {
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    int *p = arr;
    for (int i=0; i<10; i++) {
        *(p+i) = 0;
    }
    for (int i=0; i<10; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

因为i为指针偏移量, 并且p是int*的指针, 一次跳过四个字节, 也就是一次跳过数组的一个元素, 访问数组下标为i的元素的地址,并将他们都置为0

于是,打印数组可以使用p+i找到下标为i的地址, 并解引用

for (int i=0; i<10; i++) {
        printf("%d ", *(p+i));
    }

由此有一个冷门但是炫酷的小结论

因为p存储的是arr的地址

因此,可以理解为

p等价于arr

也就是 p+i等价于arr+i

解引用

*(p+i)等价于*(arr+i)都等价于arr[i]

*(arr+i)等价于arr[i]

那么有没有可能 *(i+arr)等价于i[arr]呢?

我们试试

for (int i=0; i<10; i++) {
        printf("%d ", i[arr]);
    }

!竟然真的可以

为什么呢?

因为编译器在打印或者说访问数组arr[i]时, 会把元素首地址与偏移量取出来, 也就是使用的是*(arr+i), 所以将数组名和下标写反也是没问题滴, 小装逼方法get.

相关推荐
@小博的博客12 分钟前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习
南宫生1 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步2 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
DARLING Zero two♡2 小时前
关于我、重生到500年前凭借C语言改变世界科技vlog.16——万字详解指针概念及技巧
c语言·开发语言·科技
love_and_hope2 小时前
Pytorch学习--神经网络--搭建小实战(手撕CIFAR 10 model structure)和 Sequential 的使用
人工智能·pytorch·python·深度学习·学习
Chef_Chen2 小时前
从0开始学习机器学习--Day14--如何优化神经网络的代价函数
神经网络·学习·机器学习
芊寻(嵌入式)2 小时前
C转C++学习笔记--基础知识摘录总结
开发语言·c++·笔记·学习
QAQ小菜鸟2 小时前
一、初识C语言(1)
c语言
hong1616883 小时前
跨模态对齐与跨领域学习
学习
何曾参静谧3 小时前
「C/C++」C/C++ 之 变量作用域详解
c语言·开发语言·c++