sizeof 运算符的含义

373 阅读2分钟

1. sizeof 定义

sizeof 是一个关键字,它是一个编译时运算符,用于判断变量或数据类型的字节大小。

sizeof 运算符可用于获取类、结构、共用体和其他用户自定义数据类型的大小。

使用 sizeof 的语法如下:

sizeof (data type)

其中,data type 是要计算大小的数据类型,包括类、结构、共用体和其他用户自定义数据类型。

2.1 基本数据类型的sizeof

int main(int argc, const char * argv[]) {
    printf("bool-> %lu\n", sizeof(bool));
    printf("char-> %lu\n", sizeof(char));
    printf("short-> %lu\n", sizeof(short));
    printf("int-> %lu\n", sizeof(int));
    printf("long-> %lu\n", sizeof(long));
    printf("long long-> %lu\n", sizeof(long long));
    printf("NSInteger-> %lu\n", sizeof(NSInteger));
    printf("double-> %lu\n", sizeof(double));
    printf("float-> %lu\n", sizeof(float));
}

当上面的代码被编译和执行时,它会产生下列结果,结果会根据使用的机器而不同:

bool-> 1
char-> 1
short-> 2
int-> 4
long-> 8
long long-> 8
NSInteger-> 8
double-> 8
float-> 4

####2.2 结构体的sizeof

结构体的sizeof涉及到字节对齐问题。

