Sword 指针的最后一位一定是0

/* 指针的最后一位一定是0 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
    网上有文章说"无论是32位还是64位机器,其地址的最后一位肯定是0(利用了指针的最后一位一定是0这一特性)" ,
    这个理论我觉得是有问题的,因此我设计如下代码证明32位机器下,对象指针的最后一位不一定是0
*/

#define DEFAULT_BUFFER_LENGTH 1024

typedef struct student_s student_t;

struct student_s
{
    int age;
    char gender;
};

void test()
{
    unsigned char* p = NULL;
    student_t    * pst;

    do 
    {
        // 2.申请内存空间
        p = (unsigned char*)malloc(1);
        if (NULL == p)
        {
            break;
        }

        /*
        设计说明:
            系统的malloc函数分配的内存,指针地址一般都是内存对齐的,这是为啥呢?
            因为目前操作系统要么是32位的,要么是64位的
            我们假定操作系统是32位,那么操作内存每次至少读取4个字节
            内存地址从0开始,每次读取肯定也是4的倍数,例如你的变量是char类型,并且你的变量是操作系统分配的,
            实际上需要多读取3个字节。
            那么我们调用系统函数malloc意味着分配一块内存,这块内存肯定也是从4的倍数地址上分配,谁让从内存寻址的时候只能是4的倍数呢
            如果一个数是4的倍数,换算成二进制,末尾2位肯定是0,因为需要满足 num%4=0,即左移2为0
        */
        printf("the value of the pointer <p> address: %p\n", p);

        // 3.创建一个student_t对象
        pst = (student_t*)((unsigned char*)p + 1);

        printf("the value of the pointer <pst> address: %p\n", pst);

        /*
        这的pst指针的最后一位就不是0,因为这个pst不算是系统分配的地址,而是程序员分配的。
        那么或许有人说一般人不会使用这种方式创建对象,一般情况下是,但是如果使用了第三方内存管理库就要小心了,你的内存可未必是系统给你分配的,
        有可能从一块大内存是弄的一小块,此时上面那个逻辑就会存在致命缺陷。

        一步一拳功夫意念要专心
        */


    } while (0);

    // 释放内存
    if (p)
    {
        free(p);
        p = NULL;
    }
}

int main()
{
    test();
    return 0;
}

 

posted on 2023-03-02 21:46  寒魔影  阅读(51)  评论(0编辑  收藏  举报

导航