数据类型所占大小

时间:2023-01-11 17:54:28
这是一道关于数据大小的题目,求下面结构体的大小,我计算了应该是sizeof(char)+sizeof(int)+sizeof(float)+sizeof(double)+sizeof(int*)+sizeof(char*)+sizeof(short)=1+4+4+8+4++4+2=27,可答案为什么事40啊?用程序测试了一下sizeof(A)也的确是等于40,但是结构体中每个成员变量的大小我计算的又是正确的,这是为什么啊?

#include <stdio.h>
#include <stdlib.h>

typedef struct A
{
char a;
int b;
float c;
double d;
int *e;
char *f;
short g;
}A;


int main(int argc, char *argv[]) 
{
printf("sizeof A=%d\n",sizeof(A));

printf("sizeof char=%d\n",sizeof(char));
printf("sizeof int=%d\n",sizeof(int));
printf("sizeof float=%d\n",sizeof(float));
printf("sizeof double=%d\n",sizeof(double));
printf("sizeof int*=%d\n",sizeof(int*));
printf("sizeof char*=%d\n",sizeof(char*));
printf("sizeof short=%d\n",sizeof(short));

return 0;
}

程序运行截图:
数据类型所占大小

9 个解决方案

#1


搜“c语言结构体字节对齐”

#2


项目属性可以设置 字节对齐方式
32位操作系统默认应该是 32bit
也就是每个成员变量的起始地址是4字节的倍数
是一个char  a[1] 和 a[4]占有的空间一样

#3


引用 1 楼 FightForProgrammer 的回复:
搜“c语言结构体字节对齐”
+1 数据类型所占大小

#4


结构体的对齐和补齐,在32位机上是按照4个字节进行对齐和补齐的。即小于4个字节的数据类型会自动转换为4个字节。大于或者是等于4个字节的。会保存4个字节的倍数。你还可以去看一下大小端的问题。也是用的这个原理。

#5


引用 4 楼 woai_tudou 的回复:
结构体的对齐和补齐,在32位机上是按照4个字节进行对齐和补齐的。即小于4个字节的数据类型会自动转换为4个字节。大于或者是等于4个字节的。会保存4个字节的倍数。你还可以去看一下大小端的问题。也是用的这个原理。


你的意思是
sizeof (struct {char c;})

的结果是4??

#6


在 结构定义前加上 #pragma pack(1) 再试试

#7


仅供参考:
#include <stdio.h>
#define field_offset(s,f) (int)(&(((struct s *)(0))->f))
struct AD  { int a; char b[13]; double c;};
#pragma pack(push)
#pragma pack(1)
struct A1  { int a; char b[13]; double c;};
#pragma pack(2)
struct A2  { int a; char b[13]; double c;};
#pragma pack(4)
struct A4  { int a; char b[13]; double c;};
#pragma pack(8)
struct A8  { int a; char b[13]; double c;};
#pragma pack(16)
struct A16 { int a; char b[13]; double c;};
#pragma pack(pop)
int main() {
    printf("AD.a %d\n",field_offset(AD,a));
    printf("AD.b %d\n",field_offset(AD,b));
    printf("AD.c %d\n",field_offset(AD,c));
    printf("\n");
    printf("A1.a %d\n",field_offset(A1,a));
    printf("A1.b %d\n",field_offset(A1,b));
    printf("A1.c %d\n",field_offset(A1,c));
    printf("\n");
    printf("A2.a %d\n",field_offset(A2,a));
    printf("A2.b %d\n",field_offset(A2,b));
    printf("A2.c %d\n",field_offset(A2,c));
    printf("\n");
    printf("A4.a %d\n",field_offset(A4,a));
    printf("A4.b %d\n",field_offset(A4,b));
    printf("A4.c %d\n",field_offset(A4,c));
    printf("\n");
    printf("A8.a %d\n",field_offset(A8,a));
    printf("A8.b %d\n",field_offset(A8,b));
    printf("A8.c %d\n",field_offset(A8,c));
    printf("\n");
    printf("A16.a %d\n",field_offset(A16,a));
    printf("A16.b %d\n",field_offset(A16,b));
    printf("A16.c %d\n",field_offset(A16,c));
    printf("\n");
    return 0;
}
//AD.a 0
//AD.b 4
//AD.c 24
//
//A1.a 0
//A1.b 4
//A1.c 17
//
//A2.a 0
//A2.b 4
//A2.c 18
//
//A4.a 0
//A4.b 4
//A4.c 20
//
//A8.a 0
//A8.b 4
//A8.c 24
//
//A16.a 0
//A16.b 4
//A16.c 24
//
//

#8


