C/C++ sizeof用法以及结构体占用内存大小问题

参考链接:https://www.jb51.net/article/136259.htm

sizeof用法

1.它是什么?
2.可不可以跟变量名,其调用方式是什么样的?
3.C语言中sizeof函数的基本使用总结
4.C/C++ 中sizeof(‘a’)的值对比?
5.答案是什么?为什么?

  int i;
  i = 10;
  printf("%d\n", i);
  printf("%d\n", sizeof(i++));
  printf("%d\n", i);
  1. sizeof是操作符,本质就是运算符,跟加减乘除的性质其实是一样的,在编译的时候进行执行,而不是在运行时才执行。虽然我们经常见到sizeof后面跟着个小括号,长得和函数差不多,但它和函数完全是两码事。

  2. sizeof有三种语法形式,如下:
    1 sizeof( object ); // sizeof( 对象 );
    2 sizeof( type_name ); // sizeof( 类型 );
    3 sizeof object; // sizeof 对象;
    sizeof操作符的值与系统还有关系,一般的,在32位编译环境中,sizeof(int)的取值为4.
    特别地,对于指针的sizeof,等于计算机内部地址总线的宽度,所以在32位计算机中,一个指针变量的返回值必定是4(字节为单位)。

  3. 变量:变量所占的字节数
    数组:数组所占的字节数
    字符串:其实就是加了’\0’的字符数组。结果为字符串字符长度+1
    指针:固定长度4 (32位地址环境)
    特殊说明:数组作为函数的入口参数时,在函数中对数组sizeof,获得的结果固定为4,因为传入的参数是一个指针

int Get_Size(int arr[]) {
 return sizeof(arr);
}
 
int main() {
 int arr_int[10] = {1,2,3,4,5};
 printf("size_fun_arr=%d\n",Get_Size(arr_int)); //4
}
//  C语言                                C++语言
char a = 'a';                           char a = 'a';
sizeof(char) = 1;                       sizeof(char) = 1;
sizeof(a) = 1;                          sizeof(a) = 1;
sizeof('a') = 4;                        sizeof('a') = 1;

字符型变量是1字节这个没错,奇怪就奇怪在C语言认为’a’是4字节,而C++语言认为’a’是1字节
原因如下:
C99标准的规定,'a’叫做整型字符常量(integer character constant),被看成是int型,所以在32位机器上占4字节。
ISO C++标准规定,'a’叫做字符字面量(character literal),被看成是char型,所以占1字节。

5.
10 4 10
C++标准:如果sizeof的操作数是一个表达式的话,这个表达式时不会被计算的。sizeof当预处理看就行了,它后面括号里的东西,根本不求值,只根据C的一堆规则判断结果类型,然后返回结果类型的大小。

结构体占用内存大小问题

结构体:
结构体成员是按照声明的顺序存储在连续的内存空间中,而结构体成员的类型不一定相同,系统在存储结构体时不是像数组一样将各个成员大小简单相加,而需要考虑地址对齐问题。

结构体存储变量的地址对齐有两个规则
1.结构体中成员变量的地址偏移量必须是该成员大小的整数倍
2.结构体大小必须是所有成员大小的整数倍。

偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体变量中第一个成员的地址就是结构体变量的首地址。因此,第一个成员的偏移量为0。第二个成员的偏移量是第一个成员的偏移量加上第一个成员的大小;第三个成员的偏移量是第二个成员的偏移量加上第二个成员的大小。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。

1.只含变量的结构体:
#include <stdio.h>
#include <stdlib.h>

typedef struct test1 {
int i;
char ch;
}test_t1;

typedef struct test2 {
int i;
short s;
char ch1;
char ch2;
}test_t2;


typedef struct test3 {
int i;
char ch1;
short s;
char ch2;
}test_t3;


int main()
{
    printf("the sizeof test_t1 is %d\n",sizeof(test_t1));//8
    printf("the sizeof test_t2 is %d\n",sizeof(test_t2));//8
    printf("the sizeof test_t3 is %d\n",sizeof(test_t3));//12
    return 0;
}

对于结构体test_t3
第一个成员的偏移量为0,
第二个成员的偏移量是第一个成员的偏移量加上第一个成员i的大小0+4=4;
第三个成员的偏移量是第二个成员的偏移量加上第二个成员的大小4+1=5,此时不满足条件1(不是sizeof(short)的整数倍),因此增加为5+1=6;
第四个成员的偏移量是第三个成员的偏移量加上第三个成员的大小6+2=8;
结构体大小等于最后一个成员的偏移量加上最后一个成员的大小8+1=9,此时不满足条件2,因此9+3=12。
故结构体的大小为12。

2.含数组的结构体:
#include <stdio.h>
#include <stdlib.h>

struct s1{
char ch;
int i;
char str[10];
}s11;

struct s12{
int i;
char ch;
char str[10];
}s12;

int main()
{
    printf("the sizeof s11 is %d\n",sizeof(s11)); //20
    printf("the sizeof s12 is %d\n",sizeof(s12)); //16
    return 0;
}

对于结构体变量s11
第一个成员的偏移量为0,
第二个成员的偏移量是第一个成员的偏移量加上第一个成员i的大小0+1=1;此时不满足条件1(不是sizeof(int)的整数倍),因此增加为1+3=4;
第三个成员的偏移量是第二个成员的偏移量加上第二个成员的大小4+4=8;
结构体大小等于最后一个成员的偏移量加上最后一个成员的大小8+10=18,此时不满足条件2,因此18+2=20,满足条件。
故结构体的大小为20。
对于结构体变量s12
第一个成员的偏移量为0,
第二个成员的偏移量是第一个成员的偏移量加上第一个成员i的大小0+4=4;
第三个成员的偏移量是第二个成员的偏移量加上第二个成员的大小4+1=5;
结构体大小等于最后一个成员的偏移量加上最后一个成员的大小5+10=15,此时不满足条件2,因此15+1=16,满足条件。
故结构体的大小为16。
注意:这里把数组 char str[10]就看作是10个char 类型的数据就好。

3.嵌套结构体的结构体

包含整个内部结构体的宽度(即整个展开的内部结构体)
上述两个原则需要修改一下
1.展开后的结构体的第一个成员的偏移量(嵌套的结构体偏移量)应当是被展开的结构体中最大成员的整数倍;
2.结构体大小必须是所有成员大小的整数倍,这里计算的是展开后的成员,而不是将嵌套的结构体看作一个整体。

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

typedef struct son1 {
int name;
int birthday;
}son_t1;

typedef struct father1 {
son_t1 s1;
int wife;
}father_t1;


typedef struct son2 {
short age;
int name;
int birthday;
}son_t2;

typedef struct father2 {
short age;
son_t2 s1;
int wife;
}father_t2;

int main()
{
    printf("the sizeof father_t1 is %d\n",sizeof(father_t1)); //12,不用解释
    printf("the sizeof father_t2 is %d\n",sizeof(father_t2)); //20
    return 0;
}

对于结构体变量father_t2
嵌套结构体展开后的变量类型分别为
short 偏移量为0
short 偏移量为 0+2=2 但是因为是嵌套,所以它必须满足条件1,因此必须是嵌套的成员里最大成员 int 的整 数倍,因此2+2=4
int 偏移量 4+2=6 同理 6+2=8
int 偏移量 8-4=12
int 偏移量 12+4=16
结构体大小等于16+4=20

总结:

了解结构体存储方式后,我们可以发现把占用内存越大的变量放在前面更能充分地利用内存,减少地址对齐带来的空间损失

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值