sizeof详解

来源:互联网 发布:欧洲历史 知乎 编辑:程序博客网 时间:2024/06/16 19:13

转载请注明出处:
http://blog.sina.com.cn/s/blog_5da08c340100bmwu.html


一、sizeof的概念  

sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等。
并不是函数
sizeof操作符以字节形式给出了其操作数的存储大小。
操作数可以是一个表达式或括在括号内的类型名。
操作数的存储大小由操作数的类型决定。    

二、sizeof的使用方法 
 

  1、用于数据类型    

  sizeof使用形式: sizeof(type)
  数据类型必须用括号括住: sizeof(int)

  2、用于变量    

sizeof使用形式: sizeof(var_name) 或 sizeof var_name    
变量名可以不用括号括住.如sizeof (var_name),sizeof var_name等都是正确形式
带括号的用法更普遍,大多数程序员采用这种形式。    

  注意:sizeof操作符不能用于函数类型,不完全类型或位字段。
          不完全类型指具有未知存储大小的数据类型,
          如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。    
  例如: sizeof(max)       
 --
若此时变量max定义为int max();
          sizeof(char_v)    --若此时char_v定义为char char_v[MAX]且MAX未知,
          sizeof(void)      
          以上都是不正确形式。    

三、sizeof的结果(以下结果都是在Linux v2.6 gcc v4获取)

sizeof操作符的结果类型是size_t
它在头文件中定义为: typedef unsigned int size_t;
该类型保证能容纳实现所建立的最大对象的字节大小.

  1、ANSI C正式规定字符类型为1字节。    

sizeof(char)          = 1;
sizeof(unsigned char) = 1;
sizeof(signed char)   = 1;
  
  2、其他类型在ANSI C中没有具体规定,大小依赖于实现。
    
sizeof(int)            = 4;
sizeof(unsigned int)   = 4;
sizeof(short int)      = 2;
sizeof(unsigned short) = 2;
sizeof(long int)       = 4;
sizeof(unsigned long)  = 4;
sizeof(float)          = 4;
sizeof(double)         = 8;
sizeof(long double)    = 12;

  3、当操作数是指针时,sizeof依赖于编译器。
   
Microsoft C/C++7.0中,near类指针字节数为2,far、huge类指针字节数为4。
一般Unix/Linux的指针字节数为4。    
例如: char *p;      //Linux中
sizeof(p) = 4;

  4、当操作数具有数组类型时,其结果是数组的总字节数。
 
例如: char a[5];
int  b[5];
sizeof(a) = 5;
sizeof(b) = 20;
   
5、当操作数是具体的字符串或者数值时,会根据具体的类型进行相应转化。
 
例如: sizeof(8)    = 4;  //自动转化为int类型
sizeof(8.8)  = 8;  //自动转化为double类型,注意,不是float类型
sizeof("ab") = 3   //自动转化为数组类型,
                             //所占字节是3,不是2,因为加上了最后的'\n'符,而字符串“ab”长度为2
                             //有资料说,会自动转化为指针类型(Linux为4)
                             //可能和操作系统与编译器有关系
         
6、当操作数是联合类型时,sizeof是其最大字节成员的字节数。
当操作数是结构类型时,sizeof是其成员类型的总字节数,包括补充字节在内。    
    
还是让我们拿例子来说话:
union  u{             //对union来说
          char c;
          double d;
}u;
sizeof(u) = max(sizeof(c),sizeof(d)) = sizeof(1,8) = 8;

struct a{             //对struct来说
          char b; 
          double x;
}a;   
在Linux上: sizeof(a) = 12;
而一般sizeof(char) + sizeof(double) = 9; 
这是因为编译器在考虑对齐问题时,在结构中插入空位以控制各成员对象的地址对齐。
但如果全对齐的话,sizeof(a) = 16, 这是因为b被放到偏移量为0的地址,占1个字节;
在存放x时,double类型长度为8,需要放到能被8整除的偏移量上,这时候需要补7个空字节,
达到8个,这时候偏移量为8,放上x后长度为16。
在此例中,所有的结构成员都要放在被4整除的地址(Linux的存放方式),这里补3个字节,所以为12。

7、当操作数是函数中的数组形参或函数类型的形参:
   
sizeof给出其指针的大小,Linux中值为4。

