前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C 语言的骚操作

C 语言的骚操作

原创
作者头像
ge3m0r
发布2024-08-24 10:55:47
1590
发布2024-08-24 10:55:47

最近看别人代码突然看见一个操作让我感到很迷惑。代码如下:

代码语言:c
复制
#define  offsetof(type, member) (size_t)&(((type*)0)->number)

如果稍微了解一下其他语言,比方说 Java 就会直到,将 0 强转为一个结构体类型指针,相当于一个空指针,空指针引用,这在 Java 中可是开发的心头大忌。

我开始也是怀疑这个是不是能够运行起来,就写了一段测试程序。

代码语言:c
复制
#include <stdio.h>

typedef struct test{
    char ch;
    int number;
}*Test;

int main(){
    int a = (int)&(((Test)0)->number);
    printf("%d\n", a);
    return 0;
}

上述代码只要熟悉 c 语言的基本都能看得懂,对代码进行编译时候编译也通过了。

编译代码
编译代码

编译器只是对编译过程做出了警告,并没有报 error ,所以语法层面是可以编译成功的。

那么既然可以运行那么有人直到结果是什么吗?

在得出结果前,我们先看一下这段代码是干什么的,首先(Test)0 是将 0 强制转化为一个指向 test 结构体的指针。

然后 ((Test)0)->number 指向了结构体的 number,其实就是相当于指向了 number 的首地址。因为空指针的初始地址是 0 那么这个指针的地址就是这个 number ,在结构体中的地址偏移。

既然直到这段是在求 number 在结构体中的地址偏移,那么他的代码输出结果是什么?

这就要提到结构体的占用内存的方式。

我们直到 char 占用 1 个字节,int 占用 4 个字节,那么这个结构体是不是占用 5 个字节?

内存对齐

算法的性能可以用空间复杂度和时间复杂度来评估,而 C 语言结构体很多设计也是空间复杂度和时间复杂度之间的取舍,结构体在使用过程中并不是一个字段地址挨着一个字段地址访问,而是为了访问效率进行内存对齐的操作

一般内存对齐都是 4 字节对齐,所以上述结构体大概的一个占用内存结构如下:

内存占用
内存占用

明白了上述内存对齐,那么number 的地址在结构体中的内存偏移我们就知道了,所以输出是 4。

但是如果我就是叛逆,我管你什么性能的,我看到空间浪费我就难受,对于穷孩子出身的我就算这饭吃了拉肚子我还是不扔怎么办?

设置内存对齐方式

内存对齐是编译器的默认的一种方式,如果想要禁止内存对齐或者自己设置内存对齐方式那么可以这样。

既然是编译器的一种设置方式,那么针对不同平台的语法也不一样,在 Linux 平台下使用 attribute((packed)) 和 attribute((aligned(4))) 来进行内存对齐,在结构体语言中就是

代码语言:c
复制
typedef struct __attribute__((packed)) test {
    char ch;
    int number;
} *Test;

修改后输出就是 1 了

当然也可以自己设置对齐方式,比方说如果设置为 8

代码语言:c
复制
typedef struct __attribute__((aligned(8))) test {
    char ch;
    int number;
} *Test;

这次输出什么呢? 很多人会认为是 8,但是实际大多可能是 4,这跟编译器有很大关系,编译器优化,默认对齐设置等等有关,所以自己设置对齐方式一般小于 4

Windows 平台也有优化选项

代码语言:c
复制
#pragma pack(push, 1)
typedef struct test {
    char ch;
    int number;
} *Test;
#pragma pack(pop)

如果不加 push 后边也不同 pop ,不过这样选择就是对后边所有结构体都进行了内存对齐设置了。

另外如果只针对某一个成员变量设置对齐方式,那么可以这样写。

代码语言:c
复制
typedef struct test {
    char ch;
    int number __declspec(align(1));  // 设置 number 成员的对齐为 1 字节
} *Test;

可以看到Windows下编译器对结构体控制粒度更细。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 内存对齐
  • 设置内存对齐方式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档