C语言——指针底层逻辑总结

一、指针是什么

计算机给每一个字节都编了唯一编号。指针就是用来保存一个字节编号的变量。

&+任意一片空间的名字:取出这片空间中第一个字节的地址

int a;
/* 
计算机开辟了一个4Byte的空间,并将这片空间命名为a 
假设这片空间的地址编号为0X00000005~0X00000008
*/


int *p = &a;
/* 
取出a这片空间中的第1个字节的地址(即0X00000005),将这个地址赋值给p
也就是说,p=0X00000005
*/

X86(32位)计算机:有32根地址线;每一个字节的地址是32位,指针大小为4Byte

X64(64位)计算机:有64根地址线;每一个字节的地址是64位,指针大小为8Byte

二、指针的三种核心用法

1.解引用指针(*p)

Type *p;

*p:从p保存的地址开始,往后连续取 sizeof(Type) 个字节,并将片空间看成Type类型

int a;
/* 
计算机开辟了一个4Byte的空间,并将这片空间命名为a 
假设这片空间的地址编号为0X00000005~0X00000008
*/


int *p = &a;
/* 
取出a这片空间中的第1个字节的地址(即0X00000005),将这个地址赋值给p
也就是说,p=0X00000005
*/

*p;
/*
从p保存的地址(即0X00000005)开始,往后连续取 sizeof(int)=4 个字节,并将片空间看成int类型
*/

2.指针 +- 整数(p+n / p-n)

Type *p;

p+n:通过p中保存的地址往后跳 n*sizeod(Type) 个字节的地址

p-n:通过p中保存的地址往前跳 n*sizeod(Type) 个字节的地址

int a;
/* 
计算机开辟了一个4Byte的空间,并将这片空间命名为a 
假设这片空间的地址编号为0X00000005~0X00000008
*/


int *p = &a;
/* 
取出a这片空间中的第1个字节的地址(即0X00000005),将这个地址赋值给p
也就是说,p=0X00000005
*/

p1 = p + 2;
/*
通过p中保存的地址(即0X00000005)往后 +2*sizeof(int)=8 个字节的地址,
即0X00000005+8=0X0000000D,将这个地址赋值给p1
也就是说,p1=0X0000000D
*/

p2 = p - 1;
/*
通过p中保存的地址(即0X00000005)往后 -1*sizeof(int)=4 个字节的地址,
即0X00000005-4=0X00000001,将这个地址赋值给p2
也就是说,p2=0X00000001
*/

3.同类型指针相减(p1-p2)

前提要求:(1)两个指针必须是同一片内存空间(2)两个指针必须是相同类型

Type *p1;

Type *p2;
p1-p2=(p1-p2)/sizeof(Type)
p2-p1=(p2-p1)/sizeof(Type)

int arr[5];
/*
arr:20Byte 假设空间地址为1~20
arr[0]:1~4
arr[1]:5~8
arr[2]:9~12
arr[3]:13~16
arr[4]:17~20
*/

char* p1 = &arr[0];//1
char* p2 = &arr[2];//9

printf("%d\n", p1 - p2); //(1-9)/sizeof(char)=-9
printf("%d\n", p2 - p1); //(9-1)/sizeof(char)=9

三、数组名的三种情况

Type arr[Size];
1.sizeof(arr)

整个数组的大小

2.&arr

整个数组的地址,类型为Type(*)[Size]

3.其余所有情况

数组首元素的地址(&arr[0]),类型为Type*

四、无类型通用指针(void*)

void* p;

特点:(1)可以保存任意地址(2)不能解引用(3)不能+-整数(4)不能相减

//交换函数
void Swap(void* a, void* b, size_t size) {
    char* p1 = (char*)a;
    char* p2 = (char*)b;
    for (int i = 0; i < size; i++) {
        char tmp = p1[i];
        p1[i] = p2[i];
        p2[i] = tmp;
    }
}

五、有类型指针(Tpye*):char*的三大用法

int*、char*、double*...

注意:char*是最特殊的有类型指针,因而主要介绍char*

char*的三大用法:

1.保存单个字符变量地址

char a = 'A';
char *p = &a;
printf("%c", *p);

2.保存字符数组或者字符串的首元素地址

char arr[] = {'a','b','c','d','e'};//字符数组
char* pa = arr;//保存字符数组的首地址

char brr[] = "abcde";//字符串
char* pb = brr;//保存字符串的首地址

/字符串的三种初始化

//1.直接初始化
char arr[] = "abc";

//2.strcpy拷贝
char brr[10];
strcpy(brr, "abc");

//3.键盘输入
char crr[10];
scanf("%s", crr);

3.保存字符串常量地址

char* p = "abcdef";
/*
"abcdef"是内存中固定的字符串常量
p保存的是它首字符地址
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值