参考[结构体内存对齐](#3. 内存对⻬的原则)

struct Struct1 {
    double a;   // 0-7
    char c;     // 8
    int b;      // 12 - 15
    short d;    // 16 - 17
}s1; 

struct Struct2 {
    double a; // 0-7
    int b;    // 8-12
    char c;  // 13
    short d; // 14 - 15
}s2;

struct Struct3 {
    double a; // 0 - 7
    struct Struct1 s; // 8-15 16 20-23 24-25
}s3;

struct Struct4 {
    double a1;   // 0 - 7
    double a;   //  8 - 15
    char c;    //   16
    int b;    //    20 - 23
    short d;  //    24 - 25
}s4;

int main() {
  	NSLog(@"s1->%lu",sizeof(s1));  // 24
    NSLog(@"s2->%lu",sizeof(s2));  // 16
		NSLog(@"s3->%lu",sizeof(s3));  // s3->32
    NSLog(@"s4->%lu",sizeof(s4));  // s4->32
  	return 0;
}

2.3 联合体的sizeof

结构体在内存组织上市顺序式的,联合体则是重叠式,各成员共享一段内存;所以整个联合体的sizeof也就是每个成员sizeof的最大值。

union un
{
    int a;
    float b;
    double c;
    char d;
}u;

printf("size of union %lu", sizeof(u)); // 8

我们一起看下 isa 的大小

#define __x86_64__ 1

typedef unsigned long           uintptr_t;

# if __arm64__
#   define ISA_MASK        0x0000000ffffffff8ULL
#   define ISA_MAGIC_MASK  0x000003f000000001ULL
#   define ISA_MAGIC_VALUE 0x000001a000000001ULL
#   define ISA_BITFIELD                                                      \
      uintptr_t nonpointer        : 1;                                       \
      uintptr_t has_assoc         : 1;                                       \
      uintptr_t has_cxx_dtor      : 1;                                       \
      uintptr_t shiftcls          : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \
      uintptr_t magic             : 6;                                       \
      uintptr_t weakly_referenced : 1;                                       \
      uintptr_t deallocating      : 1;                                       \
      uintptr_t has_sidetable_rc  : 1;                                       \
      uintptr_t extra_rc          : 19
#   define RC_ONE   (1ULL<<45)
#   define RC_HALF  (1ULL<<18)

# elif __x86_64__
#   define ISA_MASK        0x00007ffffffffff8ULL
#   define ISA_MAGIC_MASK  0x001f800000000001ULL
#   define ISA_MAGIC_VALUE 0x001d800000000001ULL
#   define ISA_BITFIELD                                                        \
      uintptr_t nonpointer        : 1;                                         \
      uintptr_t has_assoc         : 1;                                         \
      uintptr_t has_cxx_dtor      : 1;                                         \
      uintptr_t shiftcls          : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \
      uintptr_t magic             : 6;                                         \
      uintptr_t weakly_referenced : 1;                                         \
      uintptr_t deallocating      : 1;                                         \
      uintptr_t has_sidetable_rc  : 1;                                         \
      uintptr_t extra_rc          : 8
#   define RC_ONE   (1ULL<<56)
#   define RC_HALF  (1ULL<<7)

# else
#   error unknown architecture for packed isa
# endif
        
        
union m_isa_t {
    m_isa_t(){ }
    m_isa_t(uintptr_t value) : bits(value) { }

    Class cls;
    uintptr_t bits;
#if defined(ISA_BITFIELD)
    struct {
        ISA_BITFIELD;  // defined in isa.h
    };
#endif
};

测试结果

@implementation Test

+ (void)test {
    union m_isa_t isa1 = m_isa_t((uintptr_t)[Test class]);
    union m_isa_t isa2 = m_isa_t();
    isa2.cls = [NSObject class];
    
    printf("size of union isa1 %lu\n", sizeof(isa1));
    printf("size of union isa2 %lu\n", sizeof(isa2));
}

@end
  
// size of union isa1 8
// size of union isa2 8

2.4 指针的sizeof

指针是用来记录另一个对象的地址,所以指针的内存大小当然就等于计算机内部地址总线的宽度

在32位计算机中,一个指针变量的返回值必定是4。

指针变量的sizeof值与指针所指的对象没有任何关系。

		char *b = "helloworld";
    char *c[10];
    double *d;
    int **e;
    void (*pf)(void);
    
    printf("size of char * %lu\n", sizeof(b));
    printf("size of char *[] %lu\n", sizeof(c));
    printf("size of double %lu\n", sizeof(d));
    printf("size of int** %lu\n", sizeof(e));
    printf("size of function pointer %lu\n", sizeof(pf));

/**
     size of char * 8
     size of char ** 80 指针数组
     size of double 8
     size of int** 8
     size of function pointer 8
     */

2.5 数组的sizeof

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

  • 当字符数组表示字符串时,其sizeof值将’/0’计算进去。
  • 当数组为形参时,其sizeof值相当于指针的sizeof值。
char arr[10];
char arr2[] = "abc";
printf("size of arr %lu\n", sizeof(arr)); // size of arr 10
printf("size of arr2 %lu\n", sizeof(arr2)); // size of arr2 4


void func(char a[3])
{
    int c = sizeof(a); //c = 4,因为这里a不在是数组类型,而是指针,相当于char *a。
}
  
void funcN(char b[])
{
    int cN = sizeof(b); //cN = 4,理由同上。
} 

2.6 函数的sizeof

sizeof也可对一个函数调用求值,其结果是函数返回值类型的大小,函数并不会被调用。

对函数求值的形式:sizeof(函数名(实参表))

  • 不可以对返回值类型为空的函数求值。
  • 不可以对函数名求值。
  • 对有参数的函数,在用sizeof时,须写上实参表。

float FuncP(int a, float b)
{
    return a + b;
}

printf("size of function %lu\n", sizeof(FuncP(1,3))); //  size of function 4

3. 内存对⻬的原则

  1. 数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第

    一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要

    从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,

    结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存

    储。

  2. 结构体作为成员: 如果一个结构里有某些结构体成员,则结构体成员要从

    其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b

    里有char,int ,double等元素,那b应该从8的整数倍开始存储.)。

  3. 收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大

    成员的整数倍.不足的要补⻬。

www.runoob.com/cplusplus/c…

www.cnblogs.com/minmin123/p…