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; }