sizeof的定义:

sizeof是C/C++中的一个操作符(operator),简单的说其作用就是返回一个对象或者类型所占的内存字节数。

MSDN上的解释为:

The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type(including aggregate types). This keyword returns a value of type size_t.

sizeof关键字提供与变量或类型(包括聚合类型)关联的存储量(以字节为单位)。此关键字返回一个size_t类型的值。看到返回,但不要认为这是一个函数。

对于sizeof的理解,sizeof:

首先是一个关键字,也是一个操作符,而非函数。

其次求长度,返回一个对象或者类型所占的内存字节数。

总结一下:sizeof更像一个特殊的宏,它是在编译阶段求值的。不要把sizeof当成函数,也不要看作一元操作符,把他当成一个特殊的编译预处理。

sizeof(数组),结果是数组所占的空间大小;

sizeof(指针),结果又是什么呢? sizeof(指针),其结果和操作系统有关,32位操作系统返回值4,64位操作系统返回值8。

再来理解这句话:sizeof求长度,返回一个对象或者类型所占的内存字节数。那么sizeof(指针),就是返回指针在内存中占用空间大小;

接着在问一个问题,不同的指针在操作系统中占用的空间大小是一样的吗?答案是肯定的,不同的指针类型在操作系统中占用的空间大小是一样的。

在写代码时,还会遇到对一个常量字符串求长度,例如:对123456字符串求长度,

printf("sizeof(123456)=%d\n", sizeof("123456"));

这个打印结果是7,是否超出了你的预期。对于sizeof("xxx"),对于""中的字符串,sizeof操作求长度,默认后面还有一个\0,所以实际的长度要+1。

printf("sizeof(1+1.2)=%d\n", sizeof(1+1.2));

 这个打印结果是8,是否又超出了你的预期。

sizeof(express),其中的express在编译过程中是不会被编译的,而是被替代类型。

     例如: int a = 1; sizeof(a=2);

     此时的express为a=2,在编译过程中被替换为sizeof(int),所以在执行完之后,a仍然是等于1。

所以sizeof(1+1.2) 在编译过程中被替换成double类型的,double占8个字节。

用一个程序来验证一下:

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

typedef struct
{
    int a;
    char buf[20];
}Node_t;

int get_array_point_size(int *data)
{
    printf("\narray pointer size %d\n", sizeof(data));
    return 0;
}

int main()
{
    char *q=NULL;
    float *f=NULL;
    Node_t *node =NULL;
    
    int a[5]={1,2,3,4,5};
    int *p=a;
    
    printf("p = %p\n",p);
    int *ptr = (int *)(&a+1);

    printf("ptr=%p\n",ptr);
    printf("%d   %d\n",*(a+1),*(ptr-1));

    printf("sizeof(ptr-1) = %d\n",sizeof(ptr-1));


    printf("sizeof(q)=%d\n", sizeof(q));
    printf("sizeof(f)=%d\n", sizeof(f));
    printf("sizeof(node)=%d\n\n", sizeof(node));

    printf("sizeof(a)=%d\n", sizeof(a));
    printf("sizeof(*q)=%d\n", sizeof(*q));
    printf("sizeof(*f)=%d\n", sizeof(*f));
    printf("sizeof(*node)=%d\n", sizeof(*node));

    printf("sizeof(123456)=%d\n", sizeof("123456"));

    get_array_point_size(a);

    return 0;
}

//运行结果
root@ubuntu140453200:/mnt/external/root/test/linux_c$ ./sizeof_1
p  =0x7ffd7485fa10
ptr=0x7ffd7485fa24
2   5
sizeof(ptr-1)=8
sizeof(q)=8
sizeof(f)=8
sizeof(nood)=8

sizeof(a)=20
sizeof(*q)=1
sizeof(*f)=4
sizeof(*nood)=24
sizeof(123456)=7

array pointer size 8
root@ubuntu140453200:/mnt/external/root/test/linux_c$

补充说明,32位编译器,64位编译器的对数据类型的大小定义不一样。 

        

各位看官,看到这里可能有一个问题,如果是数组作为参数传入到函数,那么这个数组在函数内部进行sizeof求长度结果是什么? 结果也是8个字节。

这里面有一段指针的内容:

    int a[5]={1,2,3,4,5};
    int *p=a;
    
    printf("p = %p\n",p);
    int *ptr = (int *)(&a+1);

    printf("ptr=%p\n",ptr);
    printf("%d   %d\n",*(a+1),*(ptr-1));

    printf("sizeof(ptr-1) = %d\n",sizeof(ptr-1));

下面来讲一下这个指针:

int a[5] = {1, 2, 3, 4, 5}; 表示 a 是一个数组,里面有五个成员;

a 表示这个数组的首地址,

a[0] 表示数组的第一个元素,

&a 表示对数组的首地址进行取址操作,这个操作其实是二维操作,将 a 看做一个二维数组,即 a[][5],相当于a[0]

&a + 1  表示将数组a,看做一个二维数组,&a 表示二维数组的第一维度的首地址,&a + 1 表示第一维度的第二组的首地址,即 a[][5], 相当于 a[1]

ptr = (int *)(&a + 1) 表示将 ptr 指向了二维数组的 a[1], 把 a 看做一个二维数组。但是这个访问是非法的,产生越界了。如果直接访问ptr的内容,程序会挂掉。

(ptr - 1) 表示的就是 a[1][0] - 1 减去一个数组成员,即a[0][5],这个访问是合法的

所以最后打印的结果就是:

p  =0x7ffd7485fa10
ptr=0x7ffd7485fa24
2   5

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