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