分析c语言的struct 的大小

本文深入探讨了结构体在VC环境中大小计算的微妙之处,通过实验揭示了填充字节的存在及其对结构体大小的影响,并分享了解决方案。


  说起结构struct,大家不会陌生,c语言中常用的一种数据类型,说起它的长度,也没啥新鲜的,不外乎把成员变量之长度加起来,聪明一点的还会接着告诉你,这是它和union的一大区别。近日来笔者鸟枪换炮,用上了vc5.0,在感受它的方便与强大的同时,也受到了形形色色的困扰,struct这个小东西就是其中之一。

  我用cfile类的一个对象操作一个文件,文件是由struct类型变量组成的,成员变量有7个float型,1个char型,char型变量占1字节,float型变量占4字节,4×7+1,我上小学的妹妹都会告诉你等于29,c语言中的sizeof(struct structname)自然更不会算错,fread(ptr,size,item,filehandle)用sizeof(struct structname)来控制每次读取的长度也很ok,可是我在vc中却遇到了麻烦,下面是我的程序,您也可以帮我挑挑错,不过可不要偷看后面的答案。

......

  struct data data1;

  lpctstr pfilename="s001.psd";

  cfile file(pfilename,cfile::moderead);

  int count=file.getlength()/sizeof(struct data);

  //得到文件中记录个数

  for(;count>0;count--)

{file.read(&data1,sizeof(struct data));

//以下是显示记录内容,因不用保存,只定义一个结构变量

......

}

  file.close();

......

  不知您看的效果如何,我的程序可是一团糟,显示的不是我想象中的模样。原因何在呢?我上看下看,左看右看,看不出所以然来。只好换法子来实现,cfile的成员函数是换不成,只有sizeof(struct data)了,不经意地把sizeof(struct data)改成了29,又不经意地一运行,竟然ok了!把sizeof(struct data)的结果显示出来,更惊诧了,32个字节!为了探究其中奥秘,我使用了物理学家常用的方法——实验法。我又定义了几个结构变量:

  struct test1

  {char a;

  int b;

  }test_1;

struct test2

  {char a;

   double b;

  }test_2;

  struct test3

  {char a;

  char b;

  char c;

  }test_3;

  struct test4

  {char a;

  int b;

  double c;

}test_4;

  不知您的结果如何,下面公布正确答案:

  sizeof(struct test1)=8

  sizeof(struct test2)=16

  sizeof(struct test3)=3

  sizeof(struct test4)=16

  都对了?希望不会,要不然下面的文章您就不看了。

  发现问题还得解决问题,凭着我的可怜的英语知识,在vc的帮助下,得到了一点说明,有兴趣并且英语好的同志可以查看#pragma pack(n)的帮助。出于兼容性的考虑,在结构变量有填充字节之说,上面的结果就是在默认情况下的结果,vc会根据结构变量中成员变量的类型来调整填充字节,您也可以用#pragma pack(n)中的n来指定填充字节,n可以取1,2,4,8等,如等于1,结果就会如同dos下c语言中sizeof(struct structname)的结果。一点小经验,拿出来共享,祝大家编程快乐!

C语言标准库中并没有直接提供 `struct HashMap` 这样的数据结构,但可以通过自定义结构体和相关函数来实现一个简单的哈希表(HashMap)。以下是一个简单的实现示例,使用链表法处理哈希冲突: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 定义哈希表的大小 #define TABLE_SIZE 100 // 定义链表节点结构体 typedef struct Node { char *key; int value; struct Node *next; } Node; // 定义哈希表结构体 typedef struct { Node *table[TABLE_SIZE]; } HashMap; // 哈希函数 unsigned int hash(const char *key) { unsigned int hashval = 0; for (int i = 0; key[i] != '\0'; i++) { hashval = key[i] + (hashval << 6) + (hashval << 16) - hashval; } return hashval % TABLE_SIZE; } // 初始化哈希表 void initHashMap(HashMap *map) { for (int i = 0; i < TABLE_SIZE; i++) { map->table[i] = NULL; } } // 插入键值对 void insert(HashMap *map, const char *key, int value) { unsigned int index = hash(key); Node *newNode = (Node *)malloc(sizeof(Node)); newNode->key = strdup(key); newNode->value = value; newNode->next = map->table[index]; map->table[index] = newNode; } // 根据键查找值 int get(HashMap *map, const char *key) { unsigned int index = hash(key); Node *current = map->table[index]; while (current != NULL) { if (strcmp(current->key, key) == 0) { return current->value; } current = current->next; } return -1; // 未找到 } // 释放哈希表内存 void freeHashMap(HashMap *map) { for (int i = 0; i < TABLE_SIZE; i++) { Node *current = map->table[i]; while (current != NULL) { Node *temp = current; current = current->next; free(temp->key); free(temp); } } } int main() { HashMap map; initHashMap(&map); insert(&map, "key1", 10); insert(&map, "key2", 20); int value = get(&map, "key1"); if (value != -1) { printf("Value for key1: %d\n", value); } freeHashMap(&map); return 0; } ``` ### 代码解释 1. **结构体定义**: - `Node` 结构体用于表示链表节点,包含键、值和指向下一个节点的指针。 - `HashMap` 结构体包含一个指向 `Node` 指针的数组,用于存储链表头节点。 2. **哈希函数**:`hash` 函数将键转换为哈希表的索引。 3. **初始化**:`initHashMap` 函数将哈希表的所有元素初始化为 `NULL`。 4. **插入操作**:`insert` 函数根据键的哈希值找到对应的链表,将新节点插入到链表头部。 5. **查找操作**:`get` 函数根据键的哈希值找到对应的链表,遍历链表查找键对应的节点。 6. **释放内存**:`freeHashMap` 函数释放哈希表中所有节点的内存。 ### 复杂度分析 - **时间复杂度**:插入和查找操作的平均时间复杂度为 $O(1)$,最坏情况下为 $O(n)$,其中 $n$ 是链表的长度。 - **空间复杂度**:$O(m)$,其中 $m$ 是哈希表的大小
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值