/* 指针的最后一位一定是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;
}
![]()