四、sizeof与其他操作符的关系  

sizeof的优先级为2级,比/、%等3级运算符优先级高。
它可以与其他操作符一起组成表达式:
例如: int i = 10;
          i * sizeof(int);

五、sizeof的主要用途  

1、主要用途是与存储分配和I/O系统那样的例程进行通信。
 
例如: void *malloc(size_t size);
        size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream);    

2、另一个的主要用途是计算数组中元素的个数。
 
 例如: void *memset(void *s, int c, sizeof(s));  


//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------

测试代码:(环境为vc6.0)
 #include <stdio.h> #include <string.h>  /*----------------------------------------------------------------------------- 编译器认为任何一种数据类型都有其大小,用它来定义一个变量能够分配确定大小的空间。 既然如 此,编译器就理所当然的认为任何一个结构体都是有大小的,哪怕这个结构体为空。 那万 一结构体真的为空,它的大小为什么值比较合适呢?假设结构体内只有一个char 型的数据  成员,那其大小为1byte(这里先不考虑内存对齐的情况).也就是说非空结构体类型数据最  少需要占一个字节的空间,而空结构体类型数据总不能比最小的非空结构体类型数据所占  的空间大吧。这就麻烦了,空结构体的大小既不能为0,也不能大于1,怎么办?定义为0.5  个byte?但是内存地址的最小单位是1 个byte,0.5 个byte 怎么处理?解决这个问题的最好  办法就是折中,编译器理所当然的认为你构造一个结构体数据类型是用来打包一些数据成  员的,而最小的数据成员需要1 个byte,编译器为每个结构体类型数据至少预留1 个byte  的空间。所以,空结构体的大小就定位1 个byte。 ------------------------------------------------------------------------------*/  struct stu1 {  };  struct stu2 { char c; };  unsigned int f(const char a[]) { return sizeof(a);//数组作为函数参数自动转换为相应类型的指针(在函数体内) }   int main() { unsigned int x,y,z; const char *s1="ab";//ab为字符串常量,存于内存中的 全局初始化数据区/静态数据区(常量区)。 //此句执行时,栈中分配的指针s1指向已初始化数据区中的字符串常量ab x=strlen(s1); y=sizeof(s1);//s1为char类型指针,指针所占字节为4(至少windows中为4) z=sizeof("ab"); printf("字符串 s1=\"ab\"(s1为指针变量)\n"); printf("strlen(s1)=%d \nsizeof(s1)=%d \nsizeof(\"ab\")=%d \n",x,y,z);   unsigned int x2,y2; char s2[]="ab";//s2为数组变量,存储在栈区,"ab"为字符串常量,存储在已初始化数据区。 //此句执行时,系统会在栈中分配长为3的内存空间,指针s2为此内存空间的首地址 //并将这段内存取名为s2 x2=strlen(s2); y2=sizeof(s2); printf("\n字符串 s2=\"ab\"(s2为数组变量)\n"); printf("strlen(s2)=%d \nsizeof(s2)=%d \n",x2,y2);   unsigned int x3; x3=f(s2); printf("\n此处测试验证数组作为函数参数自动转换为相应类型的指针的情况:\n"); printf("%d\n",x3);   unsigned int x4,y4; x4=sizeof(struct stu1); y4=sizeof(struct stu2); printf("\n结构体所占空间大小:\n"); printf("%d,%d\n",x4,y4);   printf("\n各种数据类型所占空间大小:\n"); printf("sizeof(char)=%d\n",sizeof(char)); printf("sizeof(short)=%d\n",sizeof(short)); printf("sizeof(int)=%d\n",sizeof(int)); printf("sizeof(unsigned int)=%d\n",sizeof(unsigned int)); printf("sizeof(long)=%d\n",sizeof(long)); printf("sizeof(float)=%d\n",sizeof(float)); printf("sizeof(double)=%d\n",sizeof(double)); printf("sizeof(long double)=%d\n",sizeof(long double)); printf("sizeof(32)=%d\n",sizeof(32)); printf("sizeof(32.0)=%d\n",sizeof(32.0));//注意,此处自动转换为double类型,而非float类型 printf("sizeof('a')=%d\n",sizeof('a'));//字符 printf("sizeof(\"a\")=%d\n",sizeof("a"));//字符串  return 0; } 

运行结果:



原创粉丝点击