C语言----深入理解指针(1)(一)

简介: C语言----深入理解指针(1)

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

相关文章
|
4天前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
4天前
|
C语言
指针进阶(回调函数)(C语言)
指针进阶(回调函数)(C语言)
|
4天前
|
存储 C语言 C++
指针进阶(函数指针)(C语言)
指针进阶(函数指针)(C语言)
|
4天前
|
编译器 C语言
指针进阶(数组指针 )(C语言)
指针进阶(数组指针 )(C语言)
|
6天前
|
存储 C语言
C语言的函数返回值和指针
C|函数返回值(区分各类值)和指针(区分各类存储空间)的细节
|
5天前
|
C语言
【C语言】:详解函数指针变量,函数指针数组及转移表
【C语言】:详解函数指针变量,函数指针数组及转移表
13 2
|
5天前
|
C语言
【C语言】:详解指针数组,数组指针及(二维)数组传参(2)
【C语言】:详解指针数组,数组指针及(二维)数组传参(2)
10 1
|
5天前
|
Serverless C语言
【C语言】:对(一维)数组与指针的深入理解(1)
【C语言】:对(一维)数组与指针的深入理解(1)
9 1
|
2天前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
9 0
|
2天前
|
C语言
C语言中的函数指针、指针函数与函数回调
C语言中的函数指针、指针函数与函数回调
6 0