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

相关文章
|
2月前
|
存储 C语言
【C语言篇】深入理解指针3(附转移表源码)
【C语言篇】深入理解指针3(附转移表源码)
42 1
|
2月前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
52 0
|
12天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
2月前
|
C语言
【c语言】指针就该这么学(3)
本文介绍了C语言中的函数指针、typedef关键字及函数指针数组的概念与应用。首先讲解了函数指针的创建与使用,接着通过typedef简化复杂类型定义,最后探讨了函数指针数组及其在转移表中的应用,通过实例展示了如何利用这些特性实现更简洁高效的代码。
20 2
|
2月前
|
C语言
如何避免 C 语言中的野指针问题?
在C语言中,野指针是指向未知内存地址的指针,可能引发程序崩溃或数据损坏。避免野指针的方法包括:初始化指针为NULL、使用完毕后将指针置为NULL、检查指针是否为空以及合理管理动态分配的内存。
|
2月前
|
C语言
C语言:哪些情况下会出现野指针
C语言中,野指针是指指向未知地址的指针,通常由以下情况产生:1) 指针被声明但未初始化;2) 指针指向的内存已被释放或重新分配;3) 指针指向局部变量,而该变量已超出作用域。使用野指针可能导致程序崩溃或不可预测的行为。
|
2月前
|
存储 C语言
C语言32位或64位平台下指针的大小
在32位平台上,C语言中指针的大小通常为4字节;而在64位平台上,指针的大小通常为8字节。这反映了不同平台对内存地址空间的不同处理方式。
|
2月前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
2月前
|
存储 C语言
C语言指针与指针变量的区别指针
指针是C语言中的重要概念,用于存储内存地址。指针变量是一种特殊的变量,用于存放其他变量的内存地址,通过指针可以间接访问和修改该变量的值。指针与指针变量的主要区别在于:指针是一个泛指的概念,而指针变量是具体的实现形式。
|
2月前
|
C语言
C语言指针(3)
C语言指针(3)
14 1