引用 7 楼 zhao4zhong1 的回复:
仅供参考:
#include <stdio.h>
#define field_offset(s,f) (int)(&(((struct s *)(0))->f))
struct AD  { int a; char b[13]; double c;};
#pragma pack(push)
#pragma pack(1)
struct A1  { int a; char b[13]; double c;};
#pragma pack(2)
struct A2  { int a; char b[13]; double c;};
#pragma pack(4)
struct A4  { int a; char b[13]; double c;};
#pragma pack(8)
struct A8  { int a; char b[13]; double c;};
#pragma pack(16)
struct A16 { int a; char b[13]; double c;};
#pragma pack(pop)
int main() {
    printf("AD.a %d\n",field_offset(AD,a));
    printf("AD.b %d\n",field_offset(AD,b));
    printf("AD.c %d\n",field_offset(AD,c));
    printf("\n");
    printf("A1.a %d\n",field_offset(A1,a));
    printf("A1.b %d\n",field_offset(A1,b));
    printf("A1.c %d\n",field_offset(A1,c));
    printf("\n");
    printf("A2.a %d\n",field_offset(A2,a));
    printf("A2.b %d\n",field_offset(A2,b));
    printf("A2.c %d\n",field_offset(A2,c));
    printf("\n");
    printf("A4.a %d\n",field_offset(A4,a));
    printf("A4.b %d\n",field_offset(A4,b));
    printf("A4.c %d\n",field_offset(A4,c));
    printf("\n");
    printf("A8.a %d\n",field_offset(A8,a));
    printf("A8.b %d\n",field_offset(A8,b));
    printf("A8.c %d\n",field_offset(A8,c));
    printf("\n");
    printf("A16.a %d\n",field_offset(A16,a));
    printf("A16.b %d\n",field_offset(A16,b));
    printf("A16.c %d\n",field_offset(A16,c));
    printf("\n");
    return 0;
}
//AD.a 0
//AD.b 4
//AD.c 24
//
//A1.a 0
//A1.b 4
//A1.c 17
//
//A2.a 0
//A2.b 4
//A2.c 18
//
//A4.a 0
//A4.b 4
//A4.c 20
//
//A8.a 0
//A8.b 4
//A8.c 24
//
//A16.a 0
//A16.b 4
//A16.c 24
//
//

+1

#9


typedef struct A
{
  char a;   
  int b;   
  float c;   
  double d;  
  int *e; 
  char *f;  
  short g;
}A;
该struct中,double类型所占空间最大,故此该struct为8字节对齐方式,a和b占据8个字节,c占据8个字节,d占据8个字节,两个指针占据8个字节,最后一个short占据8个字节,一共是40个字节。
内存对齐技术是一种以空间换取读取效率的做法,比如b,应该是从第5个字节存储到第8个字节,字节偏移为4,实际上就是要struct实例对象的基地址+字节偏移4能够整除b的类型大小(int为4)。具体你可以打印出所有struct成员的地址来看看内存排布,PS:打印a地址的时候,请注意将其强制转换为(void*),否则打印出来的不是地址值。

#1


搜“c语言结构体字节对齐”

#2


项目属性可以设置 字节对齐方式
32位操作系统默认应该是 32bit
也就是每个成员变量的起始地址是4字节的倍数
是一个char  a[1] 和 a[4]占有的空间一样

#3


引用 1 楼 FightForProgrammer 的回复:
搜“c语言结构体字节对齐”
+1 数据类型所占大小

#4


结构体的对齐和补齐,在32位机上是按照4个字节进行对齐和补齐的。即小于4个字节的数据类型会自动转换为4个字节。大于或者是等于4个字节的。会保存4个字节的倍数。你还可以去看一下大小端的问题。也是用的这个原理。

#5


引用 4 楼 woai_tudou 的回复:
结构体的对齐和补齐,在32位机上是按照4个字节进行对齐和补齐的。即小于4个字节的数据类型会自动转换为4个字节。大于或者是等于4个字节的。会保存4个字节的倍数。你还可以去看一下大小端的问题。也是用的这个原理。


你的意思是
sizeof (struct {char c;})

的结果是4??

#6


在 结构定义前加上 #pragma pack(1) 再试试

#7


仅供参考:
#include <stdio.h>
#define field_offset(s,f) (int)(&(((struct s *)(0))->f))
struct AD  { int a; char b[13]; double c;};
#pragma pack(push)
#pragma pack(1)
struct A1  { int a; char b[13]; double c;};
#pragma pack(2)
struct A2  { int a; char b[13]; double c;};
#pragma pack(4)
struct A4  { int a; char b[13]; double c;};
#pragma pack(8)
struct A8  { int a; char b[13]; double c;};
#pragma pack(16)
struct A16 { int a; char b[13]; double c;};
#pragma pack(pop)
int main() {
    printf("AD.a %d\n",field_offset(AD,a));
    printf("AD.b %d\n",field_offset(AD,b));
    printf("AD.c %d\n",field_offset(AD,c));
    printf("\n");
    printf("A1.a %d\n",field_offset(A1,a));
    printf("A1.b %d\n",field_offset(A1,b));
    printf("A1.c %d\n",field_offset(A1,c));
    printf("\n");
    printf("A2.a %d\n",field_offset(A2,a));
    printf("A2.b %d\n",field_offset(A2,b));
    printf("A2.c %d\n",field_offset(A2,c));
    printf("\n");
    printf("A4.a %d\n",field_offset(A4,a));
    printf("A4.b %d\n",field_offset(A4,b));
    printf("A4.c %d\n",field_offset(A4,c));
    printf("\n");
    printf("A8.a %d\n",field_offset(A8,a));
    printf("A8.b %d\n",field_offset(A8,b));
    printf("A8.c %d\n",field_offset(A8,c));
    printf("\n");
    printf("A16.a %d\n",field_offset(A16,a));
    printf("A16.b %d\n",field_offset(A16,b));
    printf("A16.c %d\n",field_offset(A16,c));
    printf("\n");
    return 0;
}
//AD.a 0
//AD.b 4
//AD.c 24
//
//A1.a 0
//A1.b 4
//A1.c 17
//
//A2.a 0
//A2.b 4
//A2.c 18
//
//A4.a 0
//A4.b 4
//A4.c 20
//
//A8.a 0
//A8.b 4
//A8.c 24
//
//A16.a 0
//A16.b 4
//A16.c 24
//
//

#8


引用 7 楼 zhao4zhong1 的回复:
仅供参考:
#include <stdio.h>
#define field_offset(s,f) (int)(&(((struct s *)(0))->f))
struct AD  { int a; char b[13]; double c;};
#pragma pack(push)
#pragma pack(1)
struct A1  { int a; char b[13]; double c;};
#pragma pack(2)
struct A2  { int a; char b[13]; double c;};
#pragma pack(4)
struct A4  { int a; char b[13]; double c;};
#pragma pack(8)
struct A8  { int a; char b[13]; double c;};
#pragma pack(16)
struct A16 { int a; char b[13]; double c;};
#pragma pack(pop)
int main() {
    printf("AD.a %d\n",field_offset(AD,a));
    printf("AD.b %d\n",field_offset(AD,b));
    printf("AD.c %d\n",field_offset(AD,c));
    printf("\n");
    printf("A1.a %d\n",field_offset(A1,a));
    printf("A1.b %d\n",field_offset(A1,b));
    printf("A1.c %d\n",field_offset(A1,c));
    printf("\n");
    printf("A2.a %d\n",field_offset(A2,a));
    printf("A2.b %d\n",field_offset(A2,b));
    printf("A2.c %d\n",field_offset(A2,c));
    printf("\n");
    printf("A4.a %d\n",field_offset(A4,a));
    printf("A4.b %d\n",field_offset(A4,b));
    printf("A4.c %d\n",field_offset(A4,c));
    printf("\n");
    printf("A8.a %d\n",field_offset(A8,a));
    printf("A8.b %d\n",field_offset(A8,b));
    printf("A8.c %d\n",field_offset(A8,c));
    printf("\n");
    printf("A16.a %d\n",field_offset(A16,a));
    printf("A16.b %d\n",field_offset(A16,b));
    printf("A16.c %d\n",field_offset(A16,c));
    printf("\n");
    return 0;
}
//AD.a 0
//AD.b 4
//AD.c 24
//
//A1.a 0
//A1.b 4
//A1.c 17
//
//A2.a 0
//A2.b 4
//A2.c 18
//
//A4.a 0
//A4.b 4
//A4.c 20
//
//A8.a 0
//A8.b 4
//A8.c 24
//
//A16.a 0
//A16.b 4
//A16.c 24
//
//

+1

#9


typedef struct A
{
  char a;   
  int b;   
  float c;   
  double d;  
  int *e; 
  char *f;  
  short g;
}A;
该struct中,double类型所占空间最大,故此该struct为8字节对齐方式,a和b占据8个字节,c占据8个字节,d占据8个字节,两个指针占据8个字节,最后一个short占据8个字节,一共是40个字节。
内存对齐技术是一种以空间换取读取效率的做法,比如b,应该是从第5个字节存储到第8个字节,字节偏移为4,实际上就是要struct实例对象的基地址+字节偏移4能够整除b的类型大小(int为4)。具体你可以打印出所有struct成员的地址来看看内存排布,PS:打印a地址的时候,请注意将其强制转换为(void*),否则打印出来的不是地址值。