梦回大学,因它难以入睡,今一文总结之

回顾大学时期,c语言与指针曾带来困惑,如今为理解openJDK源码,再次深入学习。文章以简单的代码示例介绍指针基础,探讨技术学习应由兴趣驱动而非完全功利。
摘要由CSDN通过智能技术生成

依稀记得10年前的大学第一门课就是它——c语言,而指针作为c语言的核心之一,当时一直难以理解,从而转战java。而今10余年过去了,依然还是放不下它,也同时为了阅读openJDK源码做准备,就重新拾起。其实就是因为喜欢研究底层这个癖好,才让我走上了不归路。没办法,重新拾起c语言基础。
其实对技术学习本来就应该是兴趣驱动,但目前太多人学习技术都过于功利,工作中用什么学什么,失去了自己对技术的追求,我又何尝不是呢?其实都是为了生存罢了。
不再感慨了,下面一小段代码,总结了指针的基础:

#include <stdio.h>

#include <stdlib.h>
struct Person
{
    char name;
    int age;
};

int test(int a,int b) {
    printf("%d %d\n", a, b);
    return a + b;
};

int test2(int a,int b) {
    printf("%d %d\n", a, b);
    return a - b;
};

void test3(struct Person persons) {
    persons.age = 10;
    //printf("persons.age: %d\n", persons.age);
}

void test4(struct Person *persons_p) {
    persons_p->age = 10;
    //printf("persons.age: %d\n", persons_p->age);
}

int main() {

    // 变量a,其内存地址为0x7ffee3a1ab38
    /**
     *             a
     *       0x7ffee3a1ab38
     *  |——————————————————————|
     *  |         10           |
     *  |——————————————————————|
     *
     */
    int a = 10;
    // int *pInt 定义一个指针类型变量,pInt本身会分配一个内存空间,即分配一个内存地址,pInt本身存放的值为变量a的内存地址
    // &a即取a的内存地址0x7ffee3a1ab38
    /**
     *
     *                                              a
     *            pInt ——————————————————————> 0x7ffee3a1ab38
     *         0x7ffee1ab2b30
     *  |——————————————————————|        |——————————————————————|
     *  |    0x7ffee3a1ab38    |        |         10           |
     *  |——————————————————————|        |——————————————————————|
     *
     *
     *
     */
    int *pInt = &a;

    // '*'即定义一个指针类型的变量,变量值为内存地址,'&'即取地址符,取得指定变量的内存地址
    printf("%p\n", &a);              //输出:0x7ffeef5e5b38,a的内存地址
    printf("%p\n", pInt);            //输出:0x7ffeef5e5b38,指针变量pInt的值
    printf("%p\n", &pInt);           //输出:0x7ffeef5e5b30,指针变量pInt的内存地址
    printf("%d\n", *pInt);           //输出:10,*pInt即解引用,取出其引用地址变量所存储的值,即变量a的值

    /**
     * 再看一个例子
     */
    // *p:p的值为0x11223344,它的内存地址为0x7ffee5cafb24
    int *p = 0x11223344;
    // 变量p的值赋值给a1,即a1=0x11223344
    int a1 = p;

    // a1为变量p的值0x11223344,&a1为变量a1的实际内存地址
    printf("%p\n", a1);           //输出:0x11223344
    printf("%p\n", &a1);          //输出:0x7ffee264cb24
    printf("%p\n", &p);           //输出:0x7ffee264cb28


    /**
     * '**':指向指针的指针,其实这么解释'**'的人就有点不负责任了,什么叫指向指针的指针呢?
     * 其实就是一个二维指针,看图:
     *                                                                              a
     *                                          pInt ——————————————————————> 0x7ffee3a1ab38
     *       pInt1 ——————————————————————>    0x7ffee1ab2b30
     * |——————————————————————|        |——————————————————————|        |——————————————————————|
     * |    0x7ffee1ab2b30    |        |    0x7ffee3a1ab38    |        |         10           |
     * |——————————————————————|        |——————————————————————|        |——————————————————————|
     *
     * **pInt1就代表pInt1指向pInt指针变量,*pInt1即取得pInt1的引用PInt的值,即0x7ffee3a1ab38。
     *                                  *(*pInt1)即取得pInt的引用a的值,即为10。
     *
     */
    int **pInt1 = &pInt;

    printf("*pInt1:%p\n", *pInt1);
    printf("**pInt1:%d\n", *(*pInt1));
    printf("%p\n", &pInt1);


    /**
     * 常量指针,指针常量
     */
    // 常量指针:能修改指针的指向,不能修改指针的实际值
    const int * c = 0x321312;
    //*c = 1;     // 此行报错
    // 指针常量:能修改指针的实际值,不能修改指针的指向
    int * const c1 = 1;
    //c1 = &a;    // 此行报错
    // 常量指针+指针常量:即不能修改指针指向,也不能修改值
    const int * const c2 = 2;
    //*c2 = 1;    // 此行报错
    //c2 = &a;    // 此行报错

    /**
     * 函数指针
     */
    // 即定义了返回值为int类型,参数为int,int类型的函数指针,p_test直接接收返回值
    int (*p_test) (int, int);
    p_test = test(1,2);
    p_test = test2(1,2);

    printf("p_test:%d\n", p_test);

    /**
     * 不同类型变量转换
     */
    // int 转 char,因为int类型在64位机器上占4个字节
    int *t = 0x11223344;
    // int转char,char占1个字节,所以只能取变量t中的一个字节,因为是小端机(什么是小端,自己普及),所以取得44,大端应该输出11
    char s = (char *)t;
    // int 转 long double
    long double *d = (long double *) t;

    printf("%p\n", s);           //输出:0x44
    printf("%p\n", d);           //输出:0x11223344

    /**
     * 通过指针方式操作数组
     */
    // 数组,通过指针的方式取char数组中的其中一个字符。
    char name[] = "test";
    // 这行是通过指针方式来获取name变量的第二个字符,因为char占1个字节,所以name+1即取得指向test数组的index为2的位置,
    // 即*(name + 1)取得对于的char字符e
    char i = *(name + 1);

    printf("%c\n", i);           //输出:e


    /**
     * 函数之值传递、引用传递
     */
    // 值传递,传递的变量本身,不会修改变量的值
    struct Person person1;
    person1.age = 1;
    test3(person1);
    printf("%d\n", person1.age);    // 输出:1

    // 引用传递,传递的是变量的内存地址,会修改变量的值
    struct Person person2;
    person2.age = 1;
    test4(&person2);
    printf("%d\n", person2.age);   // 输出:10

    return 0;
}

本文这小段代码挺小白的,因为对于c语言来说,我也是个小白。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值