sizeof详细分析以及陷阱
- 格式:doc
- 大小:80.50 KB
- 文档页数:8
sizeof用法sizeof是C/C++语言中非常常用的一个操作符,用于计算数据类型或变量在内存中所占的字节数。
本文将从使用方法、注意事项、应用场景等方面进行详细讲解。
1.使用方法sizeof操作符有两种用法:(1)计算数据类型在内存中所占的字节数语法:sizeof(数据类型)例子:sizeof(int)(2)计算变量在内存中所占的字节数语法:sizeof(变量名)例子:int a; sizeof(a)2.注意事项(1)sizeof操作符计算的字节数只与数据类型相关,与具体的实现相关性较小。
(2)对于数组,sizeof计算的是整个数组所占的字节数,而不是指向数组首元素的指针所占的字节数。
(3)对于指针,sizeof计算的是指针本身所占的字节数,而不是指针指向对象所占的字节数。
(4)通过结构体、共用体等数据类型可以自定义复合类型,sizeof计算的是整个数据类型所占的字节数。
(5)sizeof操作符是在编译时计算,不会对程序运行造成任何影响。
3.应用场景(1)动态内存分配在进行动态内存分配时,需要根据数据类型的大小决定分配的内存空间大小。
使用sizeof操作符可以方便地获取数据类型的大小,从而确定需要分配的内存大小。
(2)指针运算对指针进行加减运算时需要知道指针指向对象的大小,从而确定加减的偏移量。
使用sizeof操作符可以获取指针指向对象的大小。
(3)复合类型处理在处理复合类型数据时,需要知道整个数据类型所占的字节数,从而方便进行内存分配、指针运算等操作。
使用sizeof操作符可以获取复合类型数据的大小。
(4)调试和分析在进行程序调试和性能分析时,需要了解数据类型在内存中的存储情况,使用sizeof操作符可以获取数据类型在内存中所占的字节数,进而方便进行调试和分析。
总之,sizeof操作符是C/C++语言中非常重要的操作符,在程序开发、调试和分析中都具有重要作用。
需要注意的是,在使用sizeof操作符时需要注意相关的注意事项,才能正确无误地进行操作。
C语⾔--sizeof总结sizeof的语法1:sizeof是C语⾔的关键字,⽤来计算变量、常量或数据类型在当前系统中占⽤内存的字节数。
…2:sizeof不是函数,产⽣这样的疑问是因为sizeof的书写确实有点像函数。
在程序中,sizeof有两种写法:1)⽤于数据类型:sizeof(数据类型)2)⽤于变量名:sizeof(变量名);sizeof变置名 //不建议这样使⽤代码⽰例:#include<stdio.h>int main() {int i;char str[20];printf("sizeof(i) is %d\n", sizeof(i));printf("sizeof i is %d\n", sizeof i);printf("sizeof int is %d\n", sizeof(int));//printf("sizeof int is %d\n", sizeof int);错误写法printf("sizeof(str) is %d\n", sizeof(str));printf("sizeof str is %d\n", sizeof str);printf("sizeof str is %d\n", sizeof (char[20]));//printf("sizeof str is %d\n", sizeof char[20]);错误写法printf("sizeof(365) is %d\n", sizeof(365));printf("sizeof(i love you) is %d\n", sizeof("i love you"));}结果:注:最后⼀个字符串之所以是11,是因为在C语⾔中字符串后边会默认添加⼀个结束符,也就是'\0'sizeof与strlensizeof是运算符,⽤来计算变量、常量或数据类型在当前系统中占⽤内存的字节数strlen是函数,⽤于计算字符串的实际长度代码⽰例:char ch[20];strcpy(ch, "i love you");printf("sizeof(ch) is %d\n", sizeof(ch));//地址长度20,不变printf("strlen(ch) is %d\n", strlen(ch));//字符串的实际长度,也就是i love you的长度,为10结构体内存对齐⾸先看⼀个例⼦:struct S{char a;int b;char c;};我们先来计算⼀下这个结构体的⼤⼩,如果不存在内存对齐这个问题,按理说这个结构体应该占(1+4+1)6个字节;然⽽事实上它占了12个字节,为什么?我们需要解决下⾯⼏个问题。
四、复杂数据类型中sizeof及其数据对齐问题 (1)、union的sizeof问题与cpu的对界 考虑下⾯问题:(默认对齐⽅式) 1 union u //8对齐 2 { 3 double a; 4 int b; 5 }; 6 7 union u2 //4对齐 8 { 9 char a[13]; 10 int b; 11 }; 12 13 union u3 //1对齐 14 { 15 char a[13]; 16 char b; 17 }; 18 19 cout< 20 cout< 21 cout< 22 都知道union的⼤⼩取决于它所有的成员中,占⽤空间的⼀个成员的⼤⼩。
所以对于u来说,⼤⼩就是的double类型成员a 了,所以sizeof(u)=sizeof(double)=8。
但是对于u2和u3,的空间都是char[13]类型的数组,为什么u3的⼤⼩是13,⽽u2是16呢?关键在于u2中的成员int b。
由于int类型成员的存在,使u2的对齐⽅式变成4(4字节对齐),也就是说,u2的⼤⼩必须在4的对界上,所以占⽤的空间变成了16(最接近13的对界)。
结论:复合数据类型,如union,struct,class的对齐⽅式为成员中对齐⽅式的成员的对齐⽅式。
编译器对界: ⾸先解释下CPU对界问题,32的C++采⽤8位对界来提⾼运⾏速度,所以编译器会尽量把数据放在它的对界上以提⾼内存命中率。
通过程序可以改变编译器对界,使⽤#pragma pack(x)宏可以改变编译器的对界⽅式,默认是8。
sizeof深入理解(vcbase)∙ 1.sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型。
该类型保证能容纳实现所建立的最大对象的字节大小。
∙ 2.sizeof是算符,strlen是函数。
∙ 3.sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以''\0''结尾的。
sizeof还可以用函数做参数,比如:∙short f();∙printf("%d\n", sizeof(f()));输出的结果是sizeof(short),即2。
∙ 4.数组做sizeof的参数不退化,传递给strlen就退化为指针了。
∙ 5.大部分编译程序在编译的时候就把sizeof计算过了是类型或是变量的长度这就是sizeof(x)可以用来定义数组维数的原因∙char str[20]="0123456789";∙int a=strlen(str); //a=10;∙int b=sizeof(str); //而b=20;∙ 6.strlen的结果要在运行的时候才能计算出来,时用来计算字符串的长度,不是类型占内存的大小。
∙7.sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧。
这是因为sizeof是个操作符不是个函数。
∙8.当适用了于一个结构类型时或变量, sizeof 返回实际的大小,当适用一静态地空间数组, sizeof 归还全部数组的尺寸。
sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸∙9.数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,如:∙fun(char [8])∙fun(char [])都等价于 fun(char *) 在C++里传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小如果想在函数内知道数组的大小,需要这样做:进入函数后用memcpy 拷贝出来,长度由另一个形参传进去fun(unsiged char *p1, int len){unsigned char* buf = new unsigned char[len+1]memcpy(buf, p1, len);}有关内容见: C++ PRIMER?∙10.计算结构变量的大小就必须讨论数据对齐问题。
sizeof在c语言中的用法一、sizeof在C语言中的用法简介在C语言中,sizeof是一个用来获取数据类型或变量在内存中所占字节数的运算符。
它返回一个无符号整数值,表示所给参数的大小。
sizeof可以用于各种数据类型,包括基本数据类型(如int、float等)、指针、数组和结构体等。
二、sizeof用法详解1. 获取基本数据类型的大小使用sizeof运算符可以获取C语言中各种基本数据类型的大小。
例如,sizeof(int)将返回该机器上int类型所占的字节数。
这对于编写可移植性强的代码非常有用。
2. 获取数组大小通过使用sizeof运算符,可以获取数组在内存中所占空间的大小。
例如,如果有一个整型数组arr,则sizeof(arr)将返回该数组所占的总字节数。
3. 获取指针变量的大小当使用sizeof运算符计算指针变量时,它将返回指针变量本身所占空间的大小,并不会计算指针所引用对象的大小。
这是因为指针只是一个地址值,在32位操作系统上通常占用4个字节,在64位操作系统上通常占用8个字节。
4. 获取结构体大小通过使用sizeof运算符,可以获取结构体在内存中所占空间的大小。
结构体由多个字段组成,而每个字段又可以是不同的数据类型。
sizeof(struct_name)将返回该结构体所占的总字节数。
5. 计算变量的大小sizeof运算符可以用于计算变量在内存中所占空间的大小。
例如,sizeof(variable)将返回变量所占的字节数。
这在动态分配内存或者进行数据传输时非常有用。
6. 获取字符串长度使用sizeof运算符可以获取字符串(字符数组)在内存中所占空间的大小,包括末尾的空字符'\0'。
例如,如果有一个字符数组str,则sizeof(str)将返回该数组所占空间的总字节数。
7. 特殊情况注意事项在使用sizeof运算符时需要特别注意一些情况。
首先,在计算指针变量时,需要明确指针类型,因为不同类型的指针在不同平台上可能占用不同大小的空间。
sizeof,一个其貌不扬的家伙,引无数菜鸟竟折腰,小虾我当初也没少犯迷糊,秉着“辛苦我一个,幸福千万人”的伟大思想,我决定将其尽可能详细的总结一下。
但当我总结的时候才发现,这个问题既可以简单,又可以复杂,所以本文有的地方并不适合初学者,甚至都没有必要大作文章。
但如果你想“知其然,更知其所以然”的话,那么这篇文章对你或许有所帮助。
菜鸟我对C++的掌握尚未深入,其中不乏错误,欢迎各位指正啊1. 定义: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.其返回值类型为size_t,在头文件stddef.h中定义。
这是一个依赖于编译系统的值,一般定义为typedef unsigned int size_t;世上编译器林林总总,但作为一个规范,它们都会保证char、signed char和unsignedchar的sizeof值为1,毕竟char是我们编程能用的最小数据类型。
2. 语法:sizeof有三种语法形式,如下:1) sizeof( object ); // sizeof( 对象);2) sizeof( type_name ); // sizeof( 类型);3) sizeof object; // sizeof 对象;所以,int i;sizeof( i ); // oksizeof i; // oksizeof( int ); // oksizeof int; // error既然写法3可以用写法1代替,为求形式统一以及减少我们大脑的负担,第3种写法,忘掉它吧!实际上,sizeof计算对象的大小也是转换成对对象类型的计算,也就是说,同种类型的不同对象其sizeof值都是一致的。
C语言中的sizeof用法C语言中的sizeof是一个很有意思的关键字,经常有人用不对,搞不清不是什么。
我以前也有用错的时候,现在写一写,也算是提醒一下自己吧。
反正现在来看,还在搞sizeof是什么意思,怎么用正确,还是有点搞笑,都经常用的东西,没有理解透彻,就差的太远了。
第一 sizeof是什么sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等,sizeof操作符以字节形式给出了其操作数的存储大小。
操作数可以是一个表达式或括在括号内的类型名。
这个操作数不好理解对吧?后面慢慢看就明白了。
sizeof的返回值是size_t,在64位机器下,被定义为long unsigned int。
第二 sizeof如何使用1、用于数据类型使用形式: sizeof(type)。
其中type如int 、double等。
例如sizeof(int)、sizeof(char*)、sizeof(double)。
这个时候sizeof后面的类型必须用括号()包起来,不包起来是错误的,通过不了编译。
其中sizeof(void*)在64位下是8,而sizeof(void)是1。
其实,在C语言中sizeof(函数),如sizeof(main),结果也是1。
但是在C++中,sizeof(void)和sizeof(函数)都是非法的,通过不了编译,后面C++就不说了,现在讲C嘛。
其实sizeof(函数),sizeof(void)虽然是1,但是是不正确的使用方式。
2、用于变量使用形式: sizeof(var)或sizeof var。
当操作基本数据类型的时候,在我64位电脑的结果如下[html] view plain copyprint?1.sizeof(char) 12.sizeof(char) 13.sizeof(short) 24.sizeof(int) 45.sizeof(long) 86.sizeof(float) 47.sizeof(double) 88.sizeof(long double) 169.sizeof(int*) 810.sizeof('a') 411.sizeof(1) 412.sizeof(1.0f) 413.sizeof(1.0) 814.sizeof "abc" 4其中sizeof('a') 4有点奇怪哈。
sizeof使用方法嘿,朋友们!今天咱就来好好唠唠 sizeof 这个家伙的使用方法。
你说 sizeof 像不像一把神奇的尺子呀?它能帮我们准确地量出各种数据类型所占的空间大小呢!比如说,你想知道一个整数在内存中占了多大地方,sizeof 就能告诉你答案。
就好比你去买衣服,你得知道自己的尺码吧?不然怎么能买到合身的呢?sizeof 就像是那个帮你量尺寸的店员,能让你清楚知道每个数据类型的“身材”。
那怎么用这把“尺子”呢?很简单啦!就把你想要量的东西放在sizeof 后面就行。
比如说 sizeof(int),它就会告诉你整数类型所占的字节数。
这可太有用啦!为啥呢?你想想啊,有时候我们写程序,得考虑内存的使用情况吧。
如果不清楚每个数据类型占多少空间,那不是容易出乱子嘛。
举个例子哈,你要存储很多数据,如果不知道它们各自占多大空间,可能就会导致内存不够用,程序就崩溃啦!这就好像你要装很多东西到一个箱子里,你总得知道每个东西大概占多大地方,才能合理安排空间,对吧?而且 sizeof 可不光能量基本数据类型哦,它对结构体、数组这些也都管用呢!就像它能量出一个人的身高、体重,也能量出一群人的总体情况一样。
比如说,你有个结构体,里面包含了各种不同类型的数据。
那sizeof 就能告诉你整个结构体所占的空间大小。
这就好比你要知道一个团队的整体规模, sizeof 就能帮你做到。
还有数组呢,它能准确地告诉你这个数组所占的总字节数。
这就像你知道一箱子苹果有多少个,每个苹果多大,就能算出这箱苹果占了多大空间一样。
总之啊,sizeof 就像是我们编程世界里的一个小助手,默默地帮我们把各种数据的“身材”量得清清楚楚。
有了它,我们就能更好地管理内存,让程序跑得更顺畅。
所以啊,朋友们,可别小看了 sizeof 哦!它虽然看起来不起眼,但在关键时刻,可是能发挥大作用的呢!好好利用它,让我们的编程之路更加顺畅吧!。
一、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的结果sizeof操作符的结果类型是size_t,它在头文件中typedef为unsignedint类型。
该类型保证能容纳实现所建立的最大对象的字节大小。
1、若操作数具有类型char、unsigned char或signed char,其结果等于1。
ANSI C正式规定字符类型为1字节。
2、int、unsigned int 、short int、unsigned short 、long int 、unsigned long 、float、double、long double类型的sizeof 在ANSI C中没有具体规定,大小依赖于实现,一般可能分别为2、2、2、2、4、4、4、8、10。
1、什么是sizeof首先看一下sizeof在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.看到return这个字眼,是不是想到了函数?错了,sizeof不是一个函数,你见过给一个函数传参数,而不加括号的吗?sizeof可以,所以sizeof不是函数。
网上有人说sizeof是一元操作符,但是我并不这么认为,因为sizeof更像一个特殊的宏,它是在编译阶段求值的。
举个例子:cout<<sizeof(int)<<endl; // 32位机上int长度为4cout<<sizeof(1==2)<<endl; // == 操作符返回bool类型,相当于cout<<sizeof(bool)<<endl;在编译阶段已经被翻译为:cout<<4<<endl;cout<<1<<endl;这里有个陷阱,看下面的程序:int a = 0;cout<<sizeof(a=3)<<endl;cout<<a<<endl;输出为什么是4,0而不是期望中的4,3???就在于sizeof在编译阶段处理的特性。
由于sizeof不能被编译成机器码,所以sizeof作用范围内,也就是()里面的内容也不能被编译,而是被替换成类型。
=操作符返回左操作数的类型,所以a=3相当于int,而代码也被替换为:int a = 0;cout<<4<<endl;cout<<a<<endl;所以,sizeof是不可能支持链式表达式的,这也是和一元操作符不一样的地方。
结论:不要把sizeof当成函数,也不要看作一元操作符,把他当成一个特殊的编译预处理。
2、sizeof的用法sizeof有两种用法:(1)sizeof(object)也就是对对象使用sizeof,也可以写成sizeof object 的形式。
(2)sizeof(typename)也就是对类型使用sizeof,注意这种情况下写成sizeof typename是非法的。
下面举几个例子说明一下:int i = 2;cout<<sizeof(i)<<endl; // sizeof(object)的用法,合理cout<<sizeof i<<endl; // sizeof object的用法,合理cout<<sizeof 2<<endl; // 2被解析成int类型的object, sizeof object的用法,合理cout<<sizeof(2)<<endl; // 2被解析成int类型的object, sizeof(object)的用法,合理cout<<sizeof(int)<<endl;// sizeof(typename)的用法,合理cout<<sizeof int<<endl; // 错误!对于操作符,一定要加()可以看出,加()是永远正确的选择。
结论:不论sizeof要对谁取值,最好都加上()。
3、数据类型的sizeof(1)C++固有数据类型32位C++中的基本数据类型,也就char,short int(short),int,long int(long),float,double, long double大小分别是:1,2,4,4,4,8, 10。
考虑下面的代码:cout<<sizeof(unsigned int) == sizeof(int)<<endl; // 相等,输出1unsigned影响的只是最高位bit的意义,数据长度不会被改变的。
结论:unsigned不能影响sizeof的取值。
(2)自定义数据类型typedef可以用来定义C++自定义类型。
考虑下面的问题:typedef short WORD;typedef long DWORD;cout<<(sizeof(short) == sizeof(WORD))<<endl; // 相等,输出1cout<<(sizeof(long) == sizeof(DWORD))<<endl; // 相等,输出1结论:自定义类型的sizeof取值等同于它的类型原形。
(3)函数类型考虑下面的问题:int f1(){return 0;};double f2(){return 0.0;}void f3(){}cout<<sizeof(f1())<<endl; // f1()返回值为int,因此被认为是intcout<<sizeof(f2())<<endl; // f2()返回值为double,因此被认为是doublecout<<sizeof(f3())<<endl; // 错误!无法对void类型使用sizeofcout<<sizeof(f1)<<endl; // 错误!无法对函数指针使用sizeofcout<<sizeof*f2<<endl; // *f2,和f2()等价,因为可以看作object,所以括号不是必要的。
被认为是double结论:对函数使用sizeof,在编译阶段会被函数返回值的类型取代,4、指针问题考虑下面问题:cout<<sizeof(string*)<<endl; // 4cout<<sizeof(int*)<<endl; // 4cout<<sizof(char****)<<endl; // 4可以看到,不管是什么类型的指针,大小都是4的,因为指针就是32位的物理地址。
结论:只要是指针,大小就是4。
(64位机上要变成8也不一定)。
顺便唧唧歪歪几句,C++中的指针表示实际内存的地址。
和C不一样的是,C++中取消了模式之分,也就是不再有small,middle,big,取而代之的是统一的flat。
flat模式采用32位实地址寻址,而不再是c中的segment:offset模式。
举个例子,假如有一个指向地址f000:8888的指针,如果是C类型则是8888(16位, 只存储位移,省略段),far类型的C指针是f0008888(32位,高位保留段地址,地位保留位移),C++类型的指针是f8888(32位,相当于段地址*16 + 位移,但寻址范围要更大)。
5、数组问题考虑下面问题:char a[] = "abcdef";int b[20] = {3, 4};char c[2][3] = {"aa", "bb"};cout<<sizeof(a)<<endl; // 7cout<<sizeof(b)<<endl; // 20*4数组a的大小在定义时未指定,编译时给它分配的空间是按照初始化的值确定的,也就是7。
c是多维数组,占用的空间大小是各维数的乘积,也就是6。
可以看出,数组的大小就是他在编译时被分配的空间,也就是各维数的乘积*数组元素的大小。
结论:数组的大小是各维数的乘积*数组元素的大小。
这里有一个陷阱:int *d = new int[10];cout<<sizeof(d)<<endl; // 4d是我们常说的动态数组,但是他实质上还是一个指针,所以sizeof(d)的值是4。
再考虑下面的问题:double* (*a)[3][6];cout<<sizeof(a)<<endl; // 4cout<<sizeof(*a)<<endl; // 72cout<<sizeof(**a)<<endl; // 24cout<<sizeof(***a)<<endl; // 4cout<<sizeof(****a)<<endl; // 8a是一个很奇怪的定义,他表示一个指向double*[3][6]类型数组的指针。
既然是指针,所以sizeof(a)就是4。
既然a是执行double*[3][6]类型的指针,*a就表示一个double*[3][6]的多维数组类型,因此sizeof(*a)=3*6*sizeof(double*)=72。
同样的,**a表示一个double*[6]类型的数组,所以sizeof(**a)=6*sizeof(double*)=24。
***a就表示其中的一个元素,也就是double*了,所以sizeof(***a)=4。
至于****a,就是一个double了,所以sizeof(****a)=sizeof(double)=8。
6、union struct内存对齐问题考虑下面问题:(默认对齐方式)C代码1. union u2. {3. double a;4. int b;5. };6.7. union u29. char a[13];10. int b;11. };12.13. union u314. {15. char a[13];16. char b;17. };18.19. cout<<sizeof(u)<<endl; // 820. cout<<sizeof(u2)<<endl; // 1621. cout<<sizeof(u3)<<endl; // 13都知道union的大小取决于它所有的成员中,占用空间最大的一个成员的大小。
所以对于u来说,大小就是最大的double类型成员a了,所以sizeof(u)=sizeof(double)=8。
但是对于u2和u3,最大的空间都是char[13]类型的数组,为什么u3的大小是13,而u2是16呢?关键在于u2中的成员int b。
由于int类型成员的存在,使u2的对齐方式变成4,也就是说,u2的大小必须在4的对界上,所以占用的空间变成了16(最接近13的对界)。