1.内存地址
内存单元的编号 == 地址 == 指针
cpu访问内存中的某个字节空间,必须知道这个字节空间在内存的什么位置,而因为内存中字节很多,所以需要给内存进行编址
代码语言:javascript复制/int main()
//{
// int a = 20;//创建变量的本质其实是在内存中申请空间
// //向内存申请4个字节的空间,用来存放20这个数字
// //这4个字节,每个字节都有编号(地址)
// //变量的名字仅仅给程序员看,编译器不看名字,
// // 编译器是通过地址找内存单元的
// //
// return 0;
//}
2.指针变量和地址
& --取地址--拿到地址
- --解引用--通过地址找回去 通过地址来找回a *pa 解释: 1.*表示pa是指针变量 2.int 表示pa指向的变量a的类型是int char ch ='w' char *pc =&ch;
/*int main()
{
int a = 20;
&a;//&----取地址操作符,拿到变量a的地址
printf("%p",&a);//打印出来的地址是00B3FD40
int* pa = &a;//将a的地址存在变量pa里面
//这个变量是用来存放地址(指针)的
//所以pa叫指针变量
//int*来是pa的类型
return 0;
}*/
/*
解释:
1.*表示pa是指针变量
2.int 表示pa指向的变量a的类型是int
char ch ='w'
char *pc =&ch;
*/
int main()
{
int a = 20;
int* pa = &a;
*pa=30;//* -解引用操作符(间接访问操作符)
//a被改成30
//通过*pa找到a
//*pa其实就是a
printf("%d", a);
return 0;
}
/*
& --取地址--拿到地址
* --解引用--通过地址找回去
通过地址来找回a *pa
*/
代码语言:javascript复制//int main()
//{
// int a = 10;
// int* p = &a;
// //1.指针变量是用来存放地址的,
// // 地址的存放需要多大空间
// //那么指针变量的大小就是多大
//
///*
//指针变量的大小取决于地址的大小
32位平台下地址是32个bit位(即4个字节)
64位平台下地址是64个bit位(即8个字节)
//x86是32位的环境,x64是64位的环境*/
// printf("%zd", sizeof(p));//输出结果是4
// return 0;
//}
//int main()
//{
// char ch = 'w';
// char* pc = &ch;
//
//
// printf("%zd", sizeof(pc));//输出结果是4
// return 0;
//}
//指针变量的大小跟类型是无关的
int main()
{
printf("%zdn", sizeof(char*));
printf("%zdn", sizeof(short*));
printf("%zdn", sizeof(int*));
printf("%zdn", sizeof(float*));
printf("%zdn", sizeof(double*));
//输出结果都是4个字节
return 0;
}
//指针变量的大小跟类型是无关的
//只要是指针类型的变量,只要在同一个平台下,大小就都是相同的
//指针类型有什么意义?为什么存在那么多的指针类型?
3.指针变量类型的意义
指针的类型决定了,对指针解引用的时候有多大权限(一次能操作几个字节)
比如:char的指针解引用就只能访问一个字节,而int的指针解引用就能访问四个字节
代码语言:javascript复制//指针类型有什么意义?为什么存在那么多的指针类型?
int main()
{
int a = 20;
int* pa = &a;//取地址a放到pa里面
char* pc = &a;
printf("&a=%pn", &a);
printf("pa=%pn", pa);
printf("pc=%pn", pc);
printf("&a 1=%pn", &a 1);
printf("pa 1=%pn", pa 1);
printf("pc 1=%pn", pc 1);
return 0;
}
/*打印结果
&a = 004FF77C
pa = 004FF77C
pc = 004FF77C
& a 1 = 004FF780
pa 1 = 004FF780
pc 1 = 004FF77D
*/
/*
char*类型的指针变量 1跳过1个字节,int类型的指针 1跳过4个字节
。这就是指针类型的差异带来的变化
int *pa
pa 1---> 1*sizeof(int)
pa n---> n*sizeof(int)
char*pc
pc 1---> 1*sizeof(char)
pc n---> n*sizeof(char)
*/
//对应int访问4个字节, 1跳过四个字节
代码语言:javascript复制//void* 指针----无具体类型的指针
//这种类型的指针可以用来接收任意类型的地址
//但是这种指针存在局限性,void*类型的指针不能直接进行指针的 -整数和解引用运算
//void*指针不能进行指针运算,可以接收不同类型的地址
//一般void*类型的指针是使用函数参数的部分,用来接收不同类型的地址
//这样的设计可以实现泛型函数的效果,使得一个函数来处理多种类型的数据
4.const修饰指针
代码语言:javascript复制int main()
{
const int n = 10;
//n=20;
int *p=&n;//把n的地址取出来给p
*p = 200;//通过n的地址来改变n的大小
printf("%d", n);
return 0;
}
代码语言:javascript复制//一般的const修饰指针变量,
// 可以放在*左边,也可以放在*右边
//int main()
//{
// int const* p;//const在*左边
// int* const p;//const在*右边
// return 0;
//}
//int main()
//{
// int n = 10;
// int m = 100;
// int* p = &n;
// *p = 20;//通过p找到n,因为p指向的是n
// p = &m;//用m的地址将n的地址覆盖了
///*关于指针有3个相关值
//* 1.p,p里面存放着一个地址
//* 2.*p,p指向的对象
//* 3.&p,表示的是p变量的地址
//*/
// return 0;
//}
//int main()
//{
// int n = 10;
// int m = 100;
// int const* p = &n;//等同于const int * p = &n;
//
// //const放在左边的时候,限制的是*p,也就是p指向的对象
// //const修饰指针变量
// //放在*左边,限制的是指针指向的内容,
// // 也就是不能通过指针变量修改它所指向的内容
// //在这里面还是限制上了n,n的数字不能被修改
//
// //但是指针变量本身是可以改变的,里面的地址是可以改变的
// *p = 20;//err
// p = &m;//ok
// return 0;
//}
//int main()
//{
// int n = 10;
// int m = 100;
// int *const p = &n;
//
// //如果要去改变p是不行的,但是没有限制*p
// //这里是可以改变p指向的对象的
//
// //
// // //将const放在*右边,此时限制的是指针变量p本身
// // //指针不能改变它的指向,
// // 但可以通过指针变量修改它所指的内容
// //指针指向的是n,但是目前已经被const固定住,不能改变指向
// *p = 20;//err
// p = &m;//ok
// return 0;
//}
//不想让const修改p就把p放在*右边
//不想让你通过p修改p的指向的内容就把const放在左边,将*p固定住
代码语言:javascript复制#include <stdio.h>
// 假设使用3个数据位和2个校验位
// 总位数为 3(数据位) 2(校验位)= 5位
// 汉明码编码函数
void hamming_encode(int data[], int *encoded) {
int p = 0; // 校验位计数器
for (int i = 0; i < 3; i ) {
// 计算每个校验位
if (i == 0) {
// 第一个校验位
encoded[p ] = (data[1] data[2]) % 2;
} else if (i == 1) {
// 第二个校验位
encoded[p ] = (data[0] data[2]) % 2;
} else {
// 第三个校验位
encoded[p ] = (data[0] data[1]) % 2;
}
// 将数据位放入编码后的数据中
encoded[p ] = data[i];
}
}
// 汉明码解码和错误纠正函数
void hamming_decode(int received[], int *data) {
int p = 0; // 校验位计数器
int error检测 = 0;
for (int i = 0; i < 3; i ) {
// 计算每个校验位
if (i == 0) {
error检测 = (received[1] received[2]) % 2;
} else if (i == 1) {
error检测 = (received[0] received[2]) % 2;
} else {
error检测 = (received[0] received[1]) % 2;
}
// 检查是否有错误
if (error检测 != received[p]) {
// 找到错误位并纠正
for (int j = 0; j < 5; j ) {
if (received[j] != (error检测 ^ received[j])) {
received[j] ^= 1; // 翻转错误位
break;
}
}
}
// 将数据位放入解码后的数据中
data[i] = received[p ];
}
}
int main() {
int data[] = {1, 0, 1}; // 原始数据
int encoded[5]; // 编码后的数据
int received[5]; // 模拟接收到的数据
int decoded[3]; // 解码后的数据
// 编码
hamming_encode(data, encoded);
printf("Encoded Data: ");
for (int i = 0; i < 5; i ) {
printf("%d ", encoded[i]);
}
printf("n");
// 模拟接收到的数据(包含一个错误)
for (int i = 0; i < 5; i ) {
received[i] = encoded[i];
}
received[2] ^= 1; // 故意引入一个错误
// 解码和错误纠正
hamming_decode(received, decoded);
printf("Decoded Data: ");
for (int i = 0; i < 3; i ) {
printf("%d ", decoded[i]);
}
printf("n");
return 0;
}
不想让const修改p就把p放在*右边-- *const p--一直指向一个数 不想让你通过p修改p的指向的内容就把const放在左边,将*p固定住-conat *p
p被const固定住,p指向内容的大小不得改变
5.指针运算
指针的基本运算有三种,分别是:
指针 -指数
指针-指针
指针的关系运算
代码语言:javascript复制//循环打印数组的内容
//int main()
//{
// int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
// int sz = sizeof(arr) / sizeof(arr[0]);
// for (int i = 0; i < sz; i )
// {
// printf("%d", arr[i]);
// }
//
//
// return 0;
//
//}
//采用指针来获取数组元素的地址
//int main()
//{
// int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
// int sz = sizeof(arr) / sizeof(arr[0]);
// int *p = &arr[0];//将arr[0]的地址存在*p中
// for (int i = 0; i < sz; i )
// {
// printf("%d ", *p);//解引用来打印arr[0]
// p ;//打印完p 往后走一步,整型指针加一就是向后挪了一个整型
// //循环十次就能把这个数组的内容打印出来
// }
// return 0;
//}
//获取数组第一个数字的地址赋值给p,再利用*p解引用,打印*p所指的数
//p 1就是*(p 1),打印数组下一个数字
//1.指针类型决定了指针 1的步长,决定了指针解引用的权限
//2.数组在内存中是连续存放的
//int main()
//{
// int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
// int sz = sizeof(arr) / sizeof(arr[0]);
// int* p = &arr[0];//将arr[0]的地址存在*p中
// for (int i = 0; i < sz; i )
// {
// printf("%d ", *(p i));//直接解引用*(p i),当i=0时,就是*p,打印的就是数组第一个数
//
// }
// return 0;
//}
p i 是跳过i*sizeof(int)个字节
代码语言:javascript复制//指针-整数,从10开始打印
//int main()
//{
// int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
// int sz = sizeof(arr) / sizeof(arr[0]);
// int* p = &arr[sz-1];//数组中最后一位的下标是sz-1
// for (int i = 0; i < sz; i )
// {
// printf("%d ", *p );
// p--;
// }
// return 0;
//}
代码语言:javascript复制//指针-指针的绝对值是指针和指针之间元素的个数
//指针-指针,计算的前提条件是两个指针指向的是同一块空间
//int main()
//{
// int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
// printf("%dn", &arr[9] - &arr[0]);//输出结果是9
// printf("%dn", &arr[0]-&arr[9] );//输出结果是-9
// return 0;
//}
//size_t my_strlen(char* p)//传过来的是数组名,用字符串指针来接收,*p指向的就是数组第一个元素
//{//size_t是无符号返回值
// size_t count = 0;
// while (*p != '