C语言数据类型大小和结构体中变量的地址分配方法【整理】

 

数据类型: char  short   int   long   float   double   (long double)
gcc3.2.2
 1      2      4     4       4       8           12
Visual C++:1      2      4     4       4       8            8

对于数组的大小也比较简单,定义数组int a[10]后,sizeof(a)为所有数组元素大小之和,所以在Visual C++下其值为40,但是有一种特殊情况:

void function  (int array[10])     {         printf(/"%d//n/",sizeof(array));     }
int main(int argc , char *argv[])
{      
   int array[10];
   function(array);
   return 1;

这里的输出结果是4,因为C语言在数组作为参数的时候传递的只是地址,也就是在function这个函数用到的array只不过是个指针变量,其结果返回是4,因为:在Win32平台上地址为32位即指针变量的大小为4字节。顺便提一下关于main中那两个形式参数的意义,假定此main函数编译后为Test.exe的入口。如果在命令行模式(Windows下为cmdLinux下的shell)运行时,如果你输入 Test 字符串字符串2,那么系统在调用此main函数时就会把3传给argc(调用此程序的参数个数输入了3个,程序名也算作一个参数),把 “Test”“ 字符串1”“字符串2”存入字符指针数组argv中,在main函数中就可以使用这些传入的参数了,这样的例子有很多,比如在命令行下运行copy命令时就会输入 copy sourcefile destinationdirectory

    
共用体变量的所占字节数为最大数据类型成员的大小,例如 union Union { int i,char  ch}; Union test; test  的大小为4(int类型的大小)

    
枚举类型变量大小为4字节,本人猜测:编译器为了较好的处理字节对齐问题,将枚举类型变量的大小处理为4,不过至今还没有看到过相关的解释。
   
    
结构体类型变量的大小问题是一些公司招聘的时候很受青睐的题目。(本人在一次笔试中和在参加一本数据结构书的校对过程中曾碰到这个问题,遂写此文)在谭的书中没有涉及到这个问题,严格的说这是个跟编译器字节对齐关系挺大的问题,网上可以搜到很多类似问题的讨论。为了使CPU对变量的进行快速高效的访问,变量的起始地址应该满足某些特性,即所谓的对齐。关于字节对齐有两个重要的宏,#pragma pack (n)#pragma pack 第一个宏是强制编译器一般以n的倍数进行地址对齐(还有特殊情况以小于n的字节数进行对齐),第二个宏结束前面设置的对齐方式,恢复到编译器默认的对齐方式。在Visual C++下默认的字节对齐数为8
[Page]
     
结构体中的变量item在结构体中相对于首地址的偏移量应该是 X 的倍数,由如下式子确定:X=min(n,sizeof(item)),举个例子(n8):struct Test { char c1; char c2; int i};  如果定义了变量Test  t ,那么在存储 t  i  X 就应该是min(8sizeofint))即为4的倍数,即 i 相对于结构体首地址的偏移量必须是4的倍数,所以 t 的大小就应该为8字节(在c1c2后填充了两个字节以满足前述条件)。对于struct { char c1; char c2}不会出现填充的的情况,每个成员相对首地址的偏移量也满足是X的倍数(此时X1),其大小为2字节。
      
验证程序:

#include <stdio.h>
main()
{
 struct Test
  {char c1; 
   char c2; 
    int i;
  }; 
 struct Test t;
 t.c1=1;
 t.c2=2;
 t.i=3;
 printf(/"%d %d %d %d//n/",sizeof(t.c1),sizeof(t.c2),sizeof(t.i),sizeof t);
}
输出:
1148
    
而对于结构struct {char c1; double d;},默认情况下这种结构体变量占用16字节(在c1后填充了7个字节以满足字节对齐)。如果强制编译器以4字节对齐,即在声明这种结构的变量前面有#pragma pack (4),此时X4,则此种类型结构体变量占用的内存为12字节。

    
再看 struct {char c1; double d; char c2;}; 在默认字节对齐的方式下,输出其大小为24,呵呵,这是因为编译器还有一条规定:结构体变量的大小必须要为X(同上定义)的倍数,如果不满足,就会在最后一个成员后填充最少字节数以满足此条件。 如果定义此结构体前有#pragma pack(4),则输出大小为16

    
还有一种特殊情况,就是空结构体。在Visual C++下其大小为1,即struct{}类型的变量在VC下输出其大小是1,解释就是VC为每个结构体变量分配一个字节的内存,以使该变量有个地址;而在gcc下输出其大小为0,我的理解是既然此结构体一个成员都没有,程序中就不会访问它,因此也不必分配内存,如果编译器碰到有访问此结构体成员的情况就会报错。

最后一种情况,结构体成员中有结构体成员的情况,如 struct test1 {  char c1; int i ;  char c2 ;};        struct test2 { int i; struct test1 t1; char c2; };此时考虑在确定上述的X时会把t1拆散成基本数据类型来处理,而考虑test2结构大小时又会把t1作为一个整体来对待,但此时所谓的整体是把test1中确定的那个最大的X拿出来来确定test2X 故默认情况下,结构test2类型变量的大小为:20(test1中最大的X被确定为4test2中也为4t112个字节,在c2后又填充了3字节,总共20字节)。举个例子: [Page]
    struct  test1  {char c1;        double  d;           char c2;};
    struct test2  { int i;      struct test1 t1;        char c2;};
    
默认情况下,结构体test2的大小为40(最大的X被确定为8),强制4字节对齐时大小为24。其实这可以理解为编译器的另一条规则:结构体的大小必须为其最大的那个X的整数倍。

 

总结:

首先确定编译器的默认对齐方式或者#pragma packn)中n的值,然后遵守以下两条法则计算结构体分配的内存大小:

1.      结构体中的变量item在结构体中相对于首地址的偏移量应该是 X 的倍数,由如下式子确定:X=min(n,sizeof(item))

结构体的大小必须为其最大的那个X的整数倍。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 我可以回答你的问题。一般来说,怀孕6个月已经超过了法律规定的人工流产期限,属于违法行为。同时,这个时候的胎儿已经发育成形,医疗风险也很高,需要进行剖宫产手术。这种手术费用因医院和地区不同而异,一般比较昂贵,具体费用需要向当地的医院进行咨询。但无论费用多少,违法行为都是不可取的,建议妊娠期内妇女应该注意避孕,做好身体保健。 ### 回答2: C语言,非结构体变量结构体变量之间是不可以直接互换的。 非结构体变量是简单的基本类型变量,如int、float、char等,它们只包含一个值。而结构体变量是由多个不同类型的变量通过定义在一起组成的,代表一个复合的数据类型。 由于非结构体变量结构体变量的内存分配方式不同,它们的数据表达形式也不同。非结构体变量在内存是连续存放,占用一段连续的内存空间;而结构体变量是由其内部成员变量按照顺序依次存放在内存,成员变量之间可能会有空洞。 由于这两种类型的变量的内部数据体现方式不同,所以不能直接互换。当我们希望将一个结构体变量的值存放到结构体变量时,需要先将非结构体变量的值提取出来,然后将其赋给结构体变量的某个成员变量。同样地,当我们希望将结构体变量的值赋给非结构体变量时,需要提取结构体变量的某个成员变量的值,然后再进行赋值操作。 因此,虽然C语言可以通过一些复杂的操作实现非结构体变量结构体变量之间的互换,但是不能直接进行互换。 ### 回答3: C语言,非结构体变量结构体变量之间不能直接互换。因为非结构体变量结构体变量在内存的存储方式不同,因此不能直接进行赋值操作。 对于非结构体的基本变量类型,例如整型、浮点型等,它们的值可以通过赋值操作相互传递。例如,可以通过将一个整型变量的值赋给另一个整型变量来实现变量之间的互换。 而对于结构体变量,由于其具有多个成员变量,且每个成员变量的类型和长度可能不同,直接进行赋值是不允许的。如果想要互换结构体变量的值,需要通过逐个赋值或者使用memcpy函数等方式进行成员变量的拷贝。 例如,如果有两个结构体变量a和b,它们包含相同的成员变量,可以通过以下方式实现互换: ``` struct MyStruct { int x; float y; char z; }; struct MyStruct a = {1, 2.0, 'A'}; struct MyStruct b; // 使用逐个赋值方式实现互换 b.x = a.x; b.y = a.y; b.z = a.z; // 使用memcpy函数实现互换 memcpy(&b, &a, sizeof(struct MyStruct)); ``` 综上所述,C语言结构体变量结构体变量之间不能直接互换,需要根据具体情况使用赋值或者拷贝方式来实现值的传递。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值