栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

重新认识C语言中的结构体

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

重新认识C语言中的结构体

我们对C语言中的struct的印象是什么?

  • 它是C语言中内置的复合数据类型;
  • 相当于C++中的class;
  • 丰富的初始化操作;
  • Struct的拷贝为浅拷贝;
  • 支持嵌套、指针等操作;
  • 支持位字段,节省空间。

如果你知道的只有这些,那么说明你对struct了解的还不够深刻,后续我们简单聊聊结构体的一些知识。

本文的代码以及描述都是基于linux环境。

1. C++中的struct

C++中的struct本质上和class没有区别,struct也支持构造函数、成员函数、虚函数、继承等,仅仅只有默认的访问权限和成员初始化和class不太一样。看一下下面的结构体相关的代码:

struct STest {
public:
	int a:8;
	int b:8;
	int c:8;
	int d:8;
	STest() {reset();}
	bool is_valid() const;
	void reset();
};

从上面的例子中,可以看到struct和clall几乎没有什么区别,那么我们到底该如何使用class、struct呢?推荐的用法是这样的:

  • struct仅被用在包含公有数据的消极变量上,可以包含有关联的常量,以及reset、is_valid、序列化、反序列化这样的通用函数;
  • 其他情况都应该用class。
2. struct的对齐

struct的对齐原则是:

  • 结构体变量中成员的偏移量必须是成员大小的整数倍;
  • 结构体总大小必须是所有成员大小的公倍数;
  • 结构体的总大小为结构体对齐字节数大小的整数倍。

举个例子,看一下下面的代码:

// file: align.c
// gcc align.c -o align
#include 
#include 

struct Test1 {
    int64_t a;
    int8_t b;
    int32_t c;
    int8_t d;
};

struct Test2 {
    int64_t a;
    int8_t b __attribute__((aligned(16)));
    int32_t c;
    int8_t d;
};

struct Test3 {
    int64_t a;
    int8_t b ;
    int32_t c;
    int8_t d;
} __attribute__((aligned(16)));

int main() {
    struct Test1 t1;
    struct Test2 t2;
    struct Test3 t3;
    printf("sizeof(t1) = %dn", sizeof(t1));
    printf("sizeof(t2) = %dn", sizeof(t2));
    printf("sizeof(t3) = %dn", sizeof(t3));
    printf("t1 &a = 0x%p, &b = 0x%p, &c= 0x%p &d = 0x%pn", &t1.a, &t1.b, &t1.c, &t1.d);
    printf("t2 &a = 0x%p, &b = 0x%p, &c= 0x%p &d = 0x%pn", &t2.a, &t2.b, &t2.c, &t2.d);
    printf("t3 &a = 0x%p, &b = 0x%p, &c= 0x%p &d = 0x%pn", &t3.a, &t3.b, &t3.c, &t3.d);
}

输出结果:

$ ./align
sizeof(t1) = 24
sizeof(t2) = 32
sizeof(t3) = 32
t1 &a = 0x0x7ffcfaeb0830, &b = 0x0x7ffcfaeb0838, &c= 0x0x7ffcfaeb083c &d = 0x0x7ffcfaeb0840
t2 &a = 0x0x7ffcfaeb0810, &b = 0x0x7ffcfaeb0820, &c= 0x0x7ffcfaeb0824 &d = 0x0x7ffcfaeb0828
t3 &a = 0x0x7ffcfaeb07f0, &b = 0x0x7ffcfaeb07f8, &c= 0x0x7ffcfaeb07fc &d = 0x0x7ffcfaeb0800

可以通过下面的图片简单看下这个结构体在不同对齐情况下的内存分布:

3. 使用struct做数据页的序列化

我们来设计这样一个数据页,如下图:

实现的方式有很多,最简单高效的应该就是用struct了,代码如下:

// file: page.c
// g++ page.c -o page

#include 
#include 
#include 
#include 

typedef struct __attribute__((packed)) {
  static const uint32_t PAGE_SIZE = 16384;
  static const uint8_t  CRC_SIZE  = 4;
  uint32_t magic;
  uint32_t version;
  uint32_t header_size;
  uint32_t payload_size;
  uint32_t padding_size;
  char     data[0];
} simple_page_t;

int serialize_data(char *data) {
    int data_size = 10240;
    memset(data, 'd', data_size);
    return data_size;
}

void padding_data(char *data, uint32_t padding_size) {
    memset(data, 'p', padding_size);
}

void set_checksum(int32_t *data) {
    *data = 123; // todo
}

int main() {
    simple_page_t *page = (simple_page_t *)malloc(simple_page_t::PAGE_SIZE);
    page->magic = 1001;
    page->version = 1;
    page->header_size = sizeof(*page);
    page->payload_size = serialize_data(page->data);
    page->padding_size = simple_page_t::PAGE_SIZE - page->header_size - page->payload_size - simple_page_t::CRC_SIZE;
    padding_data(page->data + page->header_size + page->payload_size, page->padding_size);
    set_checksum((int32_t*)page->data + simple_page_t::PAGE_SIZE - simple_page_t::CRC_SIZE);

    // write page (16KB) to file.
    printf("header-size = %dn", page->header_size);
}

就是这么简单,加上相关的测试代码总共才40行左右。

写在后面

本文就写到这里,你还了解哪些struct实用开发技巧呢,欢迎留言。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/352698.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号