1.内存地址
内存单元的编号 == 地址 == 指针
cpu访问内存中的某个字节空间,必须知道这个字节空间在内存的什么位置,而因为内存中字节很多,所以需要给内存进行编址
/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 */
//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("%zd\n", sizeof(char*)); printf("%zd\n", sizeof(short*)); printf("%zd\n", sizeof(int*)); printf("%zd\n", sizeof(float*)); printf("%zd\n", sizeof(double*)); //输出结果都是4个字节 return 0; } //指针变量的大小跟类型是无关的 //只要是指针类型的变量,只要在同一个平台下,大小就都是相同的 //指针类型有什么意义?为什么存在那么多的指针类型?
3.指针变量类型的意义
指针的类型决定了,对指针解引用的时候有多大权限(一次能操作几个字节)
比如:char的指针解引用就只能访问一个字节,而int的指针解引用就能访问四个字节
//指针类型有什么意义?为什么存在那么多的指针类型? int main() { int a = 20; int* pa = &a;//取地址a放到pa里面 char* pc = &a; printf("&a=%p\n", &a); printf("pa=%p\n", pa); printf("pc=%p\n", pc); printf("&a+1=%p\n", &a + 1); printf("pa+1=%p\n", pa + 1); printf("pc+1=%p\n", 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跳过四个字节
//void* 指针----无具体类型的指针 //这种类型的指针可以用来接收任意类型的地址 //但是这种指针存在局限性,void*类型的指针不能直接进行指针的+-整数和解引用运算 //void*指针不能进行指针运算,可以接收不同类型的地址 //一般void*类型的指针是使用函数参数的部分,用来接收不同类型的地址 //这样的设计可以实现泛型函数的效果,使得一个函数来处理多种类型的数据
4.const修饰指针
int main() { const int n = 10; //n=20; int *p=&n;//把n的地址取出来给p *p = 200;//通过n的地址来改变n的大小 printf("%d", n); return 0; }
//一般的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固定住
#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指向内容的大小不得改变
C语言----深入理解指针(1)(一)https://developer.aliyun.com/article/1544336