总结常出现的求sizeof值的情况

本文详细解析了C/C++中sizeof运算符在不同情况下的应用,包括普通变量、指针变量、数组、结构体及类的使用场景,并探讨了内存对齐规则和特殊情况下的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


总结常出现的求sizeof值的情况

以前对于C/C++求一些变量的sizeof值很是疑惑,现在经过一段时间的了解,大致有个了解,现在对一些普遍存在,经常要求sizeof值得情况做个总结,整理了很长时间哦!

1. 普通变量的sizeof

普通变量的sizeof值就等于其类型的大小,与变量赋值没有关系。

例如:int n = 100;                  sizeof(n) = 4;

           double m =123.456   sizeof(m) = 8;

2. 指针变量的sizeof

指针变量的sizeof值与指针所指的对象没有任何关系,既然是存放地址的,那么它当然等于计算机内部地址总线的宽度。所以在32位计算机中,一个指针变量的sizeof是4(以字节为单位),在64位系统中指针变量的sizeof结果为8。

例如:char *pc = “abc”;                sizeof(pc) = 4;

            int *pi;                                   sizeof(pi) = 4;

            string *ps;                            sizeof(ps) = 4;

            char** ppc = &pc;                sizeof(ppc)= 4;

            void (*pf) ();(函数指针)   sizeof(pf) = 4;

3.  数组的sizeof

数组的sizeof值等于数组所占用的内存字节数。

(3.1)数组的长度=数组元素*类型大小

例如:char a1[] = “abc”;  sizeof(a1) = 3*1+1=4,注意:字符串末尾还存在一个空字符‘\0’

             int a2[3] = {1,2,3};  sizeof(a2) = 3*4=12

(3.2)数组元素个数=数组长度/类型大小

 例如:int c2 = sizeof(a2) /sizeof(int) = 3;

(3.3)数组“传址”(数组为函数参数)

     数组在作为函数参数时,数组是“传址”的,调用者只需将实参的地址传递过去,所以数组蜕变成指针类型。

     例如:void foo1(char a3[3])

           {

                      sizeof(a3) = 4;

           }

void foo2(char a4[])

{

           sizeof(a4) = 4;

}

4.  结构体的sizeof

     在没有#pragma pack宏的情况下,遵循以下三条内存对齐规则

     (1)数据成员对齐规则:结构(struct)里的数据成员,第一个数据成员放在offset=0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员(比如数组,结构体等)大小的整数倍开始。(int在32位机上为4字节,则要从4的整数倍地址开始存储)。

     (2)结构体作为成员:如果一个结构体里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那么b应该从8的整数倍开始存储)。

     (3)收尾工作:结构体的总大小,也就sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。

      例如:struct aa

                     {

                            int id;                   // offset=0,是4的倍数,不用扩大

                            double weight;  // offset=0+4=4不是8的倍数,扩大成offset=8

                            float height;       // offset=8+8=16是4的倍数,不用扩大

                                                       // offset=16+4=20不是8的倍数,扩大成offset=24

                     }AA;                          //sizeof(AA)=24;

                  struct bb

                   {

                            char name[2];            // offset=0,是2的倍数,不用扩大

                            int id;                           // offset=0+2=2,不是4的倍数,扩大成offset=4

                           double score;            // offset=4+4=8,是8的倍数,不用扩大

                           short t;                         // offset=8+8=16,是2的倍数,不用扩大

                          AA a;                            // offset=16+2=18,不是24的倍数,扩大成offset=24

                                                                // offset=24+24=48,是24的倍数,不用扩大

                 }BB;                                      //  sizeof(BB)=48;

5.  类的sizeof

(5.1)  空类的sizeof1。空类是指没有成员的类,类中的函数不占空间,除非是虚函数。

  例如:classA

               {

                public:

                       A(){}

                        ~A(){}

                        void fun(){}

                 };      //  sizeof(A)=1;

(5.2) 若类中包含成员,则类对象的大小只包括其中非静态成员经过对齐所占的空间,对齐方式和结构体相同。

例如:class B

               {

                public:

                 int b;

                             float c;

                             char d;

              };      //  sizeof(B)=12;

            class C

               {

                public:

                             static int a;

                 int b;

                             float c;

                             char d;

              };      //  sizeof(C)=12;

 (5.3) 在类中包含虚函数,则无论有几个虚函数,类的大小=数据成员的大小+4。

(因为编译器会为虚函数生成一张虚函数表,来记录对应的函数地址,因此在内存中只需要保存一个指向虚函数表的指针即可,指针大小为4.)

 例如:class D

               {

                public:

                             D(){}

                             ~D(){}

                              int a;

                              virtual void f(int) {}

                              virtual void f(double) {}

               };      //  sizeof(D)=8;

(5.4) 对于子类,它的类大小=父类大小+它的成员大小。(遵循对齐规则)

