⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 谈谈对齐 - c-c++ - embeded linux.htm

📁 講述ARM下的字符數據對齊方式的內容
💻 HTM
📖 第 1 页 / 共 4 页
字号:
typedef ARM_PACKED struct St2Tag
{
	St1 st1;
	char ch2;
}
GNUC_PACKED St2;
#ifdef WIN32
#pragma pack()
#endif
</PRE>
                        <P 
                        style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">其中:__GNUC__是gcc的预定义宏,__arm__是ARM编译器的预定义宏,可以用它们识别当前的编译器。</P>
                        <H3 
                        style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; PADDING-RIGHT: 0.6em; BORDER-TOP: rgb(204,204,204) 1px dotted; PADDING-LEFT: 0.6em; FONT-SIZE: 12px; PADDING-BOTTOM: 0.6em; MARGIN: 6px 0px 0px; BORDER-LEFT: rgb(204,204,204) 1px dotted; PADDING-TOP: 0.6em; BORDER-BOTTOM: rgb(204,204,204) 1px dotted; FONT-FAMILY: 'Microsoft yahei', verdana, sans-serif">2.4 
                        全局设置</H3>
                        <P 
                        style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">在VC中,有的程序员习惯设置整个工程的struct 
                        member 
                        alignment,这对应于命令行选项“/Zpi”,其中i=1,2,4,8,16。如果将这个值设为1,工程中所有结构都是紧缩排列。紧缩排列会增大代码量,降低结构访问效率。我们应该仅在必要的时候使用紧缩结构。</P>
                        <P 
                        style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">“/Zp1”是紧缩排列,那么“/Zp2”,“/Zp4”等选项是怎样排列的呢?</P>
                        <P 
                        style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">设选项“/Zpi”中设定的长度是i,设某个结构成员的基本长度是m,则该结构成员按照m和i中较小的值对齐。例如:如果我们设置了“/Zp2”,则基本长度不大于2的成员按照基本长度对齐,基本长度大于2的成员按照2对齐。</P>
                        <P 
                        style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">其实,我们不应该使用“/Zp2”这么奇怪的选项,除非有非如此不可的理由。</P>
                        <H3 
                        style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; PADDING-RIGHT: 0.6em; BORDER-TOP: rgb(204,204,204) 1px dotted; PADDING-LEFT: 0.6em; FONT-SIZE: 12px; PADDING-BOTTOM: 0.6em; MARGIN: 6px 0px 0px; BORDER-LEFT: rgb(204,204,204) 1px dotted; PADDING-TOP: 0.6em; BORDER-BOTTOM: rgb(204,204,204) 1px dotted; FONT-FAMILY: 'Microsoft yahei', verdana, sans-serif">2.5 
                        紧缩结构的用途</H3>
                        <P 
                        style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">其实最常用的结构对齐选项就是:默认对齐和紧缩。在两个程序,或者两个平台之间传递数据时,我们通常会将数据结构设置为紧缩的。这样不仅可以减小通信量,还可以避免对齐带来的麻烦。假设甲乙双方进行跨平台通信,甲方使用了“/Zp2”这么奇怪的对齐选项,而乙方的编译器不支持这种对齐方式,那么乙方就可以理解什么叫欲哭无泪了。</P>
                        <P 
                        style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">当我们需要一个字节一个字节访问结构数据时,我们通常都会希望结构是紧缩的,这样就不必考虑哪个字节是填充字节了。我们把数据保存到非易失设备时,通常也会采用紧缩结构,既减小存储量,也方便其它程序读出。</P>
                        <H3 
                        style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; PADDING-RIGHT: 0.6em; BORDER-TOP: rgb(204,204,204) 1px dotted; PADDING-LEFT: 0.6em; FONT-SIZE: 12px; PADDING-BOTTOM: 0.6em; MARGIN: 6px 0px 0px; BORDER-LEFT: rgb(204,204,204) 1px dotted; PADDING-TOP: 0.6em; BORDER-BOTTOM: rgb(204,204,204) 1px dotted; FONT-FAMILY: 'Microsoft yahei', verdana, sans-serif">2.6 
                        细节</H3>
                        <P 
                        style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">最后记录一个小细节。gcc编译器和VC编译器都支持在紧缩结构中包含非紧缩结构,例如前面例子中的St2可以包含非紧缩的St1。但对于ARM编译器而言,紧缩结构包含的其它结构必须是紧缩的。如果紧缩的St2包含了非紧缩的St1,编译时就会报错:</P><PRE>error:  #1031: Definition of "struct St1Tag" in packed "struct St1T2g" must be __packed</PRE><PRE><SPAN class=Apple-style-span style="FONT-SIZE: 12px"><SPAN class=Apple-style-span style="FONT-FAMILY: verdana; WHITE-SPACE: normal"><H2 style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">3 数据对齐</H2><H3 style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; PADDING-RIGHT: 0.6em; BORDER-TOP: rgb(204,204,204) 1px dotted; PADDING-LEFT: 0.6em; FONT-SIZE: 12px; PADDING-BOTTOM: 0.6em; MARGIN: 6px 0px 0px; BORDER-LEFT: rgb(204,204,204) 1px dotted; PADDING-TOP: 0.6em; BORDER-BOTTOM: rgb(204,204,204) 1px dotted; FONT-FAMILY: 'Microsoft yahei', verdana, sans-serif">3.1 CISC和RISC</H3><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">CPU从指令集的特点上可以分为两类:CISC和RISC。CISC和RISC分别是复杂指令集计算机(Complex Instruction Set Computer)和精简指令集计算机(Reduced Instruction Set Computer)的缩写。</P><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">CPU的工作可以看作以下步骤的反复循环:</P><UL style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 5px 0px 5px 35px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none"><LI style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 2px; MARGIN: 0px; PADDING-TOP: 2px; LIST-STYLE-TYPE: disc">step 1: 取指令<LI style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 2px; MARGIN: 0px; PADDING-TOP: 2px; LIST-STYLE-TYPE: disc">step 2: 取数据<LI style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 2px; MARGIN: 0px; PADDING-TOP: 2px; LIST-STYLE-TYPE: disc">step 3: 执行指令<LI style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 2px; MARGIN: 0px; PADDING-TOP: 2px; LIST-STYLE-TYPE: disc">step 4: 输出结果</LI></UL><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">CISC CPU支持很多寻址模式,因此取数据的时间是不确定的。 RISC CPU的最大特点是简化了指令的寻址模式,除了Load/Store指令外,其它指令都采用寄存器寻址,即从寄存器读写数据。这种设计使取数据的时间相对稳定,可以简化指令流水线的设计。</P><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">一般而言,RISC架构可以降低CPU的复杂性以及允许在同样的工艺水平下生产出功能更强大的CPU,但对于编译器的设计有更高的要求。</P><H3 style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; PADDING-RIGHT: 0.6em; BORDER-TOP: rgb(204,204,204) 1px dotted; PADDING-LEFT: 0.6em; FONT-SIZE: 12px; PADDING-BOTTOM: 0.6em; MARGIN: 6px 0px 0px; BORDER-LEFT: rgb(204,204,204) 1px dotted; PADDING-TOP: 0.6em; BORDER-BOTTOM: rgb(204,204,204) 1px dotted; FONT-FAMILY: 'Microsoft yahei', verdana, sans-serif">3.2 对齐数据访问</H3><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">RISC CPU的Load/Store指令要求数据是对齐的。长度为4的数据应放在4n边界上,长度为2的数据应放在2n边界上。以ARM CPU的Load为例:</P><PRE>LDR       R5,[R4]
