今天我们大家一起开始学习指针的第一课:内存和地址
1.内存
⼀个比特位可以存储⼀个2进制的位1或者0
计算机中常见的单位(补充):
1Byte = 8bit
1KB = 1024Byte
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
1PB = 1024TB
内存单元的编号 == 地址 == 指针
2.取地址操作符(& )
#include <stdio.h>
int main()
{
int a = 10;
&a;//取出a的地址
printf("%p\n", &a);
return 0;
}
3.解引用操作符( * )
int main()
{
int a = 100;
int* pa = &a;
*pa = 0;
return 0;
}
*pa 的意思就是通过pa中存放的地址,找到指向的空间,*pa其实就是a变量了
4.指针变量
4.1概念
那我们通过取地址操作符(&)拿到的地址是⼀个数值,
比如:0x006FFD70,这个数值有时候也是需要存储起来,方便后期再使用的,
那我们把这样的地址值存放在哪里呢?
答案是:指针变量中。
4.2指针变量的大小
32位平台下地址是32个bit位,指针变量大小是4个字节
64位平台下地址是64个bit位,指针变量大小是8个字节
注意指针变量的大小和类型是无关的,只要指针类型的变量,在相同的平台下,大小都是相同的。
5.指针类型的意义
- 指针的类型决定了,对指针解引用的时候有多大的权限(一次能操作几个字节)
- 指针的类型决定了指针向前或者向后⾛一步有多大(距离)
- 在指针类型中有一种特殊的类型是 void * 类型的,
可以理解为无具体类型的指针(或者叫泛型指针),
这种类型的指针可以用来接受任意类型地址。
但是也有局限性, void* 类型的指针不能直接进行指针的+ - 整数和解引用的运算。
⼀般 void* 类型的指针是使用在函数参数的部分,
用来接收不同类型数据的地址,这样的设计可以实现泛型编程的效果。
使得⼀个函数来处理多种类型的数据。
6.const
- const如果放在 * 的左边,修饰的是指针指向的内容,
保证指针指向的内容不能通过指针来改变。但是指针变量本⾝的内容可变。 - const如果放在 * 的右边,修饰的是指针变量本⾝,
保证了指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变。
练习
1.字符串左旋
实现一个函数,可以左旋字符串中的k个字符。
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
代码
#include<stdio.h>
//方法一:先把后面的移动至前面:FDEC ,然后再把前面的部分补充上:FEDCAB
void Left_Move(char arr[], int k)
{
int len = strlen(arr);
int pos = k % len;//k是要旋转的次数,k%len代表旋转停止的下标出
char tmp[265] = { 0 };//新建一个数组存放
strcpy(tmp, arr + pos);//先将后面部分拷贝到前面,
//strcpy和strncat是字符串函数,用来对字符和字符串进行操作
strncat(tmp, arr, pos);//把前面的接到后面
strcpy(arr, tmp);//拷贝回原数组中
}
int main()
{
char arr[7] = { 'A','B','C','D','E','F'};
int k = 2;
printf("旋转之前的数组:%s\n", arr);
Left_Move(arr, k);
printf("旋转后的数组为:%s\n", arr);
return 0;
}
//方法二:用指针,前后进行逆序,先将前半部分逆序:BA,再将后半部分逆序:FEDC
//然后整体逆序得到:CDEFAB
#include<stdio.h>
#include<string.h>
#include<assert.h>
void reverse(char* left, char* right)
{
assert(left && right);
while (left < right)
{
char tmp = { 0 };
tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
void Left_Move(char arr[],int k)
{
int len = strlen(arr);
k %= len;
reverse(arr, arr + 1);
reverse(arr + 2, arr+len - 1);
reverse(arr, arr+len - 1);
}
int main()
{
char arr[7] ="abcdef";
printf("顺序交换前的数组为:%s\n", arr);
int k = 0;
printf("请输入要交换多少个字母的顺序:\n");
scanf("%d", &k);
Left_Move(arr,k);
printf("顺序交换后的数组为:%s\n", arr);
return 0;
}
方法一运行结果
方法二运行结果
总结:学习了内存和地址的概念,了解了取地址操作符&和解引用操作符*,了解了指针变量
对指针(内存、地址、取地址操作符、解引用、指针变量)的分享就到这里了,如果感觉不错,希望可以给博主点个赞或者关注,感谢大家的支持,成为我继续分享的动力,还有什么问题和建议可以在评论区评论,拜拜。