例如:classA1

      {

           public:

                     inta;

          private:

                   char b;

     };       //  sizeof(A1) = 8;

     class A2 : public A1

     {

          public:

                 char b;

                short a;

      };             //  8+1+2=11,不是4的倍数,由于对齐原则,sizeof(A2)=12

(5.5) 对于子类和父类中都有虚函数(但是不同的虚函数)的情况,子类的大小是父类的成员加上自己成员的大小,对齐后,再加上4。

       例如:classB1

               {

                public:

                             B1(){}

                             ~B1(){}

                              int a;

                              virtual void f(int){}

                              virtual void f(double){}

              };   

            class B2 : public B1

            {

             public:

                     B2() {}

                      int b;

                      virtual void g(int){}

              };           //  4+4=8,是4的倍数,已经对齐,所有sizeof(B2)=8+4=12

(5.6) 对于虚继承的子类,它的类大小等于父类大小加上它自己成员的大小,再加上它自己一个指向父类的指针(大小为4),对齐后的sizeof。

    例如:class a

               {

                 private:

                         int x;

               };         //   sizeof(a) = 4

              class b : virtual public a

             {

               private:

                        int y;

              };         //   sizeof(b)= 4+4+4=12,是4的倍数,满足对齐原则

            class c : virtual public b

           {

             private:

                   int z;

          };     //   sizeof(c)= 4+4+4=12,是4的倍数,满足对齐原则

         class d : public b,  public c

         {

            private:

                   int m;

         };       //   sizeof(d)=sizeof(b)+sizeof(c)-b和c相同的部分(a的成员大小,4)+自己的成员大小(4)=24

(5.7)   对于既有虚继承又有虚函数的子类,其类的大小等于父类大小(包括虚拟表指针,4)加上它自己的大小(包括虚拟表指针,4),再加上它自己一个指向父类的指针(大小为4),对齐后的sizeof值。

    例如:class B1

               {

                public:

                             B1(){}

                             ~B1(){}

                              virtual void f(int){}

                              virtual void f(double){}

               };    //  sizeof(B1)=4

               class B2 : virtual publicB1

               {

                public:

                        B2() {}

                        virtual void g(int){}

               };    //  sizeof(B2)=sizeof(B1)+4(自己的大小)+4(指向父类的指针)=12


好的,在 C/C++ 中,`sizeof` 运算符用于计算变量或型的大小(以字节为单位)。下面是关于 `str`、字符串 `"Hello"` 的指针以及整数 `10` 的详细解释: --- 假设我们在 64 位系统上运行,并且使用的是典型的 x86_64 架构环境。 ### 1. 字符串 "Hello" 的 sizeof ```c++ const char str[] = "Hello"; ``` 这里定义了一个字符数组 `str`,它的内容是字符串 `"Hello"`。 - **注意**:字符串量 `"Hello"` 实际是一个以 `\0` 结尾的字符序列,即包含 `'H', 'e', 'l', 'l', 'o', '\0'` 六个字符。 - 因此,`sizeof(str)` 返回的结果是这个字符数组的实际存储长度,也就是 **6 字节**(5 个字母加上 1 个空终止符)。 如果我们将它表示为一个指针: ```c++ const char* ptrStr = "Hello"; ``` 此时,`ptrStr` 只是指向该字符串第一个字符的地址,而不是整个字符串本身。因此: - `sizeof(ptrStr)` 返回的是指针本身的大小(在 64 位平台上通是 **8 字节**),而与实际指向的内容无关。 --- ### 2. 整数 10 的 sizeof 对于普通的整型变量 `int` 来说: ```c++ int num = 10; ``` - 在大多数现代系统中(包括 GCC 和 MSVC 编译器),`int` 型占用 **4 字节** 内存。 - 因此,`sizeof(num)` 或者直接用 `sizeof(10)` 都会得到结果 **4 字节**。 需要注意的是,这里的数 `10` 被视为量表达式的一部分,`sizeof` 计算时不会真正分配内存给数字 `10`,而是依据数据型推导出其大小。 --- ### 总结表 | 表达式 | 数据型 | Sizeof (单位: 字节) | |-----------------------|--------------------|-------------------------| | const char str[] | 数组 | 6 | | const char* ptrStr | 指针 | 8 (64 位平台下) | | int num | 整型 | 4 | --- ### 示例代码验证 你可以通过以下示例代码来验证上述结论: ```c++ #include <iostream> using namespace std; int main() { const char str[] = "Hello"; // 字符数组 const char* ptrStr = "Hello"; // 指针 int num = 10; // 整型 cout << "Size of array str: " << sizeof(str) << " bytes\n"; cout << "Size of pointer ptrStr: " << sizeof(ptrStr) << " bytes\n"; cout << "Size of integer num: " << sizeof(num) << " bytes\n"; return 0; } ``` 输出可能是这样的: ``` Size of array str: 6 bytes Size of pointer ptrStr: 8 bytes Size of integer num: 4 bytes ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值