﻿<?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++博客-明镜止水</title><link>http://www.cppblog.com/henry90/</link><description>知行合一</description><language>zh-cn</language><lastBuildDate>Tue, 14 Apr 2026 23:06:37 GMT</lastBuildDate><pubDate>Tue, 14 Apr 2026 23:06:37 GMT</pubDate><ttl>60</ttl><item><title>关于pragma字节强制对齐的讨论</title><link>http://www.cppblog.com/henry90/archive/2012/10/24/193810.html</link><dc:creator>寒璿</dc:creator><author>寒璿</author><pubDate>Wed, 24 Oct 2012 13:29:00 GMT</pubDate><guid>http://www.cppblog.com/henry90/archive/2012/10/24/193810.html</guid><wfw:comment>http://www.cppblog.com/henry90/comments/193810.html</wfw:comment><comments>http://www.cppblog.com/henry90/archive/2012/10/24/193810.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/henry90/comments/commentRss/193810.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/henry90/services/trackbacks/193810.html</trackback:ping><description><![CDATA[使用#pragma pack（NUM_OF_BYTE）可以实现字节对齐<br /><div>#include &lt;cstdio&gt;</div><div></div><div>#pragma pack(2)</div><div>struct C</div><div>{</div><div>&nbsp; &nbsp; char b;</div><div>&nbsp; &nbsp; int a;</div><div>&nbsp; &nbsp; double d;</div><div>&nbsp; &nbsp; short c;</div><div>}test;</div><div>#pragma pack()</div><div></div><div>int main()</div><div>{</div><div>&nbsp; &nbsp; printf("%p %p %p %p", &amp;test.b, &amp;test.a, &amp;test.d, &amp;test.c);</div><div>}</div><div>上例是按2字节对齐，可以按1 2 4 8字节对齐，除此之外，都不能编译通过<br /><img src="http://www.cppblog.com/images/cppblog_com/henry90/images/pragma5.jpg" width="450" height="311" alt="" /><br /><img src="http://www.cppblog.com/images/cppblog_com/henry90/images/pragma9.jpg" width="463" height="308" alt="" /><img src="http://www.cppblog.com/images/cppblog_com/henry90/images/pragma8.jpg" width="293" height="344" alt="" /><br /></div><img src ="http://www.cppblog.com/henry90/aggbug/193810.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/henry90/" target="_blank">寒璿</a> 2012-10-24 21:29 <a href="http://www.cppblog.com/henry90/archive/2012/10/24/193810.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OpenGL入门技巧——字体的渲染（引用黑莓样例源码）</title><link>http://www.cppblog.com/henry90/archive/2012/08/31/188890.html</link><dc:creator>寒璿</dc:creator><author>寒璿</author><pubDate>Fri, 31 Aug 2012 03:35:00 GMT</pubDate><guid>http://www.cppblog.com/henry90/archive/2012/08/31/188890.html</guid><wfw:comment>http://www.cppblog.com/henry90/comments/188890.html</wfw:comment><comments>http://www.cppblog.com/henry90/archive/2012/08/31/188890.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/henry90/comments/commentRss/188890.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/henry90/services/trackbacks/188890.html</trackback:ping><description><![CDATA[《OpenGL编程精粹》是本很好的书，但是渲染字体的步骤让我头疼，要自己载入图片，自己写一个类，如果有以往开发的经验和源码，直接引用还可以。<br />但是对于新手来说，还是简单点好，这里介绍的例子是黑莓样例Hello World中的字体渲染技巧，能不能通用还有待检验啊。<br /><div>&nbsp; &nbsp; &nbsp; &nbsp; int dpi = bbutil_calculate_dpi(screen_cxt);</div><div><span style="white-space:pre">	</span>font = bbutil_load_font(</div><div><span style="white-space:pre">			</span>"/usr/fonts/font_repository/adobe/MyriadPro-Bold.otf", 10, dpi);</div><div><span style="white-space:pre">	</span>if (!font) {</div><div><span style="white-space:pre">		</span>fprintf(stderr, "cant open font\n");</div><div><span style="white-space: pre; ">	</span>}<br />先load一个font文件，可以看到，使用了adobe的字体库，在大多数电脑上都应该有这个字体库，类似的库当然也可以。<br />bbutil_load_font文件，看起来有点长，别担心，这些都是可以直接引用的代码：<br /><div>font_t* bbutil_load_font(const char* path, int point_size, int dpi) {</div><div>&nbsp; &nbsp; FT_Library library;</div><div>&nbsp; &nbsp; FT_Face face;</div><div>&nbsp; &nbsp; int c;</div><div>&nbsp; &nbsp; int i, j;</div><div>&nbsp; &nbsp; font_t* font;</div><div></div><div>&nbsp; &nbsp; if (!initialized) {</div><div>&nbsp; &nbsp; <span style="white-space:pre">	</span>fprintf(stderr, "EGL has not been initialized\n");</div><div>&nbsp; &nbsp; <span style="white-space:pre">	</span>return NULL;</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; if (!path){</div><div>&nbsp; &nbsp; <span style="white-space:pre">	</span>fprintf(stderr, "Invalid path to font file\n");</div><div><span style="white-space:pre">		</span>return NULL;</div><div><span style="white-space:pre">	</span>}</div><div></div><div>&nbsp; &nbsp; if(FT_Init_FreeType(&amp;library)) {</div><div>&nbsp; &nbsp; <span style="white-space:pre">	</span>fprintf(stderr, "Error loading Freetype library\n");</div><div>&nbsp; &nbsp; <span style="white-space:pre">	</span>return NULL;</div><div>&nbsp; &nbsp; }</div><div>&nbsp; &nbsp; if (FT_New_Face(library, path,0,&amp;face)) {</div><div><span style="white-space:pre">		</span>fprintf(stderr, "Error loading font %s\n", path);</div><div><span style="white-space:pre">		</span>return NULL;</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; if(FT_Set_Char_Size ( face, point_size * 64, point_size * 64, dpi, dpi)) {</div><div><span style="white-space:pre">		</span>fprintf(stderr, "Error initializing character parameters\n");</div><div><span style="white-space:pre">		</span>return NULL;</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; font = (font_t*) malloc(sizeof(font_t));</div><div>&nbsp; &nbsp; font-&gt;initialized = false;</div><div></div><div>&nbsp; &nbsp; glGenTextures(1, &amp;(font-&gt;font_texture));</div><div></div><div>&nbsp; &nbsp; //Let each glyph reside in 32x32 section of the font texture</div><div>&nbsp; &nbsp; int segment_size_x = 0, segment_size_y = 0;</div><div>&nbsp; &nbsp; int num_segments_x = 16;</div><div>&nbsp; &nbsp; int num_segments_y = 8;</div><div></div><div>&nbsp; &nbsp; FT_GlyphSlot slot;</div><div>&nbsp; &nbsp; FT_Bitmap bmp;</div><div>&nbsp; &nbsp; int glyph_width, glyph_height;</div><div></div><div>&nbsp; &nbsp; //First calculate the max width and height of a character in a passed font</div><div>&nbsp; &nbsp; for(c = 0; c &lt; 128; c++) {</div><div><span style="white-space:pre">		</span>if(FT_Load_Char(face, c, FT_LOAD_RENDER)) {</div><div><span style="white-space:pre">			</span>fprintf(stderr, "FT_Load_Char failed\n");</div><div><span style="white-space:pre">			</span>free(font);</div><div><span style="white-space:pre">			</span>return NULL;</div><div><span style="white-space:pre">		</span>}</div><div></div><div><span style="white-space:pre">		</span>slot = face-&gt;glyph;</div><div><span style="white-space:pre">		</span>bmp = slot-&gt;bitmap;</div><div></div><div><span style="white-space:pre">		</span>//glyph_width = nextp2(bmp.width);</div><div><span style="white-space:pre">		</span>//glyph_height = nextp2(bmp.rows);</div><div></div><div><span style="white-space:pre">		</span>glyph_width = bmp.width;</div><div><span style="white-space:pre">		</span>glyph_height = bmp.rows;</div><div></div><div><span style="white-space:pre">		</span>if (glyph_width &gt; segment_size_x) {</div><div><span style="white-space:pre">			</span>segment_size_x = glyph_width;</div><div><span style="white-space:pre">		</span>}</div><div></div><div><span style="white-space:pre">		</span>if (glyph_height &gt; segment_size_y) {</div><div><span style="white-space:pre">			</span>segment_size_y = glyph_height;</div><div><span style="white-space:pre">		</span>}</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; int font_tex_width = nextp2(num_segments_x * segment_size_x);</div><div>&nbsp; &nbsp; int font_tex_height = nextp2(num_segments_y * segment_size_y);</div><div></div><div>&nbsp; &nbsp; int bitmap_offset_x = 0, bitmap_offset_y = 0;</div><div></div><div>&nbsp; &nbsp; GLubyte* font_texture_data = (GLubyte*) malloc(sizeof(GLubyte) * 2 * font_tex_width * font_tex_height);</div><div></div><div>&nbsp; &nbsp; if (!font_texture_data) {</div><div><span style="white-space:pre">		</span>fprintf(stderr, "Failed to allocate memory for font texture\n");</div><div><span style="white-space:pre">		</span>free(font);</div><div><span style="white-space:pre">		</span>return NULL;</div><div><span style="white-space:pre">	</span>}</div><div></div><div>&nbsp; &nbsp; // Fill font texture bitmap with individual bmp data and record appropriate size, texture coordinates and offsets for every glyph</div><div>&nbsp; &nbsp; for(c = 0; c &lt; 128; c++) {</div><div><span style="white-space:pre">		</span>if(FT_Load_Char(face, c, FT_LOAD_RENDER)) {</div><div><span style="white-space:pre">			</span>fprintf(stderr, "FT_Load_Char failed\n");</div><div><span style="white-space:pre">			</span>free(font);</div><div><span style="white-space:pre">			</span>return NULL;</div><div><span style="white-space:pre">		</span>}</div><div></div><div><span style="white-space:pre">		</span>slot = face-&gt;glyph;</div><div><span style="white-space:pre">		</span>bmp = slot-&gt;bitmap;</div><div></div><div><span style="white-space:pre">		</span>glyph_width = nextp2(bmp.width);</div><div><span style="white-space:pre">		</span>glyph_height = nextp2(bmp.rows);</div><div></div><div><span style="white-space:pre">		</span>div_t temp = div(c, num_segments_x);</div><div></div><div><span style="white-space:pre">		</span>bitmap_offset_x = segment_size_x * temp.rem;</div><div><span style="white-space:pre">		</span>bitmap_offset_y = segment_size_y * temp.quot;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; for (j = 0; j &lt; glyph_height; j++) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; <span style="white-space:pre">	</span>for (i = 0; i &lt; glyph_width; i++) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; <span style="white-space:pre">		</span>font_texture_data[2 * ((bitmap_offset_x + i) + (j + bitmap_offset_y) * font_tex_width) + 0] =</div><div>&nbsp; &nbsp; &nbsp; &nbsp; <span style="white-space:pre">		</span>font_texture_data[2 * ((bitmap_offset_x + i) + (j + bitmap_offset_y) * font_tex_width) + 1] =</div><div><span style="white-space:pre">					</span>(i &gt;= bmp.width || j &gt;= bmp.rows)? 0 : bmp.buffer[i + bmp.width * j];</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; font-&gt;advance[c] = (float)(slot-&gt;advance.x &gt;&gt; 6);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; font-&gt;tex_x1[c] = (float)bitmap_offset_x / (float) font_tex_width;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; font-&gt;tex_x2[c] = (float)(bitmap_offset_x + bmp.width) / (float)font_tex_width;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; font-&gt;tex_y1[c] = (float)bitmap_offset_y / (float) font_tex_height;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; font-&gt;tex_y2[c] = (float)(bitmap_offset_y + bmp.rows) / (float)font_tex_height;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; font-&gt;width[c] = bmp.width;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; font-&gt;height[c] = bmp.rows;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; font-&gt;offset_x[c] = (float)slot-&gt;bitmap_left;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; font-&gt;offset_y[c] = &nbsp;(float)((slot-&gt;metrics.horiBearingY-face-&gt;glyph-&gt;metrics.height) &gt;&gt; 6);</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; glBindTexture(GL_TEXTURE_2D, font-&gt;font_texture);</div><div>&nbsp; &nbsp; glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);</div><div>&nbsp; &nbsp; glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);</div><div></div><div>&nbsp; &nbsp; glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, font_tex_width, font_tex_height, 0, GL_LUMINANCE_ALPHA , GL_UNSIGNED_BYTE, font_texture_data);</div><div></div><div>&nbsp; &nbsp; int err = glGetError();</div><div></div><div>&nbsp; &nbsp; free(font_texture_data);</div><div></div><div>&nbsp; &nbsp; FT_Done_Face(face);</div><div>&nbsp; &nbsp; FT_Done_FreeType(library);</div><div></div><div>&nbsp; &nbsp; if (err != 0) {</div><div>&nbsp; &nbsp; <span style="white-space:pre">	</span>fprintf(stderr, "GL Error 0x%x", err);</div><div>&nbsp; &nbsp; <span style="white-space:pre">	</span>free(font);</div><div>&nbsp; &nbsp; <span style="white-space:pre">	</span>return NULL;</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; font-&gt;initialized = true;</div><div>&nbsp; &nbsp; return font;</div><div>}<br />font_t类型如下：<br /><div>typedef struct{</div><div>&nbsp; &nbsp; unsigned int font_texture;</div><div>&nbsp; &nbsp; float pt;</div><div>&nbsp; &nbsp; float advance[128];</div><div>&nbsp; &nbsp; float width[128];</div><div>&nbsp; &nbsp; float height[128];</div><div>&nbsp; &nbsp; float tex_x1[128];</div><div>&nbsp; &nbsp; float tex_x2[128];</div><div>&nbsp; &nbsp; float tex_y1[128];</div><div>&nbsp; &nbsp; float tex_y2[128];</div><div>&nbsp; &nbsp; float offset_x[128];</div><div>&nbsp; &nbsp; float offset_y[128];</div><div>&nbsp; &nbsp; int initialized;</div><div>} font_t;<br />这样就可以使用系统的字体了，字体大小和位置：<br /><div>void bbutil_measure_text(font_t* font, char* msg, float *width, float* height) {</div><div><span style="white-space:pre">	</span>int i, c;</div><div></div><div><span style="white-space:pre">	</span>if (!msg) {</div><div><span style="white-space:pre">		</span>return;</div><div><span style="white-space:pre">	</span>}</div><div></div><div><span style="white-space:pre">	</span>if (width) {</div><div><span style="white-space:pre">		</span>//Width of a text rectangle is a sum advances for every glyph in a string</div><div><span style="white-space:pre">		</span>*width = 0.0f;</div><div></div><div><span style="white-space:pre">		</span>for(i = 0; i &lt; strlen(msg); ++i) {</div><div><span style="white-space:pre">			</span>c = msg[i];</div><div><span style="white-space:pre">			</span>*width += font-&gt;advance[c];</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">	</span>}</div><div></div><div><span style="white-space:pre">	</span>if (height) {</div><div><span style="white-space:pre">		</span>//Height of a text rectangle is a high of a tallest glyph in a string</div><div><span style="white-space:pre">		</span>*height = 0.0f;</div><div></div><div><span style="white-space:pre">		</span>for(i = 0; i &lt; strlen(msg); ++i) {</div><div><span style="white-space:pre">			</span>c = msg[i];</div><div></div><div><span style="white-space:pre">			</span>if (*height &lt; font-&gt;height[c]) {</div><div><span style="white-space:pre">				</span>*height = font-&gt;height[c];</div><div><span style="white-space:pre">			</span>}</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">	</span>}</div><div>}<br /><div>float text_width, text_height;</div><div><span style="white-space:pre">	</span>bbutil_measure_text(font, notice, &amp;text_width, &amp;text_height);</div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">	</span>pos_x = (width - text_width) / 2;</div><div><span style="white-space:pre">	</span>pos_y = height / 2;<br />字体的渲染：<br /><div>bbutil_render_text(font, notice, pos_x, pos_y);</div><div><span style="white-space:pre">	</span>bbutil_render_text(font, sscore, pos_x2, pos_y2);<br /><br />这一篇不是原创，借鉴了很多黑莓样例的源码，主要是为了在开发中节省时间，OpenGL方面的知识还需要学习。<br /></div></div></div></div></div></div><img src ="http://www.cppblog.com/henry90/aggbug/188890.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/henry90/" target="_blank">寒璿</a> 2012-08-31 11:35 <a href="http://www.cppblog.com/henry90/archive/2012/08/31/188890.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OpenGL入门技巧——圆形绘制与渲染</title><link>http://www.cppblog.com/henry90/archive/2012/08/31/188887.html</link><dc:creator>寒璿</dc:creator><author>寒璿</author><pubDate>Fri, 31 Aug 2012 02:59:00 GMT</pubDate><guid>http://www.cppblog.com/henry90/archive/2012/08/31/188887.html</guid><wfw:comment>http://www.cppblog.com/henry90/comments/188887.html</wfw:comment><comments>http://www.cppblog.com/henry90/archive/2012/08/31/188887.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/henry90/comments/commentRss/188887.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/henry90/services/trackbacks/188887.html</trackback:ping><description><![CDATA[Qt和其他众多库中，圆形绘制可能并不困难，但是OpenGL不是，因为OpenGL中的一切图形都是基于面和坐标。<br />渲染一个正方形或者正方体并不困难，只需要指出4或6或8个点，也就是顶点数组，就能看出效果。<br />但是对于初学者来讲，很难想到该如何渲染一个圆。<br />其实，只需要增加点数，同时调用正余弦函数，创建圆形顶点数组的简单代码如下：<br /><div>&nbsp; &nbsp; &nbsp; &nbsp; int i;</div><div><span style="white-space:pre">	</span>/*</div><div><span style="white-space:pre">	</span>为了尽量近似圆形，需要360个点。</div><div><span style="white-space:pre">	</span>每个点有两个值：x轴和y轴，所以需要计算720个数值。</div><div><span style="white-space:pre">	</span>*/</div><div><span style="white-space:pre">	</span>for (i = 0; i &lt; 720; i += 2) {</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;// x value</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;vertices[i] &nbsp; = (cos(DEGREES_TO_RADIANS(i/2)) * 1);</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;// y value</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;vertices[i+1] = (sin(DEGREES_TO_RADIANS(i/2)) * 1);</div><div><span style="white-space:pre">	</span>}</div><div>之后，在渲染函数里面加上：<br /><div>&nbsp; &nbsp; &nbsp; &nbsp; glEnableClientState(GL_VERTEX_ARRAY);</div><div><span style="white-space:pre">	</span>glVertexPointer(2, GL_FLOAT, 0, vertices);<br />颜色渲染方面还是按照常规的步骤：<br /><div><span style="white-space:pre">	</span>glClearColor(0.5f, 0.7f, 0.9f, 1.0f); &nbsp; //指定颜色</div><div>&nbsp; &nbsp; &nbsp; &nbsp; glClear(GL_COLOR_BUFFER_BIT); &nbsp; //刷出颜色<br />注意，绘制圆形的时候选定好绘制方式，不然可能绘制出的只是一系列点，在屏幕上显示不明显，误以为代码错误。</div>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;glDrawArrays(GL_TRIANGLE_FAN, 0, 360); &nbsp; //这个绘制方法可以理解为连续填充绘制，绘制出的是完整的圆形，不是离散的点<br /><br />写这篇的原因是，我绘制圆形的时候找了很久才拼凑起有效的方法，算是半个原创吧，希望更多的人能更容易得搜索到，节省时间。</div></div><img src ="http://www.cppblog.com/henry90/aggbug/188887.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/henry90/" target="_blank">寒璿</a> 2012-08-31 10:59 <a href="http://www.cppblog.com/henry90/archive/2012/08/31/188887.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>字符串自动机的思考——从百度之星E题谈起</title><link>http://www.cppblog.com/henry90/archive/2012/06/01/177086.html</link><dc:creator>寒璿</dc:creator><author>寒璿</author><pubDate>Fri, 01 Jun 2012 08:39:00 GMT</pubDate><guid>http://www.cppblog.com/henry90/archive/2012/06/01/177086.html</guid><wfw:comment>http://www.cppblog.com/henry90/comments/177086.html</wfw:comment><comments>http://www.cppblog.com/henry90/archive/2012/06/01/177086.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/henry90/comments/commentRss/177086.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/henry90/services/trackbacks/177086.html</trackback:ping><description><![CDATA[<p style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; ">2012百度之星的E题吧，因为之间没准备，卡在这道水题上，程序一直wrong answer。</p><p style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; ">昨晚找人讨论了字符串的问题，写一点思考出来。</p><p style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; ">E题的大意是：c变量名风格是小写字母带下划线，比如：long_an，Java变量名是首字母小写，其后每个单词首字母大写。</p><p style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; ">但是在判定逻辑时，我对有些情况有疑惑：</p><p style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; ">1.双下划线，__exit，file__exit</p><p style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; ">2.首字符下划线，_exit</p><p style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; ">3.末尾字符下划线，__exit_</p><p style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; ">4.java这样的变量名：bAIDU</p><p style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; ">其实，以上这些情况都是合法的，比如双下划线，在调用某些系统函数时，经常遇到。这些都是琐碎逻辑的问题。</p><p style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; ">按照水题的标准来说，应该可以对c风格变量名的字符串使用strlwr和strcmp函数，直接比较即可得出。java的变量名判定就要容易一些，E题过的人代码都比较短，大概是这样做的吧。</p><p style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; ">晚上找同学讨论，他告诉我说字符串处理都可以用自动机来实现，这是收获颇丰的一点，比如上面的E题。</p><p style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; ">起始0状态遇到大写字母直接终结，遇到小写字母和下划线进入下一个状态1，然后依次判定，这样的代码会简短和精密许多。</p><img src ="http://www.cppblog.com/henry90/aggbug/177086.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/henry90/" target="_blank">寒璿</a> 2012-06-01 16:39 <a href="http://www.cppblog.com/henry90/archive/2012/06/01/177086.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为什么重载逻辑运算操作符不支持短路求值，用函数实现IF的语义错误</title><link>http://www.cppblog.com/henry90/archive/2012/05/07/173905.html</link><dc:creator>寒璿</dc:creator><author>寒璿</author><pubDate>Mon, 07 May 2012 07:19:00 GMT</pubDate><guid>http://www.cppblog.com/henry90/archive/2012/05/07/173905.html</guid><wfw:comment>http://www.cppblog.com/henry90/comments/173905.html</wfw:comment><comments>http://www.cppblog.com/henry90/archive/2012/05/07/173905.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/henry90/comments/commentRss/173905.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/henry90/services/trackbacks/173905.html</trackback:ping><description><![CDATA[<p style="color: #524222; font-family: 'Microsoft Yahei', Arial; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; width: 900px; ">IF 家族的分支语句，在计算机程序设计中可以说必不可少。相信读者都很熟悉这种 IF 结构</p><pre style="white-space: pre-wrap; word-wrap: break-word; color: #524222; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; ">IF 条件 THEN</pre><pre style="white-space: pre-wrap; word-wrap: break-word; color: #524222; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; ">    一些语句;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; color: #524222; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; ">ELSE</pre><pre style="white-space: pre-wrap; word-wrap: break-word; color: #524222; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; ">    另一些语句;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; color: #524222; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; ">END IF</pre><p style="color: #524222; font-family: 'Microsoft Yahei', Arial; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; width: 900px; ">这是从 ALGOL 语言一脉相承下来的，很&#8220;自然&#8221;的 IF 写法。而早期的 FORTRAN 的 IF 写法却不这么直观，而是</p><pre style="white-space: pre-wrap; word-wrap: break-word; color: #524222; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; ">IF (表达式) A B C</pre><p style="color: #524222; font-family: 'Microsoft Yahei', Arial; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; width: 900px; ">取决于表达式的值是小于零，等于零还是大于零，分别跳到（等价于 goto）标签 A， 标签B 或者标签 C。这个 IF 隐含了三个 Goto，可以说和结构化编程的实践截然相反，降低了程序的可读性。 Fortran 首创的这个三分支跳转的 IF 饱受诟病，Fortran 77 开始支持结构化的 IF，而 Fortran 90 标准进一步宣布三分支跳转的用法已经&#8220;过时&#8221;，不支持使用。</p><p style="color: #524222; font-family: 'Microsoft Yahei', Arial; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; width: 900px; ">用 XIF 子程序完成类似于 IF 的分支功能，用法是：</p><pre style="white-space: pre-wrap; word-wrap: break-word; color: #524222; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; ">XIF(条件, 表达式A, 表达式B)</pre><p style="color: #524222; font-family: 'Microsoft Yahei', Arial; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; width: 900px; ">取决于条件的满足与否，XIF 返回表达式A 或者表达式B 的值。很快，他发现，用子程序的方法实现 XIF，在语义上并不正确。我们知道，在 Fortran 和其他高级语言中，函数参数的值在进入函数之前必须全部确定。在 XIF 这里，不难看出，不管条件满足与否，我们都先要计算表达式A 和表达式B 的值。而 IF 是个分支逻辑，从语义上来说，应该只计算满足条件的分支的值。因此，用函数来实现 IF 是不正确的 [b]。</p><p style="color: #524222; font-family: 'Microsoft Yahei', Arial; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; width: 900px; "></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; padding-left: 30px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; width: 900px; color: #5f5f5f; font-family: Georgia, 'Times New Roman', Times, 'Hiragino Sans GB', 'Hiragino Kaku Gothic Pro', STXihei, Hei, SimSun, 'WenQuanYi Micro Hei', sans-serif; text-align: justify; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; color: #003366; ">作为一个旁注，尽管 John McCarthy 早在50多年前就发现了函数实现 IF 是语义错误的，现代的程序员还常常犯这个错误。一个值得一题的例子是 C++ 逻辑运算符重载和短路表达式的不等价性。我们都知道，在 C 语言中，逻辑与 (&amp;&amp;) 和逻辑或( || ) 都隶属于短路表达式，也就是说，对于 A &amp;&amp; B 这样的表达式，如果 A 已经确定为 false，就无需计算表达式 B 的值，即 B 的计算被&#8221;短路&#8221;。以 C 为蓝本的 C++ 一方便保留了这些短路表达式，另一方面在面向对象的特性中，引入了运算符重载。具体来说，只要一个对象定义了 operator&amp;&amp; 成员函数，就可以进行 &amp;&amp; 运算。乍一看，这是一个很酷的特性，可以让程序员用 A&amp;&amp;B 这样的数学表达式表达复杂的逻辑关系。然而，仔细想想， &nbsp;A.operator&amp;&amp;(B) 在语义上并不等价于 C 所定义的 A&amp;&amp;B，原因在于 A.operator&amp;&amp;() 是个函数，在求值之前需要先计算 B 的值，而后者是个短路表达式，本质上相当于</span></p><pre style="white-space: pre-wrap; word-wrap: break-word; color: #524222; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; ">    <span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; color: #003366; ">IF A:</span></pre><pre style="white-space: pre-wrap; word-wrap: break-word; color: #524222; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; ">    <span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; color: #003366; "> return True</span></pre><pre style="white-space: pre-wrap; word-wrap: break-word; color: #524222; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; ">    <span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; color: #003366; ">ELSE:</span></pre><pre style="white-space: pre-wrap; word-wrap: break-word; color: #524222; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; ">    <span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; color: #003366; "> return B</span></pre><pre style="white-space: pre-wrap; word-wrap: break-word; color: #524222; line-height: 26px; text-align: left; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: baseline; ">    <span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; font-size: 13px; vertical-align: baseline; color: #003366; font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; ">因为短路表达式不一定会对 B 求值，这两者从语义上就是不等价的。如果 B 不是一个简单的对象，而是一个复杂表达式的时候，对 B 求值可能有副作用，而这个副作用，是写 A &amp;&amp; B 并把它当做短路表达式的程序员所没有预见的。按照 C++ Gotcha 的说法，这很容易造成潜在的程序 Bug。实际上，C++逻辑运算符重载是一个危险的特性，很多公司的编程标准都禁止使用逻辑运算符重载。<br /><br /><span style="color: #524222; font-family: 'Microsoft Yahei', Arial; font-size: 14px; line-height: 26px; ">转自&nbsp;</span><a href="http://blog.youxu.info/" style="color: #220000; text-decoration: none; font-family: 'Microsoft Yahei', Arial; font-size: 14px; line-height: 26px; ">http://blog.youxu.info/</a></span></pre><img src ="http://www.cppblog.com/henry90/aggbug/173905.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/henry90/" target="_blank">寒璿</a> 2012-05-07 15:19 <a href="http://www.cppblog.com/henry90/archive/2012/05/07/173905.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>