您现在的位置是:主页 > news > 学做网站好做吗/最新网络推广平台
学做网站好做吗/最新网络推广平台
admin2025/5/5 21:03:08【news】
简介学做网站好做吗,最新网络推广平台,重庆网站建设帝维科技,静态网页毕业设计论文从 C 开始 边界对齐 看到下列结构体,使用 sizeof 可得该结构体大小为 24 个字节 typedef struct {char a; // 1 个字节double c; // 8 个字节int b; // 4 个字节 } AType;C 边界对齐规则 那为什么需要对齐呢?原因也很简单,即一次读写…
学做网站好做吗,最新网络推广平台,重庆网站建设帝维科技,静态网页毕业设计论文从 C 开始
边界对齐
看到下列结构体,使用 sizeof 可得该结构体大小为 24 个字节
typedef struct {char a; // 1 个字节double c; // 8 个字节int b; // 4 个字节
} AType;C 边界对齐规则 那为什么需要对齐呢?原因也很简单,即一次读写…
从 C 开始
边界对齐
看到下列结构体,使用 sizeof
可得该结构体大小为 24 个字节
typedef struct {char a; // 1 个字节double c; // 8 个字节int b; // 4 个字节
} AType;
C 边界对齐规则
那为什么需要对齐呢?原因也很简单,即一次读写就能把整个数给拿出来(众所周知内存的读写对于 CPU 来说开销是蛮大的)
对于 x86 对齐只是建议而不是强制,而对于 MIPS 必须强制对齐
优化结构体存储大小
由于对齐规则的存在,所以可以调整结构体内字段顺序来优化存储大小。如下面优化过的结构体大小为 16 个字节
typedef struct {double c; // 8 个字节int b; // 4 个字节char a; // 1 个字节
} BType;
此时我心里便有了一个小问号,调整字段顺序这么简单的事情应该交由编译器做,而不是交给程序员处理。
那为什么没有交由编译器做呢?
内存中按序存放
结构体中的字段在内存中是按序存放的
#include <stdio.h>typedef struct {double c; // 8 个字节int b; // 4 个字节char a; // 1 个字节
} BType;typedef char* ptr;void main() {BType b = {1.0, 2, 'a'};printf("%d\n", *(p + 8)); // 输出 2
}
看回 Java
字段重新排列
public class AlignDemo {public static void main(String[] args) {AClass o = new AClass();System.out.println(ClassLayout.parseInstance(o).toPrintable());}public static class AClass {char a;double b;int c;}
}
AlignDemo$AClass object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)12 4 int AClass.c 016 8 double AClass.b 0.024 2 char AClass.a 26 6 (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 0 bytes internal + 6 bytes external = 6 bytes total
最终整个对象大小要补足为 8 的整数倍
可见字段顺序和类中字段顺序是不一致的,因为编译器做了优化用以压缩空间
那为什么 Java 却能这样优化呢?Java 对数据的访问做了严格的限制,指针都没有,更别提上文的骚操作了
又见 Redis
负数索引
以下代码摘自 Redis 的 sds.h
typedef char *sds;struct sdshdr64 {uint64_t len;uint64_t alloc;unsigned char flags;char buf[];
};static inline size_t sdsavail(const sds s) {unsigned char flags = s[-1]; // 这是什么骚操作?...
}
因为 C 数组是没有边界检查的,所以负数索引不会报错。sds 其实是一个 char 指针,上面说到 C 结构体在内存中是按序存放的,不妨把他想象成一个数组。往前走一个 char 的宽度,便能取得 flags。