LDRSH     R7,[R6]
LDRB      R9,[R8]
</PRE><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">LDR、LDRSH、LDRB分别从存储器读取一个字、半字和字节,放到指定寄存器。例如“LDR R5,[R4]”就是从R4指向的存储单元中读一个字(长度为4),放到R5中。 LDR要求数据地址在4n边界上,否则就会发生错误。LDRSH要求数据地址在2n边界上,否则就会发生错误。</P><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">发生什么错误呢?这与具体的CPU有关,在ARM7TDMI上,非对齐访问会导致程序跳到数据访问错误的处理向量,即地址0x00000010处。在ARM920T上,LDR指令可能返回错误的数据。</P><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">CISC的CPU支持非对齐的数据读取。</P><H3 style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; PADDING-RIGHT: 0.6em; BORDER-TOP: rgb(204,204,204) 1px dotted; PADDING-LEFT: 0.6em; FONT-SIZE: 12px; PADDING-BOTTOM: 0.6em; MARGIN: 6px 0px 0px; BORDER-LEFT: rgb(204,204,204) 1px dotted; PADDING-TOP: 0.6em; BORDER-BOTTOM: rgb(204,204,204) 1px dotted; FONT-FAMILY: 'Microsoft yahei', verdana, sans-serif">3.3 例子</H3><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">我们来看一个例子:</P><PRE>// 例子1
void test(void)
{
	char a[] = {1,2,3,4,5};
	int *pi, i;
	
	printf("&amp;a[1]=%p\n", &amp;a[1]);
	pi = (int *)&amp;a[1];
	i = *pi;
	printf("%08X\n", i);
}
</PRE><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">关键是这句:</P><PRE>	i = *pi;
</PRE><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">我们知道地址pi指向的4个字节依次是:0x02,0x03,0x04,0x05。在小尾的CPU上,我们期待的输出是05040302。让我们看看这段代码在不同平台的运行效果。</P><H4 style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">3.3.1 PC/Windows</H4><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">输出结果是:</P><PRE>&amp;a[1]=0012FF25
05040302
</PRE><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">符合我们的预期,也说明PC的CPU支持非对齐的数据读取。</P><H4 style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">3.3.2 PC/Linux</H4><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">输出结果是:</P><PRE>&amp;a[1]=0xbfa0c36c
05040302
</PRE><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">值得注意的是gcc编译器将局部变量a放在了1n边界(0xbfa0c36b)上。我们希望pi是一个奇数地址,将测试代码修改为:</P><PRE>// 例子2
void test(void)
{
        int a[] = {0x04030201, 0x08070605};
        int *pi, i;

        pi = (int *)&amp;((char *)&amp;a)[1];
        printf("pi=%p\n", pi);
        i = *pi;
        printf("%08X\n", i);
}
</PRE><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">输出结果是:</P><PRE>pi=0xbfe87fe9
05040302
</PRE><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">符合我们的预期。数据对齐是CPU的问题,和编译器、操作系统没有关系。</P><H4 style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">3.3.3 ARM920T/Linux</H4><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">输出结果是:</P><PRE>&amp;a[1]=0xbec49e55
01040302
</PRE><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">考虑到小尾,CPU实际读到的4个字节依次是0x02,0x03,0x04,0x01。这个结果不是我们所预期的,CPU出错了。</P><H4 style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">3.3.4 ARM7TDMI</H4><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">程序在执行:</P><PRE>	i = *pi;
</PRE><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">时直接跳回Data Abort的处理向量,即地址0x00000010。</P><H3 style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; PADDING-RIGHT: 0.6em; BORDER-TOP: rgb(204,204,204) 1px dotted; PADDING-LEFT: 0.6em; FONT-SIZE: 12px; PADDING-BOTTOM: 0.6em; MARGIN: 6px 0px 0px; BORDER-LEFT: rgb(204,204,204) 1px dotted; PADDING-TOP: 0.6em; BORDER-BOTTOM: rgb(204,204,204) 1px dotted; FONT-FAMILY: 'Microsoft yahei', verdana, sans-serif">3.4 对策</H3><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">在读取紧缩结构或结构的紧缩成员时,编译器会自动产生按字节读取的代码。我们只要在做强制指针转换时细心一些就可以了。我们不应该将指向窄数据的指针强制转换成指向宽数据的指针。在可能发生数据对齐问题的地方,按字节读取数据。</P><H2 style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">4 结束语</H2><P style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 14px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; TEXT-INDENT: 2em; LINE-HEIGHT: 22px; PADDING-TOP: 0px">我很欣赏一本叫作《玫瑰的名字》的小说。这是一本侦探小说,但给了我不少编程的启示。威廉教士在迷宫内解不开谜团,在迷宫外却推理出迷宫的真相。我也倾向于在头脑中调试程序,调试器只是不得已而用之。身陷其中,既会改变要测试的对象,也可能被表象迷惑。从外面观察,通过想象推理,有时更容易发现真相,或抓住调试的重点。本文讨论了一些与对齐相关的细节。多了解一些细节,有助于我们在头脑中形成更清晰的程序映像。</P></SPAN></SPAN></PRE></SPAN></SPAN>
                        <P></P></SPAN></DIV></TD></TR></TBODY></TABLE>
                  <P style="MARGIN: 5px; LINE-HEIGHT: 150%"></P></TD></TR>
              <TR>
                <TD align=middle height=25><FONT color=#295200>发表于: 2008-10-13 
                  ,修改于: 2008-10-13 09:46,已浏览173次,有评论0条</FONT> <A id=star 
                  title=推荐这篇文章 onclick="NewWindows(this.href);return false;" 
                  href="http://blog.chinaunix.net/u2/star.php?blogid=70445&amp;artid=1287302">推荐</A> 
                  <A id=complaint title=投诉这篇文章 
                  onclick="NewWindows(this.href);return false;" 
                  href="http://blog.chinaunix.net/u2/complaint.php?blogid=70445&amp;artid=1287302">投诉</A> 
                </TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD>
    <TD width=18 
    background="谈谈对齐 - C-C++ - Embeded Linux.files/bg_art_right.gif"></TD></TR>
  <TR>
    <TD width=18 height=28><IMG alt="" 
      src="谈谈对齐 - C-C++ - Embeded Linux.files/bg_art_left_bottom.gif" 
    border=0></TD>
    <TD background="谈谈对齐 - C-C++ - Embeded Linux.files/bg_art_bottom.gif">
      <P style="MARGIN: 5px; LINE-HEIGHT: 150%"></P></TD>
    <TD width=18 height=28><IMG alt="" 
      src="谈谈对齐 - C-C++ - Embeded Linux.files/bg_art_right_bottom.gif" 
    border=0></TD></TR></TBODY></TABLE><BR>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#a5bd6b cellSpacing=1 
cellPadding=0 width="90%" align=center border=1>
  <TBODY>
  <TR>
    <TD style="COLOR: #295200" bgColor=#eff7de height=25><B>网友评论</B></TD></TR>
  <TR>
    <TD bgColor=#ffffff height=1></TD></TR>
  <TR>
    <TD align=middle bgColor=#f9f5e7>
      <TABLE 
      style="COLOR: #295200; BORDER-COLLAPSE: collapse; WORD-WRAP: break-word" 
      cellSpacing=0 cellPadding=0 width="100%" align=center border=0>
        <TBODY></TBODY></TABLE></TD></TR></TBODY></TABLE><BR>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#a5bd6b cellSpacing=1 
cellPadding=0 width="90%" align=center border=1>
  <TBODY>
  <TR>
    <TD style="COLOR: #295200" bgColor=#eff7de height=25><B>发表评论</B></TD></TR>
  <TR>
    <TD bgColor=#ffffff height=1></TD></TR>
  <TR>
    <TD align=middle bgColor=#f9f5e7><IFRAME name=comment 
      src="谈谈对齐 - C-C++ - Embeded Linux.files/comment.htm" frameBorder=0 
      width="100%" height=160></IFRAME></TD></TR></TBODY></TABLE></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -