﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-&lt;H1&gt;&lt;font color=orange&gt;JonsenElizee&lt;/font&gt;&lt;/H1&gt;-随笔分类-C++.Basic</title><link>http://www.cppblog.com/JonsenElizee/category/13491.html</link><description>C++ Blog
&lt;BR&gt;
&lt;BR&gt;
"An idea is fragile . It can be killed by a scornful smile or a yawn .It can be mound down by irony and scared to death by a cold look." 
&lt;BR&gt; 
"Most cultures throughout human history have not liked creative individuals .They ignore them or kill them.It is a very efficient way of stopping creativity."  
&lt;BR&gt; 
&lt;BR&gt;
------Advertising boss Charles Browe and Howard Gardner ,professor at Harvard </description><language>zh-cn</language><lastBuildDate>Tue, 03 Aug 2010 06:46:20 GMT</lastBuildDate><pubDate>Tue, 03 Aug 2010 06:46:20 GMT</pubDate><ttl>60</ttl><item><title>About C++ sizeof</title><link>http://www.cppblog.com/JonsenElizee/archive/2010/07/22/121020.html</link><dc:creator>JonsenElizee</dc:creator><author>JonsenElizee</author><pubDate>Thu, 22 Jul 2010 04:20:00 GMT</pubDate><guid>http://www.cppblog.com/JonsenElizee/archive/2010/07/22/121020.html</guid><description><![CDATA[<div class="postcontent"><font style="background-color: #ffffff;" color="#0000ff" size="3"><a title="出去"  href="http://www.fish888.com/C-sizeof-t132091">原文作者及文章来源</a><br><br>1、什么是sizeof</font>
</div>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
首先看一下sizeof在msdn上的定义：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
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.</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
看到return这个字眼，是不是想到了函数？错了，sizeof不是一个函数，你见过给一个函数传参数，而不加括号的吗？sizeof可以，所以sizeof不是函数。网上有人说sizeof是一元操作符，但是我并不这么认为，因为sizeof更像一个特殊的宏，它是在编译阶段求值的。举个例子：<br>&nbsp;<br>&nbsp;cout&lt;&lt;sizeof(int)&lt;&lt;endl;&nbsp;//
32位机上int长度为4<br>&nbsp;cout&lt;&lt;sizeof(1==2)&lt;&lt;endl;&nbsp;// == 操作符返回bool类型，相当于
cout&lt;&lt;sizeof(bool)&lt;&lt;endl;</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
在编译阶段已经被翻译为：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;cout&lt;&lt;4&lt;&lt;endl;<br>&nbsp;cout&lt;&lt;1&lt;&lt;endl;</font>
</p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
这里有个陷阱，看下面的程序：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;int
a =
0;<br>&nbsp;cout&lt;&lt;sizeof(a=3)&lt;&lt;endl;<br>&nbsp;cout&lt;&lt;a&lt;&lt;endl;</font>
</p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
输出为什么是4，0而不是期望中的4，3？？？就在于sizeof在编译阶段处理的特性。由于sizeof不能被编译成机器码，所以sizeof作用范围内，也就是()里面的内容也不能被编译，而是被替换成类型。=操作符返回左操作数的类型，所以a=3相当于int，而代码也被替换为：</font>
</p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;int
a = 0;<br>&nbsp;cout&lt;&lt;4&lt;&lt;endl;<br>&nbsp;cout&lt;&lt;a&lt;&lt;endl;</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
所以，sizeof是不可能支持链式表达式的，这也是和一元操作符不一样的地方。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
结论：不要把sizeof当成函数，也不要看作一元操作符，把他当成一个特殊的编译预处理。</font> </p>
<p><font style="background-color: #ffffff;" color="#0000ff" size="3">2、sizeof的用法</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
sizeof有两种用法：<br>&nbsp; <br>&nbsp;&nbsp;&nbsp; （1）sizeof(object)<br>&nbsp;&nbsp;&nbsp; 也就是对对象使用sizeof，也可以写成sizeof
object 的形式。例如：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
（2）sizeof(typename)<br>&nbsp;&nbsp;&nbsp; 也就是对类型使用sizeof，注意这种情况下写成sizeof
typename是非法的。下面举几个例子说明一下：</font> </p>
<p><br><font style="background-color: #ffffff;" color="#000000">&nbsp;int i = 2;<br>&nbsp;cout&lt;&lt;sizeof(i)&lt;&lt;endl;&nbsp;//
sizeof(object)的用法，合理<br>&nbsp;cout&lt;&lt;sizeof i&lt;&lt;endl;&nbsp;// sizeof
object的用法，合理<br>&nbsp;cout&lt;&lt;sizeof 2&lt;&lt;endl;&nbsp;// 2被解析成int类型的object, sizeof
object的用法，合理<br>&nbsp;cout&lt;&lt;sizeof(2)&lt;&lt;endl;&nbsp;// 2被解析成int类型的object,
sizeof(object)的用法，合理<br>&nbsp;cout&lt;&lt;sizeof(int)&lt;&lt;endl;//
sizeof(typename)的用法，合理<br>&nbsp;cout&lt;&lt;sizeof int&lt;&lt;endl;&nbsp;//
错误！对于操作符，一定要加()</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
可以看出，加()是永远正确的选择。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
结论：不论sizeof要对谁取值，最好都加上()。</font> </p>
<p><br><font style="background-color: #ffffff;" color="#0000ff" size="3">3、数据类型的sizeof</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">（1）C++固有数据类型</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
32位C++中的基本数据类型，也就char,short int(short),int,long int(long),float,double, long
double<br>大小分别是：1，2，4，4，4，8, 10。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
考虑下面的代码：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;cout&lt;&lt;sizeof(unsigned int) == sizeof(int)&lt;&lt;endl;&nbsp;//
相等，输出 1</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
unsigned影响的只是最高位bit的意义，数据长度不会被改变的。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
结论：unsigned不能影响sizeof的取值。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">（2）自定义数据类型</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
typedef可以用来定义C++自定义类型。考虑下面的问题：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;typedef short WORD;<br>&nbsp;typedef long
DWORD;<br>&nbsp;cout&lt;&lt;(sizeof(short) == sizeof(WORD))&lt;&lt;endl;&nbsp;//
相等，输出1<br>&nbsp;cout&lt;&lt;(sizeof(long) == sizeof(DWORD))&lt;&lt;endl;&nbsp;//
相等，输出1</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
结论：自定义类型的sizeof取值等同于它的类型原形。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">（3）函数类型</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
考虑下面的问题：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;int
f1(){return 0;};<br>&nbsp;double f2(){return 0.0;}<br>&nbsp;void f3(){}</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;cout&lt;&lt;sizeof(f1())&lt;&lt;endl;&nbsp;//
f1()返回值为int，因此被认为是int<br>&nbsp;cout&lt;&lt;sizeof(f2())&lt;&lt;endl;&nbsp;//
f2()返回值为double，因此被认为是double<br>&nbsp;cout&lt;&lt;sizeof(f3())&lt;&lt;endl;&nbsp;//
错误！无法对void类型使用sizeof<br>&nbsp;cout&lt;&lt;sizeof(f1)&lt;&lt;endl;&nbsp;&nbsp;//
错误！无法对函数指针使用sizeof&nbsp;&nbsp;&nbsp;<br>&nbsp;cout&lt;&lt;sizeof*f2&lt;&lt;endl;&nbsp;&nbsp;//
*f2，和f2()等价，因为可以看作object，所以括号不是必要的。被认为是double</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
结论：对函数使用sizeof，在编译阶段会被函数返回值的类型取代，</font> </p>
<p><font style="background-color: #ffffff;" color="#0000ff" size="3">4、指针问题</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
考虑下面问题：<br>&nbsp;<br>&nbsp;cout&lt;&lt;sizeof(string*)&lt;&lt;endl;&nbsp;//
4<br>&nbsp;cout&lt;&lt;sizeof(int*)&lt;&lt;endl;&nbsp;//
4<br>&nbsp;cout&lt;&lt;sizof(char****)&lt;&lt;endl;&nbsp;// 4</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
可以看到，不管是什么类型的指针，大小都是4的，因为指针就是32位的物理地址。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
结论：只要是指针，大小就是4。（64位机上要变成8也不一定）。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
顺便唧唧歪歪几句，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 +
位移，但寻址范围要更大)。</font> </p>
<p><font style="background-color: #ffffff;" color="#0000ff" size="3">5、数组问题</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
考虑下面问题：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;char
a[] = "abcdef";<br>&nbsp;int b[20] = {3, 4};<br>&nbsp;char c[2][3] = {"aa",
"bb"};<br>&nbsp;</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;cout&lt;&lt;sizeof(a)&lt;&lt;endl;&nbsp;//
7<br>&nbsp;cout&lt;&lt;sizeof(b)&lt;&lt;endl;&nbsp;//
20*4<br>&nbsp;cout&lt;&lt;sizeof(c)&lt;&lt;endl;&nbsp;// 6<br>&nbsp;</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
数组a的大小在定义时未指定，编译时给它分配的空间是按照初始化的值确定的，也就是7。c是多维数组，占用的空间大小是各维数的乘积，也就是6。可以看出，数组的大小就是他在编译时被分配的空间，也就是各维数的乘积*数组元素的大小。</font>
</p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
结论：数组的大小是各维数的乘积*数组元素的大小。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
这里有一个陷阱：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;int
*d = new int[10];</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;cout&lt;&lt;sizeof(d)&lt;&lt;endl;&nbsp;// 4</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
d是我们常说的动态数组，但是他实质上还是一个指针，所以sizeof(d)的值是4。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
再考虑下面的问题：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;double*
(*a)[3][6];<br>&nbsp;<br>&nbsp;cout&lt;&lt;sizeof(a)&lt;&lt;endl;&nbsp;&nbsp;//
4<br>&nbsp;cout&lt;&lt;sizeof(*a)&lt;&lt;endl;&nbsp;&nbsp;//
72<br>&nbsp;cout&lt;&lt;sizeof(**a)&lt;&lt;endl;&nbsp;//
24<br>&nbsp;cout&lt;&lt;sizeof(***a)&lt;&lt;endl;&nbsp;//
4<br>&nbsp;cout&lt;&lt;sizeof(****a)&lt;&lt;endl;&nbsp;// 8</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
a是一个很奇怪的定义，他表示一个指向 double*[3][6]类型数组的指针。既然是指针，所以sizeof(a)就是4。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
既然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。</font>
</p>
<p><br><font style="background-color: #ffffff;" color="#0000ff" size="3">6、向函数传递数组的问题。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
考虑下面的问题：<br>#include &lt;iostream&gt;<br>using namespace std;</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">int
Sum(int i[])<br>{<br>&nbsp;int sumofi = 0;<br>&nbsp;for (int j = 0; j &lt;
sizeof(i)/sizeof(int); j++) //实际上，sizeof(i) = 4<br>&nbsp;{<br>&nbsp;&nbsp;sumofi +=
i[j];<br>&nbsp;}<br>&nbsp;return sumofi;<br>}</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">int
main()<br>{<br>&nbsp;int allAges[6] = {21, 22, 22, 19, 34,
12};<br>&nbsp;cout&lt;&lt;Sum(allAges)&lt;&lt;endl;<br>&nbsp;system("pause");<br>&nbsp;return
0;<br>}</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
Sum的本意是用sizeof得到数组的大小，然后求和。但是实际上，传入自函数Sum的，只是一个int
类型的指针，所以sizeof(i)=4，而不是24，所以会产生错误的结果。解决这个问题的方法使是用指针或者引用。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
使用指针的情况：<br>int Sum(int (*i)[6])<br>{<br>&nbsp;int sumofi = 0;<br>&nbsp;for (int j = 0; j
&lt; sizeof(*i)/sizeof(int); j++) //sizeof(*i) = 24<br>&nbsp;{<br>&nbsp;&nbsp;sumofi +=
(*i)[j];<br>&nbsp;}<br>&nbsp;return sumofi;<br>}</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">int
main()<br>{<br>&nbsp;int allAges[] = {21, 22, 22, 19, 34,
12};<br>&nbsp;cout&lt;&lt;Sum(&amp;allAges)&lt;&lt;endl;<br>&nbsp;system("pause");<br>&nbsp;return
0;<br>}<br>&nbsp;&nbsp;&nbsp; 在这个Sum里，i是一个指向i[6]类型的指针，注意，这里不能用int Sum(int
(*i)[])声明函数，而是必须指明要传入的数组的大小，不然sizeof(*i)无法计算。但是在这种情况下，再通过sizeof来计算数组大小已经没有意义了，因为此时大小是指定为6的。<br>使用引用的情况和指针相似：</font>
</p>
<p><font style="background-color: #ffffff;" color="#000000">int
Sum(int (&amp;i)[6])<br>{<br>&nbsp;int sumofi = 0;<br>&nbsp;for (int j = 0; j &lt;
sizeof(i)/sizeof(int); j++)<br>&nbsp;{<br>&nbsp;&nbsp;sumofi += i[j];<br>&nbsp;}<br>&nbsp;return
sumofi;<br>}</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">int
main()<br>{<br>&nbsp;int allAges[] = {21, 22, 22, 19, 34,
12};<br>&nbsp;cout&lt;&lt;Sum(allAges)&lt;&lt;endl;<br>&nbsp;system("pause");<br>&nbsp;return
0;<br>}<br>&nbsp;&nbsp;&nbsp;
这种情况下sizeof的计算同样无意义，所以用数组做参数，而且需要遍历的时候，函数应该有一个参数来说明数组的大小，而数组的大小在数组定义的作用域内通过sizeof求值。因此上面的函数正确形式应该是：<br>#include
&lt;iostream&gt;<br>using namespace std;</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">int
Sum(int *i, unsigned int n)<br>{<br>&nbsp;int sumofi = 0;<br>&nbsp;for (int j = 0; j &lt;
n; j++)<br>&nbsp;{<br>&nbsp;&nbsp;sumofi += i[j];<br>&nbsp;}<br>&nbsp;return sumofi;<br>}</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">int
main()<br>{<br>&nbsp;int allAges[] = {21, 22, 22, 19, 34, 12};<br>&nbsp;cout&lt;&lt;Sum(i,
sizeof(allAges)/sizeof(int))&lt;&lt;endl;<br>&nbsp;system("pause");<br>&nbsp;return
0;<br>}</font> </p>
<p><font style="background-color: #ffffff;" color="#0000ff" size="3">7、字符串的sizeof和strlen</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
考虑下面的问题：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;char
a[] = "abcdef";<br>&nbsp;char b[20] = "abcdef";<br>&nbsp;string s = "abcdef";</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;cout&lt;&lt;strlen(a)&lt;&lt;endl;&nbsp;&nbsp;//
6，字符串长度<br>&nbsp;cout&lt;&lt;sizeof(a)&lt;&lt;endl;&nbsp;&nbsp;//
7，字符串容量<br>&nbsp;cout&lt;&lt;strlen(b)&lt;&lt;endl;&nbsp;&nbsp;//
6，字符串长度<br>&nbsp;cout&lt;&lt;strlen(b)&lt;&lt;endl;&nbsp;&nbsp;//
20，字符串容量<br>&nbsp;cout&lt;&lt;sizeof(s)&lt;&lt;endl;&nbsp;&nbsp;// 12,
这里不代表字符串的长度，而是string类的大小<br>&nbsp;cout&lt;&lt;strlen(s)&lt;&lt;endl;&nbsp;&nbsp;//
错误！s不是一个字符指针。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;a[1]
= '\0';<br>&nbsp;cout&lt;&lt;strlen(a)&lt;&lt;endl;&nbsp;&nbsp;//
1<br>&nbsp;cout&lt;&lt;sizeof(a)&lt;&lt;endl;&nbsp;&nbsp;// 7，sizeof是恒定的</font> </p>
<p><br><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
strlen是寻找从指定地址开始，到出现的第一个0之间的字符个数，他是在运行阶段执行的，而sizeof是得到数据的大小，在这里是得到字符串的容量。所以对同一个对象而言，sizeof的值是恒定的。string是C++类型的字符串，他是一个类，所以sizeof(s)表示的并不是字符串的长度，而是类string的大小。strlen(s)根本就是错误的，因为strlen的参数是一个字符指针，如果想用strlen得到s字符串的长度，应该使用sizeof(s.c_str())，因为string的成员函数c_str()返回的是字符串的首地址。实际上，string类提供了自己的成员函数来得到字符串的容量和长度，分别是Capacity()和Length()。string封装了常用了字符串操作，所以在C++开发过程中，最好使用string代替C类型的字符串。</font>
</p>
<p><font color="#ff0000">我注：关于sizeof(string)，好像不同的实现返回的结果不一样：<br>DevCPP：4<br>VS2005：32</font></p>
<p><br><font style="background-color: #ffffff;" color="#0000ff" size="3">8、从union的sizeof问题看cpu的对界</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
考虑下面问题：（默认对齐方式）</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;union u<br>&nbsp;{<br>&nbsp;&nbsp;double a;<br>&nbsp;&nbsp;int b;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;union u2<br>&nbsp;{<br>&nbsp;&nbsp;char a[13];<br>&nbsp;&nbsp;int b;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;union u3<br>&nbsp;{<br>&nbsp;&nbsp;char a[13];<br>&nbsp;&nbsp;char b;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;cout&lt;&lt;sizeof(u)&lt;&lt;endl;&nbsp;&nbsp;//
8<br>&nbsp;cout&lt;&lt;sizeof(u2)&lt;&lt;endl;&nbsp;&nbsp;//
16<br>&nbsp;cout&lt;&lt;sizeof(u3)&lt;&lt;endl;&nbsp;&nbsp;// 13</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
都知道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的对界）。</font>
</p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
结论：复合数据类型，如union，struct，class的对齐方式为成员中对齐方式最大的成员的对齐方式。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
顺便提一下CPU对界问题，32的C++采用8位对界来提高运行速度，所以编译器会尽量把数据放在它的对界上以提高内存命中率。对界是可以更改的，使用#pragma
pack(x)宏可以改变编译器的对界方式，默认是8。C++固有类型的对界取编译器对界方式与自身大小中较小的一个。例如，指定编译器按2对界，int类型的大小是4，则int的对界为2和4中较小的2。在默认的对界方式下，因为几乎所有的数据类型都不大于默认的对界方式8（除了long
double），所以所有的固有类型的对界方式可以认为就是类型自身的大小。更改一下上面的程序：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;#pragma pack(2)<br>&nbsp;union u2<br>&nbsp;{<br>&nbsp;&nbsp;char a[13];<br>&nbsp;&nbsp;int
b;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;union u3<br>&nbsp;{<br>&nbsp;&nbsp;char a[13];<br>&nbsp;&nbsp;char b;<br>&nbsp;};<br>&nbsp;#pragma
pack(8)</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;cout&lt;&lt;sizeof(u2)&lt;&lt;endl;&nbsp;&nbsp;//
14<br>&nbsp;cout&lt;&lt;sizeof(u3)&lt;&lt;endl;&nbsp;&nbsp;// 13</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
由于手动更改对界方式为2，所以int的对界也变成了2，u2的对界取成员中最大的对界，也是2了，所以此时sizeof(u2)=14。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
结论：C++固有类型的对界取编译器对界方式与自身大小中较小的一个。</font> </p>
<p><br><font style="background-color: #ffffff;" color="#0000ff" size="3">9、struct的sizeof问题</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
因为对齐问题使结构体的sizeof变得比较复杂，看下面的例子：(默认对齐方式下)</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;struct s1<br>&nbsp;{<br>&nbsp;&nbsp;char a;<br>&nbsp;&nbsp;double b;<br>&nbsp;&nbsp;int c;<br>&nbsp;&nbsp;char
d;&nbsp;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;struct s2<br>&nbsp;{<br>&nbsp;&nbsp;char a;<br>&nbsp;&nbsp;char b;<br>&nbsp;&nbsp;int c;<br>&nbsp;&nbsp;double
d;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;cout&lt;&lt;sizeof(s1)&lt;&lt;endl;&nbsp;//
24<br>&nbsp;cout&lt;&lt;sizeof(s2)&lt;&lt;endl;&nbsp;// 16</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
同样是两个char类型，一个int类型，一个double类型，但是因为对界问题，导致他们的大小不同。计算结构体大小可以采用元素摆放法，我举例子说明一下：首先，CPU判断结构体的对界，根据上一节的结论，s1和s2的对界都取最大的元素类型，也就是double类型的对界8。然后开始摆放每个元素。<br>&nbsp;&nbsp;&nbsp;
对于s1，首先把a放到8的对界，假定是0，此时下一个空闲的地址是1，但是下一个元素d是double类型，要放到8的对界上，离1最接近的地址是8了，所以d被放在了8，此时下一个空闲地址变成了16，下一个元素c的对界是4，16可以满足，所以c放在了16，此时下一个空闲地址变成了20，下一个元素d需要对界1，也正好落在对界上，所以d放在了20，结构体在地址21处结束。由于s1的大小需要是8的倍数，所以21-23的空间被保留，s1的大小变成了24。<br>&nbsp;&nbsp;&nbsp;
对于s2，首先把a放到8的对界，假定是0，此时下一个空闲地址是1，下一个元素的对界也是1，所以b摆放在1，下一个空闲地址变成了2；下一个元素c的对界是4，所以取离2最近的地址4摆放c，下一个空闲地址变成了8，下一个元素d的对界是8，所以d摆放在8，所有元素摆放完毕，结构体在15处结束，占用总空间为16，正好是8的倍数。</font>
</p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
这里有个陷阱，对于结构体中的结构体成员，不要认为它的对齐方式就是他的大小，看下面的例子：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;struct s1<br>&nbsp;{<br>&nbsp;&nbsp;char a[8];<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;struct s2<br>&nbsp;{<br>&nbsp;&nbsp;double d;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;struct s3<br>&nbsp;{<br>&nbsp;&nbsp;s1 s;<br>&nbsp;&nbsp;char a;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;struct s4<br>&nbsp;{<br>&nbsp;&nbsp;s2 s;<br>&nbsp;&nbsp;char a;&nbsp;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;cout&lt;&lt;sizeof(s1)&lt;&lt;endl;&nbsp;//
8<br>&nbsp;cout&lt;&lt;sizeof(s2)&lt;&lt;endl; //
8<br>&nbsp;cout&lt;&lt;sizeof(s3)&lt;&lt;endl; //
9<br>&nbsp;cout&lt;&lt;sizeof(s4)&lt;&lt;endl; // 16;</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
s1和s2大小虽然都是8，但是s1的对齐方式是1，s2是8（double），所以在s3和s4中才有这样的差异。</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
所以，在自己定义结构体的时候，如果空间紧张的话，最好考虑对齐因素来排列结构体里的元素。</font> </p>
<p><font style="background-color: #ffffff;" color="#0000ff" size="3">10、不要让double干扰你的位域</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
在结构体和类中，可以使用位域来规定某个成员所能占用的空间，所以使用位域能在一定程度上节省结构体占用的空间。不过考虑下面的代码：</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;struct s1<br>&nbsp;{<br>&nbsp;&nbsp;int i: 8;<br>&nbsp;&nbsp;int j: 4;<br>&nbsp;&nbsp;double
b;<br>&nbsp;&nbsp;int a:3;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;struct s2<br>&nbsp;{<br>&nbsp;&nbsp;int i;<br>&nbsp;&nbsp;int j;<br>&nbsp;&nbsp;double b;<br>&nbsp;&nbsp;int
a;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;struct s3<br>&nbsp;{<br>&nbsp;&nbsp;int i;<br>&nbsp;&nbsp;int j;<br>&nbsp;&nbsp;int a;<br>&nbsp;&nbsp;double
b;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;struct s4<br>&nbsp;{<br>&nbsp;&nbsp;int i: 8;<br>&nbsp;&nbsp;int j: 4;<br>&nbsp;&nbsp;int
a:3;<br>&nbsp;&nbsp;double b;<br>&nbsp;};</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;cout&lt;&lt;sizeof(s1)&lt;&lt;endl;&nbsp;&nbsp;//
24<br>&nbsp;cout&lt;&lt;sizeof(s2)&lt;&lt;endl;&nbsp;&nbsp;//
24<br>&nbsp;cout&lt;&lt;sizeof(s3)&lt;&lt;endl;&nbsp;&nbsp;//
24<br>&nbsp;cout&lt;&lt;sizeof(s4)&lt;&lt;endl;&nbsp;&nbsp;// 16</font> </p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
可以看到，有double存在会干涉到位域（sizeof的算法参考上一节），所以使用位域的的时候，最好把float类型和double类型放在程序的开始或者最后。</font>
</p>
<p><font style="background-color: #ffffff;" color="#000000">&nbsp;&nbsp;&nbsp;
第一次写东西，发现自己的表达能力太差了，知道的东西讲不出来，讲出来的东西别人也看不懂，呵呵。另外，C99标准的sizeof已经可以工作在运行时了，打算最近找个支持C99的编译器研究一下。</font>
</p>
<br><img src ="http://www.cppblog.com/JonsenElizee/aggbug/121020.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/JonsenElizee/" target="_blank">JonsenElizee</a> 2010-07-22 12:20 <a href="http://www.cppblog.com/JonsenElizee/archive/2010/07/22/121020.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>My Palindrome Algorithm</title><link>http://www.cppblog.com/JonsenElizee/archive/2010/07/21/120976.html</link><dc:creator>JonsenElizee</dc:creator><author>JonsenElizee</author><pubDate>Wed, 21 Jul 2010 09:19:00 GMT</pubDate><guid>http://www.cppblog.com/JonsenElizee/archive/2010/07/21/120976.html</guid><wfw:comment>http://www.cppblog.com/JonsenElizee/comments/120976.html</wfw:comment><comments>http://www.cppblog.com/JonsenElizee/archive/2010/07/21/120976.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/JonsenElizee/comments/commentRss/120976.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/JonsenElizee/services/trackbacks/120976.html</trackback:ping><description><![CDATA[Here is a simple palindrome algorithm from me.<br>It only can make a judge on single-byte character string.<br><span style="color: red;">Can anybody write a palindrome algorithm for Chinese character string? thank you at first.</span><br><br><img src="http://www.cppblog.com/images/cppblog_com/jonsenelizee/snap_0101.png" border="0"><br>  <img src ="http://www.cppblog.com/JonsenElizee/aggbug/120976.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/JonsenElizee/" target="_blank">JonsenElizee</a> 2010-07-21 17:19 <a href="http://www.cppblog.com/JonsenElizee/archive/2010/07/21/120976.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Funny printf ++</title><link>http://www.cppblog.com/JonsenElizee/archive/2010/07/21/120965.html</link><dc:creator>JonsenElizee</dc:creator><author>JonsenElizee</author><pubDate>Wed, 21 Jul 2010 07:19:00 GMT</pubDate><guid>http://www.cppblog.com/JonsenElizee/archive/2010/07/21/120965.html</guid><wfw:comment>http://www.cppblog.com/JonsenElizee/comments/120965.html</wfw:comment><comments>http://www.cppblog.com/JonsenElizee/archive/2010/07/21/120965.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/JonsenElizee/comments/commentRss/120965.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/JonsenElizee/services/trackbacks/120965.html</trackback:ping><description><![CDATA[<img src="http://www.cppblog.com/CuteSoft_Client/CuteEditor/images/emwink.gif" align="absmiddle" border="0">The following codes are tested on VS2005.<br>For reply from role0523, please pay attention to compiler version and so on.<br>Thanks for any reply from anyone.<img src="http://www.cppblog.com/CuteSoft_Client/CuteEditor/images/emwink.gif" align="absmiddle" border="0"><br><br><img src="http://www.cppblog.com/images/cppblog_com/jonsenelizee/snap_0099.png" border="0"><br>&nbsp;&nbsp; <img src="http://www.cppblog.com/images/cppblog_com/jonsenelizee/snap_0098.png" border="0"><br><br><br>   <img src ="http://www.cppblog.com/JonsenElizee/aggbug/120965.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/JonsenElizee/" target="_blank">JonsenElizee</a> 2010-07-21 15:19 <a href="http://www.cppblog.com/JonsenElizee/archive/2010/07/21/120965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Potential Hazards in C/C++</title><link>http://www.cppblog.com/JonsenElizee/archive/2010/07/20/120880.html</link><dc:creator>JonsenElizee</dc:creator><author>JonsenElizee</author><pubDate>Tue, 20 Jul 2010 07:44:00 GMT</pubDate><guid>http://www.cppblog.com/JonsenElizee/archive/2010/07/20/120880.html</guid><description><![CDATA[Do you know all these potential hazards in C/C++?<br>Here is a image for all potential hazards.<br>Though, you would say one or more of them are not dangerous, please pay attention to them during your coding work.<br><img src="http://www.cppblog.com/images/cppblog_com/jonsenelizee/snap_0086.png" border="0"><br>  <img src ="http://www.cppblog.com/JonsenElizee/aggbug/120880.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/JonsenElizee/" target="_blank">JonsenElizee</a> 2010-07-20 15:44 <a href="http://www.cppblog.com/JonsenElizee/archive/2010/07/20/120880.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>