<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7472707667787761494</id><updated>2012-02-18T10:24:34.461-08:00</updated><title type='text'>sttony's blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-6058084951006490578</id><published>2012-02-18T10:24:00.001-08:00</published><updated>2012-02-18T10:24:34.481-08:00</updated><title type='text'>使用SQLServer Express：该用户与可信 SQL Server 连接无关联。</title><content type='html'>昨天遇到一个怪问题。&lt;br /&gt;我的本上原来装VS2005时，安装了VS自带的SQLExpres版本,用.net访问时很正常。昨天准备用java程序来访问之，装了一个jdbc，打开TCP/IP支持，创建用户。连接结果出错&lt;br /&gt;&lt;br /&gt;该用户与可信 SQL Server 连接无关联。 (Microsoft SQL Server, Error: 18452)&lt;br /&gt;&lt;br /&gt;尝试了无数遍，包括关闭windows防火墙，打开named pipe，都不好使。发现用SQLExpress的管理器也不能连接，也是该错误。&lt;br /&gt;&lt;br /&gt;折腾了2小时无果，去微软的网站下了SQL server Express Sp2版本。安装过程中发现VS2005原来安装的实例设置的是Windows集成登录，而我创建的帐号是SQL认证登录。改成混合认证，一切正常了。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-6058084951006490578?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/6058084951006490578/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/sqlserver-express-sql-server.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/6058084951006490578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/6058084951006490578'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/sqlserver-express-sql-server.html' title='使用SQLServer Express：该用户与可信 SQL Server 连接无关联。'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-7799501362358209130</id><published>2012-02-18T10:23:00.001-08:00</published><updated>2012-02-18T10:23:02.870-08:00</updated><title type='text'>吃椰子</title><content type='html'>&lt;a href="http://1.bp.blogspot.com/_Dhc_J360IPo/SL4PbBbciQI/AAAAAAAAAGU/UWQJh4HdtrI/s1600-h/20080828.jpg"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5241643973220272386" src="http://1.bp.blogspot.com/_Dhc_J360IPo/SL4PbBbciQI/AAAAAAAAAGU/UWQJh4HdtrI/s400/20080828.jpg" style="cursor: pointer; display: block; margin: 0px auto 10px; text-align: center;" /&gt;&lt;/a&gt;&lt;br /&gt;回家途中看见买椰子的，不禁食指大动，买了一个回家。&lt;br /&gt;买的人告诉我主要是喝水，还给了我两个吸管。回家切了半天才发现，弄开椰子是很麻烦的事情。&lt;br /&gt;&lt;br /&gt;动用菜刀把外面的纤维都拔掉之后也没看那3个孔，最后只好动用锤子钻子钉子在上面打两个孔。&lt;br /&gt;&lt;div id="blogContainer" style="font-size: 12px;"&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;/div&gt;&lt;a href="http://3.bp.blogspot.com/_Dhc_J360IPo/SL4Pmd-BwXI/AAAAAAAAAGc/NS8BS-KyYDs/s1600-h/20080828%28001%29.jpg"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5241644169860071794" src="http://3.bp.blogspot.com/_Dhc_J360IPo/SL4Pmd-BwXI/AAAAAAAAAGc/NS8BS-KyYDs/s400/20080828%28001%29.jpg" style="cursor: pointer; display: block; margin: 0px auto 10px; text-align: center;" /&gt;&lt;/a&gt;一片狼藉啊。&lt;br /&gt;&lt;br /&gt;&lt;div id="blogContainer" style="font-size: 12px;"&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-7799501362358209130?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/7799501362358209130/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/blog-post_9382.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/7799501362358209130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/7799501362358209130'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/blog-post_9382.html' title='吃椰子'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_Dhc_J360IPo/SL4PbBbciQI/AAAAAAAAAGU/UWQJh4HdtrI/s72-c/20080828.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-5239381315559896221</id><published>2012-02-18T10:22:00.001-08:00</published><updated>2012-02-18T10:22:01.509-08:00</updated><title type='text'>非典型性C语言教程-1.1 变量</title><content type='html'>C语言最本质的东西就是函数和变量。 函数和变量在编译完成后会有实际的数据在那里，也就是运行时载入内存的时候会占用内存。现在先说变量。&lt;br /&gt;&lt;br /&gt;变量按其存储在内存中的位置分有3种， 全局/静态的， 局部/栈（stack）的，和堆(heap)变量。这3个概念其实牵扯到OS对于进程内存的管理方式。&lt;br /&gt;&lt;br /&gt;现代的OS对于一个进程一般采用线性的内存，即对于32位系统而言一个进程的地址空间一般是从0x00000000开始一直到0xFFFFFFFF，很早在8086机器上引入的分段模式已经不在使用了，数据和代码都放在一起。代码就对应于C语言的函数，全局静态的数据对应与全局/静态变量。除此之外OS载入进程后还会动态的生成两种内存结构：一种是栈stack，一种是堆heap。由于有时stack的中文翻译也写成 堆栈，所以后面一律使用stack和heap来描述两者。Stack用于函数调用和返回，以及局部变量，heap对应与用malloc函数分配的内存空间。&lt;br /&gt;&lt;br /&gt;全局变量编译完成后在可执行文件中占用一个段，一般称为.data段。进程载入的时候，全局变量也跟着载入内存，在内存中占用固定的地址。所有使用全局变量的地方最后都变成对固定内存地址的引用。堆变量一般由指针应用，由malloc分配。这种变量一旦分配也对应与内存中的固定地址，但是要记得分配了就要释放，否则就是著名的内存泄漏错误(memory leak)。如果你的程序在结束时不会因为消耗过多的内存而引发系统响应变慢这样的问题，那么不释放也没有关系，程序结束时，malloc分配的内存会由OS释放掉。&lt;br /&gt;&lt;br /&gt;稍微麻烦一点的是局部变量。局部变量是在函数内部定义的，函数被调用的时候会移动栈顶，形成函数这次执行需要的active frame。下面都以x86机器为例。如图在x86上sp寄存器指向栈顶&lt;br /&gt;&lt;a href="http://bp2.blogger.com/_Dhc_J360IPo/RlubxxZ6tGI/AAAAAAAAAA4/ZA8FjCCXy0o/s1600-h/stack.JPG"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5069817084913562722" src="http://bp2.blogger.com/_Dhc_J360IPo/RlubxxZ6tGI/AAAAAAAAAA4/ZA8FjCCXy0o/s320/stack.JPG" style="cursor: pointer; float: left; margin: 0pt 10px 10px 0pt;" /&gt;&lt;/a&gt;bp一般用于引用栈的内部。一个函数调用一般是这样：首先把函数的参数压入堆栈，然后调用call，call指令会自动压入返回地址。call之后就转到函数的代码了，函数的头几条指令一般都是移动Sp和BP在栈中开辟一块内存放函数需要的局部变量。然后后面对局部变量的引用都被编译成相对bp的地址，[bp+10]这样的地址。这样处理局部变量的目的就是为了让函数可以重入。在单线程下，不可能有同时运行的代码调用同一个函数，所以重入可以等价与递归，函数自己调用自己。&lt;br /&gt;&lt;br /&gt;最早出现的高级语言Forturn是不支持递归的，当时Forturn对于局部变量的处理和全局变量一样，如果函数自己调用自己，就不能分清楚引用的局部变量到底是哪一个。后来改成了stack的形式。举个例子：&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int ff(int n)&lt;br /&gt;{&lt;br /&gt; int ret=1;&lt;br /&gt; if(n==0 || n==1)&lt;br /&gt;    ret=1;&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;     ret=ff(n-1)*n;&lt;br /&gt; }&lt;br /&gt; return ret;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;这是一个简单的计算阶乘的递归实现的例子。现在假设局部变量ret有固定的地址，那么递归层次中下一层的调用会修改ret的值，使得调用它的函数得不到正确的ret值。我们实际看一下VC8下这段程序产生的代码。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: #3333ff;"&gt;int ff(int n)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #3333ff;"&gt;{&lt;/span&gt;&lt;br /&gt;00411390  push        ebp &lt;br /&gt;00411391  mov         ebp,esp&lt;br /&gt;00411393  sub         esp,0CCh&lt;br /&gt;00411399  push        ebx &lt;br /&gt;0041139A  push        esi &lt;br /&gt;0041139B  push        edi &lt;br /&gt;0041139C  lea         edi,[ebp-0CCh]&lt;br /&gt;004113A2  mov         ecx,33h&lt;br /&gt;004113A7  mov         eax,0CCCCCCCCh&lt;br /&gt;004113AC  rep stos    dword ptr es:[edi]&lt;br /&gt;   &lt;span style="color: #3333ff;"&gt;int ret=1;&lt;/span&gt;&lt;br /&gt;004113AE  mov         dword ptr [ret],1&lt;br /&gt;   &lt;span style="color: #3333ff;"&gt;if(n==0 || n==1)&lt;/span&gt;&lt;br /&gt;004113B5  cmp         dword ptr [n],0&lt;br /&gt;004113B9  je          ff+31h (4113C1h)&lt;br /&gt;004113BB  cmp         dword ptr [n],1&lt;br /&gt;004113BF  jne         ff+3Ah (4113CAh)&lt;br /&gt;      &lt;span style="color: #3333ff;"&gt;ret=1;&lt;/span&gt;&lt;br /&gt;004113C1  mov         dword ptr [ret],1&lt;br /&gt;   &lt;span style="color: #3333ff;"&gt;else&lt;/span&gt;&lt;br /&gt;004113C8  jmp         ff+50h (4113E0h)&lt;br /&gt;   &lt;span style="color: #3333ff;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #3333ff;"&gt;       ret=ff(n-1)*n;&lt;/span&gt;&lt;br /&gt;004113CA  mov         eax,dword ptr [n]&lt;br /&gt;004113CD  sub         eax,1&lt;br /&gt;004113D0  push        eax &lt;br /&gt;004113D1  call        ff (411145h)&lt;br /&gt;004113D6  add         esp,4&lt;br /&gt;004113D9  imul        eax,dword ptr [n]&lt;br /&gt;004113DD  mov         dword ptr [ret],eax&lt;br /&gt;   &lt;span style="color: #3333ff;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #3333ff;"&gt;    return ret;&lt;/span&gt;&lt;br /&gt;004113E0  mov         eax,dword ptr [ret]&lt;br /&gt;&lt;span style="color: #3333ff;"&gt;}&lt;/span&gt;&lt;br /&gt;004113E3  pop         edi &lt;br /&gt;004113E4  pop         esi &lt;br /&gt;004113E5  pop         ebx &lt;br /&gt;004113E6  add         esp,0CCh&lt;br /&gt;004113EC  cmp         ebp,esp&lt;br /&gt;004113EE  call        @ILT+300(__RTC_CheckEsp) (411131h)&lt;br /&gt;004113F3  mov         esp,ebp&lt;br /&gt;004113F5  pop         ebp &lt;br /&gt;004113F6  ret             &lt;/pre&gt;也许你不知道如何在VC8下显示反汇编，后面会专门讨论VC8。VC8的反汇编代码已经做了优化，比如局部变量ret的地址表示成了[ret]（004113AE）实际上它应该是类似与[bp+xx]这样的地址。其次VC8的调试版本里面所有的没有初始化的变量都用0xcc来填充，而不是0x00。 我个人猜想之所有用0xcc来填充是因为0xcc在x86机器上恰好是int 3h指令的机器码，而int 3h指令就是调试中断的指令。可能你不懂汇编，这里只简单的说说。函数调用的开始几行汇编代码都类似，就是完成了建立局部变量空间，也就是active frame的过程，主要操作的是sp和bp寄存器。看一看算ff(2)时的系统内存：&lt;br /&gt;0x0012FBC7  cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc 01 00 00 00 f3 13 41 00 c8 fc 12 00 d6 13 41 00 01 00 00 00 &lt;br /&gt;0x0012FBF0  ac fd 12 00 9c f9 84 07 00 e0 fd 7f cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc&lt;br /&gt;此时ESP寄存器是0x0012FB9E， 表示栈顶， 栈的第一个元素是01 00 00 00， 即ret=1，后面的一个32位数是00 d6 13 41 即0x4113d600，这个是返回地址。后一个01 00 00 00表示的是函数的参数。调试的时候VC8在栈中插入了大量的cc， 这个是为了VC8的-GS选项，即栈检查，防止缓冲区溢出错误。&lt;br /&gt;&lt;br /&gt;可以看到函数返回的时候有退栈的动作（004113E6  add         esp,0CCh ），就是释放了局部变量所占用的栈空间，于是局部变量的生存就结束了。&lt;br /&gt;&lt;br /&gt;写程序的时候使用那种变量要了解这种变量的特性，和生存周期。比如返回局部变量的地址就是一种典型的错误，局部变量占用的内存，在函数结束之后就还给系统了，返回局部变量的地址在函数完成之后使用，属于未定义的行为。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-5239381315559896221?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/5239381315559896221/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/c-11.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/5239381315559896221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/5239381315559896221'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/c-11.html' title='非典型性C语言教程-1.1 变量'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_Dhc_J360IPo/RlubxxZ6tGI/AAAAAAAAAA4/ZA8FjCCXy0o/s72-c/stack.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-2706947257540534086</id><published>2012-02-18T10:18:00.000-08:00</published><updated>2012-02-18T10:20:30.922-08:00</updated><title type='text'>最近开始学习图像识别，第一步FFT</title><content type='html'>代码根据csdn论坛上一位达人的C++代码改编： &lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;public class FFT {&lt;br /&gt;&lt;br /&gt; /** Creates a new instance of FFT */&lt;br /&gt; public FFT(int _ex) {&lt;br /&gt;&lt;br /&gt;  ex = _ex;&lt;br /&gt;  N = (int) Math.pow(2, ex);&lt;br /&gt;  omegaRe = new double[N];&lt;br /&gt;  omegaIm = new double[N];&lt;br /&gt;  for (int k = 0; k &amp;amp;lt; N; k++) {&lt;br /&gt;   omegaRe[k] = Math.cos(2 * Math.PI / N * k);&lt;br /&gt;   omegaIm[k] = Math.sin(-2 * Math.PI / N * k);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; double omegaRe[];&lt;br /&gt; double omegaIm[];&lt;br /&gt; int ex;&lt;br /&gt; int N;&lt;br /&gt;&lt;br /&gt; public int rev(int x) {&lt;br /&gt;  int in = x;&lt;br /&gt;  int ret = 0;&lt;br /&gt;  for (int i = 0; i &amp;amp;lt; ex; i++) {&lt;br /&gt;   ret = ret | (in % 2 &amp;amp;lt;&amp;amp;lt; ex - i - 1);&lt;br /&gt;   in = in &amp;amp;gt;&amp;amp;gt; 1;&lt;br /&gt;  }&lt;br /&gt;  return ret;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void fft(double[] inputRe, double[] inputIm, double[] outputRe,&lt;br /&gt;   double[] outputIm) {&lt;br /&gt;&lt;br /&gt;  assert (inputRe.length &amp;amp;gt;= N);&lt;br /&gt;  assert (inputRe.length == inputIm.length);&lt;br /&gt;  assert (outputRe.length == outputIm.length);&lt;br /&gt;  assert (inputRe.length == outputRe.length);&lt;br /&gt;&lt;br /&gt;  int k; // 当前树的深度&lt;br /&gt;  int j;&lt;br /&gt;&lt;br /&gt;  int nBtFlyLen = 0;&lt;br /&gt;&lt;br /&gt;  if (inputIm == null) {&lt;br /&gt;   inputIm = new double[inputRe.length];&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // 变换需要的工作空间&lt;br /&gt;  double[] work1Re = new double[N];&lt;br /&gt;  double[] work1Im = new double[N];&lt;br /&gt;  double[] work2Re = new double[N];&lt;br /&gt;  double[] work2Im = new double[N];&lt;br /&gt;&lt;br /&gt;  // 临时变量&lt;br /&gt;  double[] tmpRe;&lt;br /&gt;  double[] tmpIm;&lt;br /&gt;  // 初始化，写入数据&lt;br /&gt;  System.arraycopy(inputRe, 0, work1Re, 0, N);&lt;br /&gt;  System.arraycopy(inputIm, 0, work1Im, 0, N);&lt;br /&gt;  // 临时变量&lt;br /&gt;  int nInter = 0;&lt;br /&gt;&lt;br /&gt;  // 蝶形算法进行快速傅立叶变换&lt;br /&gt;  for (k = 0; k &amp;amp;lt; ex; k++) {&lt;br /&gt;   for (j = 0; j &amp;amp;lt; (1 &amp;amp;lt;&amp;amp;lt; k); j++) {&lt;br /&gt;    // 计算长度&lt;br /&gt;    nBtFlyLen = 1 &amp;amp;lt;&amp;amp;lt; (ex - k);&lt;br /&gt;    // 倒序重排，加权计算&lt;br /&gt;    for (int i = 0; i &amp;amp;lt; nBtFlyLen / 2; i++) {&lt;br /&gt;     nInter = j * nBtFlyLen;&lt;br /&gt;     work2Re[i + nInter] = work1Re[i + nInter]&lt;br /&gt;       + work1Re[i + nInter + nBtFlyLen / 2];&lt;br /&gt;     work2Im[i + nInter] = work1Im[i + nInter]&lt;br /&gt;       + work1Im[i + nInter + nBtFlyLen / 2];&lt;br /&gt;&lt;br /&gt;     double a = work1Re[i + nInter]&lt;br /&gt;       - work1Re[i + nInter + nBtFlyLen / 2];&lt;br /&gt;     double b = work1Im[i + nInter]&lt;br /&gt;       - work1Im[i + nInter + nBtFlyLen / 2];&lt;br /&gt;     double c = omegaRe[i * (1 &amp;amp;lt;&amp;amp;lt; k)];&lt;br /&gt;     double d = omegaIm[i * (1 &amp;amp;lt;&amp;amp;lt; k)];&lt;br /&gt;     work2Re[i + nInter + nBtFlyLen / 2] = a * c - b * d;&lt;br /&gt;     work2Im[i + nInter + nBtFlyLen / 2] = a * d + b * c;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   // 交换 work1和work2的数据&lt;br /&gt;   tmpRe = work1Re;&lt;br /&gt;   tmpIm = work1Im;&lt;br /&gt;   work1Re = work2Re;&lt;br /&gt;   work1Im = work2Im;&lt;br /&gt;   work2Re = tmpRe;&lt;br /&gt;   work2Im = tmpIm;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // 重新排序&lt;br /&gt;  for (j = 0; j &amp;amp;lt; N; j++) {&lt;br /&gt;   nInter = 0;&lt;br /&gt;   for (int i = 0; i &amp;amp;lt; ex; i++) {&lt;br /&gt;    if ((j &amp;amp;amp; (1 &amp;amp;lt;&amp;amp;lt; i)) != 0) {&lt;br /&gt;     nInter += 1 &amp;amp;lt;&amp;amp;lt; (ex - i - 1);&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   outputRe[j] = work1Re[nInter];&lt;br /&gt;   outputIm[j] = work1Im[nInter];&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void ifft(double[] inputRe, double[] inputIm, double[] outputRe,&lt;br /&gt;   double[] outputIm) {&lt;br /&gt;&lt;br /&gt;  assert (inputRe.length &amp;amp;gt;= N);&lt;br /&gt;  assert (inputRe.length == inputIm.length);&lt;br /&gt;  assert (outputRe.length == outputIm.length);&lt;br /&gt;  assert (inputRe.length == outputRe.length);&lt;br /&gt;&lt;br /&gt;  double[] transformRe = new double[N];&lt;br /&gt;  double[] transformIm = new double[N];&lt;br /&gt;&lt;br /&gt;  for (int i = 0; i &amp;amp;lt; N; i++) {&lt;br /&gt;   transformRe[i] = inputRe[i];&lt;br /&gt;   transformIm[i] = -inputIm[i];&lt;br /&gt;  }&lt;br /&gt;  fft(transformRe, transformIm, outputRe, outputIm);&lt;br /&gt;  for (int i = 0; i &amp;amp;lt; N; i++) {&lt;br /&gt;   outputRe[i] = outputRe[i] / N;&lt;br /&gt;   outputIm[i] = -outputIm[i] / N;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void fft_2d(double[][] inputRe, double[][] inputIm,&lt;br /&gt;   double[][] outputRe, double[][] outputIm) {&lt;br /&gt;&lt;br /&gt;  // 检查不强， 没有循环检查二维数组的第二维&lt;br /&gt;  assert (inputRe.length &amp;amp;gt;= N);&lt;br /&gt;  assert (inputRe.length == inputIm.length);&lt;br /&gt;  assert (outputRe.length == outputIm.length);&lt;br /&gt;  assert (inputRe.length == outputRe.length);&lt;br /&gt;&lt;br /&gt;  if (inputIm == null)&lt;br /&gt;   inputIm = new double[N][N];&lt;br /&gt;&lt;br /&gt;  for (int i = 0; i &amp;amp;lt; N; i++) {&lt;br /&gt;   fft(inputRe[i], inputIm[i], outputRe[i], outputIm[i]);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // 重新为in分配一块空间&lt;br /&gt;  double[][] inRe = new double[N][N];&lt;br /&gt;  double[][] inIm = new double[N][N];&lt;br /&gt;&lt;br /&gt;  // 转置&lt;br /&gt;  for (int i = 0; i &amp;amp;lt; N; i++) {&lt;br /&gt;   for (int j = 0; j &amp;amp;lt; N; j++) {&lt;br /&gt;    inRe[i][j] = outputRe[j][i];&lt;br /&gt;    inIm[i][j] = outputIm[j][i];&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  for (int i = 0; i &amp;amp;lt; N; i++) {&lt;br /&gt;   fft(inRe[i], inIm[i], outputRe[i], outputIm[i]);&lt;br /&gt;  }&lt;br /&gt;  for (int i = 0; i &amp;amp;lt; N; i++) {&lt;br /&gt;   for (int j = 0; j &amp;amp;lt; N; j++) {&lt;br /&gt;    inRe[i][j] = outputRe[j][i];&lt;br /&gt;    inIm[i][j] = outputIm[j][i];&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  for (int i = 0; i &amp;amp;lt; N; i++) {&lt;br /&gt;   System.arraycopy(inRe[i], 0, outputRe[i], 0, N);&lt;br /&gt;   System.arraycopy(inIm[i], 0, outputIm[i], 0, N);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void ifft_2d(double[][] inputRe, double[][] inputIm,&lt;br /&gt;   double[][] outputRe, double[][] outputIm) {&lt;br /&gt;&lt;br /&gt;  double[][] workRe = new double[N][N];&lt;br /&gt;  double[][] workIm = new double[N][N];&lt;br /&gt;&lt;br /&gt;  for (int i = 0; i &amp;amp;lt; N; i++) {&lt;br /&gt;   for (int j = 0; j &amp;amp;lt; N; j++) {&lt;br /&gt;    workRe[i][j] = inputRe[i][j];&lt;br /&gt;    workIm[i][j] = -inputIm[i][j];&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  fft_2d(workRe, workIm, outputRe, outputIm);&lt;br /&gt;  for (int i = 0; i &amp;amp;lt; N; i++) {&lt;br /&gt;   for (int j = 0; j &amp;amp;lt; N; j++) {&lt;br /&gt;    outputRe[i][j] = outputRe[i][j] / (N * N);&lt;br /&gt;    outputIm[i][j] = -outputIm[i][j] / (N * N);&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;创建FFT对象的时候指定层数ex，也就是点数N= pow(2,ex); 构造函数中会计算omega（0到N-1)节约时间。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-2706947257540534086?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/2706947257540534086/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/fft.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/2706947257540534086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/2706947257540534086'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/fft.html' title='最近开始学习图像识别，第一步FFT'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-3753002120197665018</id><published>2012-02-18T10:10:00.000-08:00</published><updated>2012-02-18T10:10:08.223-08:00</updated><title type='text'>非典型性C语言教程-1.0 翻译单元，标识符，内部连接，外部连接</title><content type='html'>前面讲了很多编译C语言文件的问题，现在开始讲C语言本身了。&lt;br /&gt;&lt;br /&gt;第一个概念就是翻译单元(translate unit）。一个源文件就是一个翻译单元。前面说过#include指令只是将文件的内容插入到#include指令的位置，比如这样的代码也是可以的：&lt;br /&gt;#include "mydoc.txt"或者#include "mycsource.c"但是这样写出的代码有点怪异，所以这里我们按照一般的概念，编译源文件（.c文件），#include头文件(.h文件）。确切的说，一个翻译单元就是一个源文件和它include的头文件。一个翻译单元编译成一个目标文件，最后将多个翻译单元连接起来生成一个完整的可执行程序。&lt;br /&gt;&lt;br /&gt;第二个概念是标识符（identifier）。标识符包括，变量的名字，函数的名字，结构的名字，联合的名字，typedef的名字，枚举中的名字，#define定义的宏也是标识符。和翻译单元的概念结合起来，标识符有两类，一类是internal linkage 一类是external linkage。&lt;br /&gt;&lt;br /&gt;什么是内部连接（internal linkage ）呢？就是编译成目标文件之后就不存在了，翻译单元的外面看不到内部连接。比如，一个局部变量，局部变量的可见性仅持续到函数返回。在比如一个结构的名字，多个翻译单元中可以有同名的结构。&lt;br /&gt;&lt;br /&gt;外部连接（external linkage）则是编译成目标文件之后仍然存在的符号。比如一个全局变量的名字，比如一个普通函数的名字。多个翻译单元中不能有同名的函数或是全局变量，否则连接的时候会报符号重名错误。&lt;br /&gt;&lt;br /&gt;0.4中说了，目标文件会有一个符号表，内部连接和外部连接的本质区别就是：内部连接不在目标文件的符号表中，而外部连接在目标文件的符号表中。内部连接包含：局部变量，结构名字，枚举名字，联合的名字，以及静态全局变量和静态函数。可能对不了解，后面会详细讲静态全局变量和静态函数。外部连接主要是全局变量和函数。&lt;br /&gt;&lt;br /&gt;给个例子，有一个程序由2个.c文件组成，看看那些会引起符号冲突那些不会。&lt;br /&gt;&lt;pre class="brush:c"&gt;// a.c&lt;br /&gt;int dd(int)&lt;br /&gt;{  &lt;br /&gt;    return 20;&lt;br /&gt;}&lt;br /&gt;int g_A=0;  &lt;br /&gt;static g_A1=10;&lt;br /&gt;struct ax  &lt;br /&gt;{&lt;br /&gt;    int a;  &lt;br /&gt;};&lt;br /&gt;  &lt;br /&gt;int main( void )&lt;br /&gt;{&lt;br /&gt;    dd(1);  &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//b.c&lt;br /&gt;static int dd(int)  &lt;br /&gt;{&lt;br /&gt;    return 20;  &lt;br /&gt;}&lt;br /&gt;int g_A=0;  &lt;br /&gt;static g_A1=10;  &lt;br /&gt;&lt;br /&gt;struct ax&lt;br /&gt;{&lt;br /&gt;    int a;  &lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;带static的函数和全局变量都是不会冲突的，但是去掉了，就肯定冲突，struct  ax不会冲突，不带static的g_A会冲突。&lt;br /&gt;&lt;br /&gt;头文件中最好只放有内部连接的东西，因为一个头文件可能被多个翻译单元所包含引用，如果在头文件中放个有外部连接的东西，很容易就在最后连接的时候出错。&lt;br /&gt;&lt;br /&gt;带external的 标识符是内部连接，比如，在第二个文件中的int g_A改成， external int g_A就没问题了。external是告诉编译器，我要使用在别的翻译单元中的东西，编译器就会留个占位符在那里，到连接的时候再解决这个符号。不使用就不会有占位符，但是如果你使用了，但是最后连接的时候却没有这个实际的变量，那么编译器就会报错，unresolved符号。&lt;br /&gt;&lt;br /&gt;函数的声明和external 类似。你可以写 int dd(int); 告诉编译器，在别的翻译单元中有这么一个函数，我将使用它，然后你就可以调用dd了只要符合int dd(int)就可以。同理，如果连接的时候找不到这个函数，编译器也会报告未解决的符号。&lt;br /&gt;&lt;br /&gt;一个典型的错误是为了写一个共用的函数，在.h文件中写一个函数体。然后在要使用这个函数的地方#include这个头文件。于是在多个翻译单元中都有了这个函数，连接的时候报告重定义。正确的做法是讲函数的实际代码放在一个源文件中，讲函数的声明放在头文件里面。需要使用函数的地方#include  头文件，最后连接的时候把包含实际代码的源文件编译连接上。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-3753002120197665018?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/3753002120197665018/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/c-10.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/3753002120197665018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/3753002120197665018'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/c-10.html' title='非典型性C语言教程-1.0 翻译单元，标识符，内部连接，外部连接'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-1289973453448553814</id><published>2012-02-18T10:05:00.001-08:00</published><updated>2012-02-18T10:05:02.985-08:00</updated><title type='text'>非典型性C语言教程- 0.4 连接</title><content type='html'>0.2 里面说过，当你使用gcc -o hello hello.c 时，gcc实际是先调用cpp预处理hello.c中的预处理命令，再自己编译之，最后调用ld进行连接生成可执行文件。Windows下是cl.exe 和link.exe。&lt;br /&gt;&lt;br /&gt;用-c选项可以让编译器不连接，如 gcc -c hello.c，或是cl -c hello.c 这样会只将源文件编译成目标文件。Unix下叫hello.o，Windows下叫hello.obj。目标文件是不能执行的，但是目标文件中已经是可以执行的机器指令了。其实目标文件和最后生成的可执行文件一样，都是一组函数（函数就是一段一段的机器指令），两者的区别在于目标文件中对函数的调用都是按名字调用的，而可执行程序中已经是按地址调用了。先举例子，比如hello.c 程序中调用了printf("hello.c");。编译成的目标文件中，会有一个符号表，其中有一个符号叫printf，并且表明他是一个函数。但是由于这个函数实际在标准库中，所以还不知道这个函数的具体细节，只有符号在那里。Hello world例子中，自己写的只有一个源文件，编译之后只需要与C语言的标准库连接就可以。&lt;br /&gt;&lt;br /&gt;C语言的标准库实际就是一组函数。在Windows下你安装了VC或是VS会给你安装上，在%VCHOME%\lib目录下，叫msvcrt.lib。这个lib文件实际使用的是%Windows%\system32下的msvcrt.dll。在Unix下在/usr/lib下，一般叫libc.so或是glibc.so等名字。C语言的标准库基本上是操作系统不可缺少的部分。&lt;br /&gt;&lt;br /&gt;首先生成hello.o或是hello.lib文件， 然后编译器调用ld或是link.exe将目标文件与C语言的标准库连接。连接在一起的时候，就可以决定， 每个函数的地址。比如main函数在0x400008出，prinft在0x400030 出。然后开始resovle符号。发现hello.o中有一个函数叫main，main中有一个对printf函数的调用，而C语言的标准库中的符号表中有一个printf的函数，于是main中对printf的函数调用就转到标准库中printf函数的入口去了，函数调用就被翻译成一条汇编指令比如叫call 0x400030了。最后会给程序加上一段stratup代码，这段代码完成一些初始化工作比如读参数，共享文件表等等，然后调用查找叫main的函数，调用main。连接的过程就完成了。&lt;br /&gt;&lt;br /&gt;当程序大的时候，需要多个源文件。会产生多个目标文件，可能目标文件a调用了目标文件b内的函数，这些最后都是在连接的时候resolve的。还是先举例子，比如有两个文件hello.c和foo.c，那么编译的时候可以写成gcc -o hello hello.c foo.c，但是实际上编译器是这样作的，&lt;br /&gt;&lt;blockquote&gt;gcc -c hello.c&lt;br /&gt;gcc -c foo.c&lt;br /&gt;ld -0 hello hello.o foo.o&lt;/blockquote&gt;上面3行命令的意义应该很清楚。&lt;br /&gt;&lt;br /&gt;下面说说连接时容易产生的问题：&lt;br /&gt;&lt;ol&gt;&lt;li&gt;unresolved symbol：这个问题一般是忘了连接某个库，或是连接某个目标文件造成的。&lt;/li&gt;&lt;li&gt;符号已定义，或是符号冲突：这个问题一般是有函数或变量重名造成的。&lt;/li&gt;&lt;/ol&gt;连接时候产生的错误并不报告是那个文件那一行错了，找起来会很麻烦。一般要用文件搜索找到相应的符号在那里。&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-1289973453448553814?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/1289973453448553814/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/c-04.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/1289973453448553814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/1289973453448553814'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/c-04.html' title='非典型性C语言教程- 0.4 连接'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-1443353713843113856</id><published>2012-02-18T10:03:00.000-08:00</published><updated>2012-02-18T10:03:49.413-08:00</updated><title type='text'>取属性消耗的时间</title><content type='html'>以前是用C/C++的，对于数组循环都是for(int i=0; i&amp;lt;n; i++) ....... 因为c的数组没有任何附加信息就是一个首地址。现在开始用java和c#，一开始喜欢写 for(int i=0; i&amp;lt;ar.Length; i++)... 这样的代码。现在发现取数组长度的属性是有额外消耗的。如下代码&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;DateTime s, e;&lt;br /&gt;s = DateTime.Now;&lt;br /&gt;for (int i = 0; i &amp;amp;lt; ddd.Count; i++)&lt;br /&gt;{&lt;br /&gt;    double x = 2.0*3.0;&lt;br /&gt;}&lt;br /&gt;e = DateTime.Now;&lt;br /&gt;TimeSpan c = e - s;&lt;br /&gt;Console.WriteLine(" time is {0}", c.TotalMilliseconds.ToString());&lt;br /&gt;s = DateTime.Now;&lt;br /&gt;&lt;br /&gt;for (int i = 0; i &amp;amp;lt; length; i++)&lt;br /&gt;{&lt;br /&gt;    double x = 2.0 * 3.0;&lt;br /&gt;}&lt;br /&gt;e = DateTime.Now;&lt;br /&gt;c = e - s;&lt;br /&gt;Console.WriteLine(" time is {0}", c.TotalMilliseconds.ToString());&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;这段代码在我的机器上执行结果如下&lt;br /&gt;time is 62.5&lt;br /&gt;time is 31.25&lt;br /&gt;也就是说取数组长度属性相当于做一次额外的浮点乘法。积累起来这个开销还是很大的。所以应该在循环开始先把长度取出来存到变量中再循环。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-1443353713843113856?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/1443353713843113856/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/blog-post_18.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/1443353713843113856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/1443353713843113856'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/blog-post_18.html' title='取属性消耗的时间'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-2035603819570640737</id><published>2012-02-18T10:00:00.000-08:00</published><updated>2012-02-18T10:00:07.591-08:00</updated><title type='text'>非典型性C语言教程-0.2 预处理</title><content type='html'>当你执行cl -o hello.exe hello.c或者 cc -o hello hello.c时，到底发生了一些什么呢？其实cl或是cc实际上调用了另外两个程序。首先调用预处理程序(&lt;span style="font-size: 85%;"&gt;UNIX下是cpp程序，在Windows下不太清楚)&lt;/span&gt;，预处理源文件。然后自己编译之，最后调用link.exe或是ld程序来完成连接成生可执行代码。这3个操作是靠管道连在一起的。要是不知道什么是管道就姑且认为，是分3步，用临时文件连在一起的。C语言的预处理机制不属于语言的一部分，但是它的作用非常重要。&lt;br /&gt;&lt;br /&gt;在C语言中，以#开头的行都是预处理命令。最常用的预处理命令就是#include，#define。常用的还有#ifdef  #ifndef  #pragma。 记住一点，&lt;span style="font-weight: bold;"&gt;大多数预处理命令基本只是执行一个文本替换的过程&lt;/span&gt;。其他的预处理指令我们以后再讲，这里只讲讲#inclue。&lt;br /&gt;&lt;br /&gt;#include 有两种形式，第一种是#include &amp;amp;lt;stdio.h&amp;amp;gt;, 第二种是#include "my.h"。 这两种形式的区别在于找头文件的默认路径不一样。 对于#include &amp;amp;lt;stdio.h&amp;amp;gt;会去INCLUDE环境变量指定的目录去找stdio.h这个文件。而#include "my.h"会在当前目录去找my.h，这个“当前目录”是指使用这条预处理命令的源文件所造的目录。比如，我有一个文件hello.c在C:\Cpp\目立下，即C:\Cpp\hello.c ，那么编译的时候预处理程序会在C:\Cpp\下找有没有叫my.h的头文件。按照上次讲的如果你写#include "../my.h"就是在C:\下找my.h这个文件。对于第一种情况可以不改INCLUDE环境变量而针对单个源文件来扩展搜寻的目录。 就是在编译的时候使用 -I参数。&lt;br /&gt;&lt;br /&gt;比如我安装了一个附加库，比如MPICH2的mpi实现， MPICH2安装在D:\mpich2下，那么提供的头文件一般是在D:\mpich2\include。如果我要在程序中包含mpi.h，只需要写了#include  。 但是在编译的时候比如加上一个选项  -ID:\mpich2\include。 否则编译的时候编译器就会抱怨无法打开mpi.h。&lt;br /&gt;&lt;br /&gt;当然你也可以写成绝对路径 #include &amp;amp;lt;d:\mpich2\include&amp;amp;gt; 。这样也可以编译通过，但是这样带来的问题是，比如你的同学拷贝你的程序在他的计算机上编译，由于他把mpich2安装在e:\software\mpich2下了，于是编译器又开始抱怨无法打开mpi.h。同理，写#include "my.h"的时候也不要写绝对路径。可能你会说，头文件不和源文件放在一起吗？还需要写相对路径吗？当你的程序由上百上千个文件组成时，可能就需要将源码组成一颗源码树。看看linux内核的源码就明白了。比如你的程序在D:\pro\hello\目录下，你把源文件全放在D:\pro\hello\src下，头文件全放在D:\pro\hello\include下， 那么include一个头文件最好写成 #include "../my.h" 而不要写成#include "D:\pro\hello\include\my.h"。 写成后者将会使的你的源代码树只能放在D:\pro下才能正确编译，而写成前者，即使你的源码拷贝到一台Linux机器上也能正确编译。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 85%;"&gt;（注，如果你细心你就会发现 #include "../my.h"中用的是/，而不是\。这才保证了在windows和unix下都能正确识别）&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;前面讲了很多#include 的用法，#include 到底完成了些什么动作呢？ 你可以用cl -E hello.c 或是gcc -E hello.c 看看。-E选项是告诉编译器在完成了预处理之后就停下来，不进行后面的步骤了。这样你就可以看到预处理到底完成了那些功能。如果看不清楚可以重定向到一个文本文件中，改成cl -E hello.c &amp;amp;gt;hellomid.c  或是 gcc -E hello.c &amp;amp;gt;hellomid.c。这样hellomid.c就是预处理完成之后的结果。&lt;br /&gt;&lt;br /&gt;你会发现预处理对于#include &amp;amp;lt;stdio.h&amp;amp;gt; 只是把stdio.h的内容直接插入到了源文件里面。在里面有一行&lt;br /&gt;&lt;blockquote&gt;int __cdecl printf(        const char * _Format, ...);&lt;/blockquote&gt;这句话保证了你能正确的调用printf("Hellp world!\n");&lt;br /&gt;&lt;br /&gt;等等！ 那printf的代码在那里？难道#include 不是给我们的程序增加了printf子程序的代码吗？答案是printf实际的代码是在后面连接的时候才加入你的代码的。&lt;br /&gt;&lt;br /&gt;#include 还有很多要注意的地方。这牵涉到头文件和源文件的关系，externl linkage和 internl lingage的区别等别的东西。这里只是强调，&lt;span style="font-weight: bold;"&gt;#include 某个头文件仅仅是讲这个头文件原样插入到了写#include 指令的位置。&lt;/span&gt;没有别的其他功能了。&lt;br /&gt;&lt;br /&gt;下一篇讲连接link的问题。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-2035603819570640737?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/2035603819570640737/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/c-02.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/2035603819570640737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/2035603819570640737'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/c-02.html' title='非典型性C语言教程-0.2 预处理'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-4363878049337113134</id><published>2012-02-18T09:59:00.000-08:00</published><updated>2012-02-18T09:59:02.360-08:00</updated><title type='text'>非典型性C语言教程- 0.1.1  文件树</title><content type='html'>最近发现文件树也是一个有人搞不清楚的概念，这里稍微介绍一下。&lt;br /&gt;很久以前Unix的文件系统就是树型结构， MS的则是到了DOS3.0才引入了文件树的概念。什么是文件树呢，大家知道现在一个硬盘上可能存储了上千万个文件，如果这上千万个文件都存储在一起会怎么样呢？可能谁也找不到自己想要的文件了。&lt;br /&gt;&lt;br /&gt;于是我们就将文件以树的形式组织起来，树有根，有非叶子节点，和叶子节点。任何一个文件系统中，非叶子节点就是“目录”或叫“文件夹”， 叶子节点就是文件。在Unix下，只有唯一的文件树，根就是根目录，以&lt;span style="color: red; font-size: 100%;"&gt;/&lt;span style="color: black;"&gt;表示。在Windows下，有盘符的概念，每个盘符有自己的文件树，以&lt;span style="color: red;"&gt;C:\&lt;/span&gt;来表示文件树的根。比如根下有个目录叫etc，etc下有个文件叫hosts。在Unix下，表示为/etc/hosts。在Windows下是C:\etc\hosts。这里Unix和Windows的目录之间的分隔符号不一样，Unix是/，Windows是\。&lt;br /&gt;&lt;br /&gt;一个文件都有一个文件名，比如前面提到的hosts，同时还有一个全路径名字，好像是叫qualified name。一个文件在系统中有一个唯一的全路径名字，这好像是废话，两个文件有同样的全路径名字怎么区别呢？&lt;br /&gt;后来WWW的出现发展了一种URL标准，进一步发展成URI标准。&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;协议名：//主机地址/[路径名]/文件名。&lt;/span&gt;&lt;br /&gt;还是那句话计算机实践的科学，先举个例子。比如你用的Windows系统，E盘下有个文件夹叫Downloads，下面有个Music文件夹，下面有首歌叫"死了都要爱.mp3"。那么表示为URI就是&lt;span style="color: #cc0000;"&gt;file:///E:\Downloads\Music\死了都要爱.mp3&lt;/span&gt;，其中file://表示是本机的文件系统。在Windows中他的全路径名字就是&lt;/span&gt;&lt;/span&gt;&lt;span style="color: red; font-size: 100%;"&gt;&lt;span style="color: black;"&gt;&lt;span style="color: #cc0000;"&gt;E:\Downloads\Music\死了都要爱.mp3&lt;span style="color: black;"&gt;。细心的话，你就会发现file:后面接了3个/，而前面我们已经说了，是两个/。有时候甚至必须写成&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: red; font-size: 100%;"&gt;&lt;span style="color: black;"&gt;&lt;span style="color: #cc0000;"&gt;file:///E:/Downloads/Music/死了都要爱.mp3。&lt;span style="color: black;"&gt;为什么呢？&lt;br /&gt;&lt;br /&gt;因为大多数互联网的标准都是依据Unix定义了。所以file:后面的3个/，前两个是协议的分隔符，后一个表示的根文件系统。 前面说了，Unix只有唯一的文件树，文件数的根就是/。而Unix路径名字中的分隔符是/，而Windows的分隔符是\。所以会出现上面那样的全路径名。这个问题在Windows平台下用Java时经常会带来困惑。&lt;br /&gt;&lt;br /&gt;前面提到的全路径名字都是绝对路径，下面讲相对路径。相对路径基础就是"."和".."。其中.表示当前目录，..表示上级目录。还是先讲例子，比如上面的例子中，在 E:\Downloads\Software\下有一个winamp.exe播放程序，他要播放"死了都要爱.mp3"，他除了可以用&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: red; font-size: 100%;"&gt;&lt;span style="color: black;"&gt;&lt;span style="color: #cc0000;"&gt;&lt;span style="color: black;"&gt;E:\Downloads\Music\死了都要爱.mp3找到这首歌以外，还可以用..\Music\ 死了都要死.mp3来找到这个文件。因为winamp.exe所在的目录是E:\Downloads\Software所以，&lt;span style="font-weight: bold;"&gt;相对&lt;/span&gt;它来说..就是E:\Downloads。用&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: red; font-size: 100%;"&gt;&lt;span style="color: black;"&gt;&lt;span style="color: #cc0000;"&gt;&lt;span style="color: black;"&gt;E:\Downloads替换掉..就和上面的全路径名字一样了。相对winamp.exe来说，.就表示&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: red; font-size: 100%;"&gt;&lt;span style="color: black;"&gt;&lt;span style="color: #cc0000;"&gt;&lt;span style="color: black;"&gt;E:\Downloads\Software。&lt;br /&gt;&lt;br /&gt;相对路径在URL或是URI中也是可用的，用法一样。我们写网页的超级链接最好都写成相对链接，这样可以随意替换目录，也不会发生错误。因为相对路径一般是不变的。&lt;br /&gt;&lt;br /&gt;前面讲了文件树的一些概念，下面讲一些常常需要注意的问题。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;执行可执行文件的错误： 一个可执行文件必须告诉操作系统它的完整名字，操作系统才能执行它。比如前面说的E:\Downloads\Software\winamp.exe，如果要执行它，要么写全路径名字，要么写相对路径名字。尤其是在Unix系统下，系统不会默认在当前目录下找这个文件，所以及时当前目录是&lt;/span&gt;&lt;span style="color: red; font-size: 100%;"&gt;&lt;span style="color: black;"&gt;&lt;span style="color: #cc0000;"&gt;&lt;span style="color: black;"&gt;E:\Downloads\Software也必须用完整的相对路径名字./winamp, 用惯了Windows的人一开始会很不习惯。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color: red; font-size: 100%;"&gt;&lt;span style="color: black;"&gt;&lt;span style="color: #cc0000;"&gt;&lt;span style="color: black;"&gt;转义字符的问题。C语言中\是转义字符前缀。要相在字符串中写\必须写成\\。比如代码佛fopen("..\\Music\\死了都要爱.mp3");。&lt;span style="font-weight: bold;"&gt;但是注意&lt;/span&gt;，这仅仅是要写字符串时这么写。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color: red; font-size: 100%;"&gt;&lt;span style="color: black;"&gt;&lt;span style="color: #cc0000;"&gt;&lt;span style="color: black;"&gt;Unix的路径名字区分大小写，而Windows的不区分。比如上面说的&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: red; font-size: 100%;"&gt;&lt;span style="color: black;"&gt;&lt;span style="color: #cc0000;"&gt;&lt;span style="color: black;"&gt;E:\Downloads\Software, 写成e:\dOWnLoDs\sOftWare也是可以的。但在Unix下一个路径/Downdloads和/downloads是不同的路径。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size: 100%;"&gt;&lt;br /&gt;最后稍微介绍一下URI。前面我们提过了 file协议，还有许多我们熟悉的http://www.google.com ；ftp://gnu.org 等等，还有很多网上的流媒体的协议头。有兴趣的参看&lt;a href="http://www.faqs.org/rfcs/rfc2396.html"&gt;RFC2396&lt;/a&gt;.&lt;/span&gt;&lt;span style="color: red; font-size: 100%;"&gt;&lt;span style="color: black;"&gt;&lt;span style="color: #cc0000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-4363878049337113134?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/4363878049337113134/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/c-011.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/4363878049337113134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/4363878049337113134'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/c-011.html' title='非典型性C语言教程- 0.1.1  文件树'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-3481980497212241317</id><published>2012-02-07T22:08:00.000-08:00</published><updated>2012-02-07T22:08:55.825-08:00</updated><title type='text'>python学习笔记3-方便的网络协议库</title><content type='html'>要求在Application中显示天气信息。于是上网搜索一番，发现了google方便的API。只要请求http://www.google.com/ig/api?weather=Beijing,China会得到一个xml文件。可以在浏览器中尝试一下看看。得到之后如何处理就简单了。用python实现的话及其简单：&lt;br /&gt;&lt;pre class="brush: python"&gt;import httplib&lt;br /&gt;from xml.dom import minidom&lt;br /&gt;conn = httplib.HTTPConnection("www.google.com")&lt;br /&gt;conn.request("GET", "/ig/api?weather=Beijing,China")&lt;br /&gt;r= conn.getresponse()&lt;br /&gt;if r.status != 200:&lt;br /&gt;    print("failed to connect network")&lt;br /&gt;    exit()&lt;br /&gt;data= r.read()&lt;br /&gt;r.close()&lt;br /&gt;conn.close()&lt;br /&gt;xmldoc = minidom.parseString(data)&lt;br /&gt;&lt;/pre&gt;得到的xmldoc再解析，就可以了。当然用Web app的话可以直接用http://www.weather.com.cn/static/html/weather_cj.shtml提供的iframe 代码。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-3481980497212241317?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/3481980497212241317/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/python3.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/3481980497212241317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/3481980497212241317'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/python3.html' title='python学习笔记3-方便的网络协议库'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-6752693848345413901</id><published>2012-02-07T22:06:00.001-08:00</published><updated>2012-02-07T22:09:20.389-08:00</updated><title type='text'>Python 学习笔记（2） 强大的动态创建</title><content type='html'>OO编程中有时会遇到这样的问题。&lt;br /&gt;我们有很对象数，水果和子类苹果，梨，香蕉....，然后我们需要根据配置文件或者输入来决定到底创建哪一个子类。&lt;br /&gt;&lt;br /&gt;对于C++，不得不写成&lt;br /&gt;&lt;pre class="brush:c"&gt;switch(type){&lt;br /&gt;    case "Apple":&lt;br /&gt;      new Apple();&lt;br /&gt;      break;    &lt;br /&gt;    case "Pear":&lt;br /&gt;      new Pear();&lt;br /&gt;      break;&lt;br /&gt;    default:&lt;br /&gt;      new fruit();&lt;br /&gt;      break;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;或者动用创建型设计模式使得代买美观一点，消除掉这个 switch case。对于Java. dotNet可以用反射。对于Python，则可以用 exec语句。&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:c"&gt;exec(" fur =%s()"%type)&lt;br /&gt;&lt;/pre&gt;对于javascript则可以使用eval()函数。&lt;br /&gt;动态语言确实很强大，不过要注意的是避免用户用特定的输入拼凑出一个可怕的语句。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-6752693848345413901?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/6752693848345413901/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/oo.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/6752693848345413901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/6752693848345413901'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/oo.html' title='Python 学习笔记（2） 强大的动态创建'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-1086002594112372888</id><published>2012-02-07T22:04:00.001-08:00</published><updated>2012-02-07T22:04:37.126-08:00</updated><title type='text'>研究生课程教了些什么</title><content type='html'>一转眼已经7月了，研究生第一年的学习已经快结束了。现在都是快餐式教育，研究生第一年基本就学完了所有的学分课程。两个学期我一共学了14门课，对其中大多数课感到失望。下面对所有的课程评论一番，毕竟我交了不低的学费。&lt;br /&gt;&lt;br /&gt;一门课的评分0-10分。0分表示这门课什么也没讲，6分表示课程让人学到了基本的概念，10分表示课程很完美。&lt;br /&gt;&lt;br /&gt;第一门必修课是《算法分析与设计》。老师是一个很认真负责的老先生，用的课本是E文的《计算机算法》。这门课个人评价7分。老师要求我们把3-10章所有的习题至少做60%，这个数量是很多的，而且有好多编程题目，结果就是互相抄袭，而且编程题目多半没有具体的实现。老师讲了3-10章的大部分内容，包括以前没有涉及的很多算法的证明，以及很多算法的时间空间复杂的分析。但是，忽略了算法的设计方法（分而治之，贪婪，动态规划，状态空间搜索），忽略了算法证明的基本思想，忽略了算法的分类（NP，P），甚至没有讲解O的数学定义，没有提和O一起的Omga, Xita记号。所以只能的7分。&lt;br /&gt;&lt;br /&gt;第二门必修课是《分布式数据库》。老师是很认真的老太太，用的课本是一本老书。这门课的评价是6。课上讲了分布式数据库的基本概念——分段，而且讲了分段的数学基础，但是缺乏实践的内容，不过现实中分布的数据库也基本全是概念产品。&lt;br /&gt;&lt;br /&gt;第三门必修课是《高级操作系统》。老师是一个很厉害的研究Unix的老先生，没有指定课本，但是好的Unix书都推荐了。这门课的评价是6.5。老师是很有水平的，但是讲课的书评不太好，而且他也说了，“这门课的内容太多，我只是给你引一下路。”不幸的是因为老师不要求大多数同学也就没有学，以致到第二学期，经常有人问我关于Unix的基本概念。确实现在的学生开始就用Windows，甚至Shell也不会用，要是自己不努力靠老师讲永远也不会理解操作系统。&lt;br /&gt;&lt;br /&gt;然后就是选修的《机器翻译基础》。这门课老师讲的还是不错的，但是我的基础不太好，对于概率学习的内容基本不会，对于形式语言的内容也不熟悉，不过其他的大部分同学还不入我:)。个人评价是6分。&lt;br /&gt;&lt;br /&gt;选修课《Internet信息处理技术》，虽然这是一门讲搜索引擎的课，但是老师讲成了概念课，基本全是高层的概念，基本没有讲实际的技术。个人评价1分。&lt;br /&gt;&lt;br /&gt;必修课《自然辩证法》《科学社会主义》，不做评价了。&lt;br /&gt;&lt;br /&gt;第二学期的第一门必修是《高性能计算》，上课的是力学系的一位老师，课的内容是并行机和并行算法。老师讲的还是很好的，但是由于是力学系的老师，于是讲的并行算法大多是数值算法，还有很多力学上求最优化的例子。这些内容对于计算机系的学生来说，无疑是比较难懂的。要是多讲一些非数值算法就好了。个人评价是7分。&lt;br /&gt;&lt;br /&gt;第二们必修是《并行计算》，这门课我到现在也没有搞明白到底准备讲什么。而且老师在课堂上还讲了很多错误概念，比如“集群机器有统一的OS，主控节点上放OS的大部分，每个CPU放一个微内核的OS”。而且在课堂上就经常讲一些浮躁的言论，比如计算机要消失了，程序员到30岁就没前途了。个人评价是-1分，不仅内容没讲，而且灌输错误的观念。&lt;br /&gt;&lt;br /&gt;两门英语课，不做评价了。&lt;br /&gt;&lt;br /&gt;选修《数字图像处理》，上课就是念课件。评价2分。&lt;br /&gt;&lt;br /&gt;选修《64位微处理器编程》，老师自己估计也不懂汇编，上课的方式是让选修的同学轮流上台讲，然而大部分人上去就是照书念。评价0分。&lt;br /&gt;&lt;br /&gt;选修《中间件》，同上，上课还是主要是老师讲，但是其中要3个同学讲，都讲的不错。评价2分。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;总体来说，个人对课程很不满意，即没有讲最新的技术（会的人很少，自己都不理解），也没有讲基本理论，甚至不上数学课。不过整个国家都在浮躁的气氛中，学校只是一个缩影。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-1086002594112372888?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/1086002594112372888/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/blog-post.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/1086002594112372888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/1086002594112372888'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/blog-post.html' title='研究生课程教了些什么'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-6692044961734146420</id><published>2012-02-07T22:00:00.000-08:00</published><updated>2012-02-07T22:01:05.351-08:00</updated><title type='text'>How to get Mac address by CSharp</title><content type='html'>可以通过调用WMI来的到本机的配置信息。&lt;pre class="brush: csharp"&gt;&lt;br /&gt;string query = "select MACAddress from Win32_NetworkAdapterConfiguration where IPEnabled='TRUE'";&lt;br /&gt;ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);&lt;br /&gt;ManagementObjectCollection collection = searcher.Get();&lt;br /&gt;foreach (ManagementObject mo in collection)&lt;br /&gt;{&lt;br /&gt;    string mac = mo["MACAddress"].ToString();&lt;br /&gt;    MessageBox.Show(" Network card MAC Address is :"+ mac);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-6692044961734146420?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/6692044961734146420/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/wmi-string-query-select-macaddress-from.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/6692044961734146420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/6692044961734146420'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/wmi-string-query-select-macaddress-from.html' title='How to get Mac address by CSharp'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-3863961048704551354</id><published>2012-02-07T21:56:00.000-08:00</published><updated>2012-02-07T21:56:06.886-08:00</updated><title type='text'>Python 学习笔记（1）</title><content type='html'>&lt;span style="font-size: 180%; font-weight: bold;"&gt;引子&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;临近毕业了，毕业论文的问题改了好久也不见提升了。于是决定学一下python。看了一些python的入门文章，觉得讲的一般，可能是我已经算一个熟练的程序员了，对于按部就班入门的文章没有什么耐性吧。看到一个同门在修改一个师兄留下的GTK UI的程序，于是想何不用python写一个GTK下的UI程序呢，于是就开始了python的探索之旅。&lt;br /&gt;&lt;span style="font-size: 180%; font-weight: bold;"&gt;&lt;br /&gt;0.1 环境的配置&lt;/span&gt;&lt;br /&gt;首先是下载python的运行时。一般的Linux下都自带了2.5版本，其实你稍微注意下会发现，Gnome桌面中的有些程序其实使用python写的。比如Fedroa8中配置网络设备的程序，其实就是一个python进程。至于windows，下载一个安装程序就OK。www.python.org，不用怀疑，去吧。现在有3.0的beta版本可用，不过比较成熟的python库都是基于2.5的，所以推荐下载2.5版本。&lt;br /&gt;&lt;br /&gt;我的目标是一个UI程序，准备选wxWidgets。实话说这个UI库的风格和MFC比较类似，不过C++本身的缺陷就决定了UI库肯定都是那么个样子。但是python作为一种动态语言wrap了C++库之后，程序就优美多了。下载一个wxPython吧。www.wxPython.org，不过这个包的下载寄宿在sourceforge下，而最近好像sourceforge又被墙了，自己想办法去下载。对于windows而言，还是一个安装程序，对于linux有点要注意的。&lt;br /&gt;&lt;br /&gt;linux下wxPython自己带了一个wxWidgets的源码树，默认情况下会编译并把这个源码树安装到&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;/opt/wx/2.8&lt;/span&gt;&lt;br /&gt;下，一定要按照它的安装文档写选项。否则在你的机器已经有wxWidgets时就会安装错误。wxPython的安装文档提到最后还有两个环境变量要设置&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;PYTHONPATH&lt;/span&gt;和&lt;span style="font-weight: bold;"&gt;LD_LIBRARY_PATH&lt;/span&gt;，&lt;br /&gt;前者是为了告诉python到哪里找安装的wxPython模块，后者是指示动态库到哪里找。对于前者其实你只需要把 $WXPython/wxPython/wx这个目录拷贝到 /usr/lib/python25下就可以了，后者要是偷懒直接把&lt;span style="font-weight: bold;"&gt;/opt/wx/2.8/lib&lt;/span&gt;下的动态库拷贝到能找到的地方也可以。&lt;br /&gt;&lt;br /&gt;安装好了之后写一个简单的程序试试吧&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 180%; font-weight: bold;"&gt;0.2 HelloWorld&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: python"&gt;import wx&lt;br /&gt;&lt;br /&gt;class Frame(wx.Frame):&lt;br /&gt;   """ I am Class doc"""&lt;br /&gt;&lt;br /&gt;   def __init__(self, image, parent =None, id =-1,&lt;br /&gt;                pos= wx.DefaultPosition,&lt;br /&gt;                title='Hello, wxPython!'):&lt;br /&gt;       temp= image.ConvertToBitmap()&lt;br /&gt;       size= temp.GetWidth(), temp.GetHeight()&lt;br /&gt;       wx.Frame.__init__(self, parent, id, title, pos, size)&lt;br /&gt;       self.bmp= wx.StaticBitmap(parent=self, bitmap= temp)&lt;br /&gt;&lt;br /&gt;class App(wx.App):&lt;br /&gt;   def OnInit(self):&lt;br /&gt;       print('In OnInit')&lt;br /&gt;       image=wx.Image('007.jpg', wx.BITMAP_TYPE_JPEG)&lt;br /&gt;       self.frame= Frame(image)&lt;br /&gt;       self.frame.Show()&lt;br /&gt;       self.SetTopWindow(self.frame)&lt;br /&gt;       return True&lt;br /&gt;&lt;br /&gt;if __name__=='__main__':&lt;br /&gt;   app.MainLoop()&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;保存为一个文本文件后缀为.py就可以,注意要在这个文件的同级目录下放一个叫image=wx.Image('007.jpg', wx.BITMAP_TYPE_JPEG) 中指定的图形文件。在shell下运行&lt;br /&gt;python wx01.py，&lt;br /&gt;会出现一个显示你准备的图形的窗口。&lt;br /&gt;&lt;br /&gt;这个例子来自 wxPython in action 这本书，电子版本很容易找，不过是E文的。这本书是很不错的wxPython的参考资料。&lt;br /&gt;&lt;br /&gt;第一个python程序就完成了。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-3863961048704551354?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/3863961048704551354/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/python-1.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/3863961048704551354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/3863961048704551354'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/python-1.html' title='Python 学习笔记（1）'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-1860368313206045345</id><published>2012-02-04T08:17:00.001-08:00</published><updated>2012-02-04T08:17:36.712-08:00</updated><title type='text'>非典型性C语言教程- 0.3 计算机程序到底是什么</title><content type='html'>前几天上课又听到了老师在宣扬“计算机行业没有经验”的论点。说计算机行业发展的太快，越老越不行，积累的经验转眼就过时。这种浮躁的言论已经听过无数次了，但是一个大学研究生课的老师在课堂上讲出来还是第一次。今天这个主题就和60年前计算机就出现的东西有关。&lt;br /&gt;&lt;br /&gt;上次讲了，编译程序首先调用预处理程序处理C语言文件中的预处理命令，然后自己编译之生成目标文件，最后调用连接程序将目标文件和库文件连接成一个可执行程序。那么一段计算机程序到底是什么呢？&lt;br /&gt;&lt;br /&gt;60年前阿兰.图灵，冯.诺依曼等人提出了计算机的体系模型，60年过去了目前实际运行的计算机都是遵循的冯.诺依曼体系。首先讲图灵机的概念，下面是www.wikipedia.org  条目Turing machienes对&lt;span style="font-style: italic;"&gt;通用图灵机&lt;/span&gt;的简介：&lt;br /&gt;&lt;blockquote&gt;Turing machines are extremely basic abstract symbol-manipulating devices which, despite their simplicity, can be adapted to simulate the logic of any computer that could possibly be constructed. They were described in 1936 by Alan Turing. Though they were intended to be technically feasible, Turing machines were not meant to be a practical computing technology, but a thought experiment about the limits of mechanical computation; thus they were not actually constructed. Studying their abstract properties yields many insights into computer science and complexity theory.&lt;br /&gt;&lt;br /&gt;A Turing machine that is able to simulate any other Turing machine is called a Universal Turing machine (UTM, or simply a universal machine). A more mathematically-oriented definition with a similar "universal" nature was introduced by Alonzo Church, whose work on lambda calculus intertwined with Turing's in a formal theory of computation known as the Church–Turing thesis. The thesis states that Turing machines indeed capture the informal notion of effective method in logic and mathematics, and provide a precise definition of an algorithm or 'mechanical procedure'.&lt;/blockquote&gt;&lt;br /&gt;这个条目有图灵机的形式化定义，以及关于图灵机几个著名问题的证明。简单来说图灵机由4部分构成：&lt;br /&gt;&lt;ol&gt;&lt;li&gt;一条无限长的纸带，分为一个一个单元，这条纸带可以左右移动。每个单元可以记录符号。&lt;/li&gt;&lt;li&gt;一个头，可以在纸带上读和写符号。&lt;/li&gt;&lt;li&gt;活动表，记录了纸带和头如何活动。&lt;/li&gt;&lt;li&gt;一个状态寄存器，记录活动表的状态。&lt;/li&gt;&lt;/ol&gt;图灵模仿了人解题的过程，解决一个问题时，头在根据活动表的内容读或写纸带单元的内容，并相应的移动纸带。这个模型就是现代计算机的鼻祖。后来冯.诺依曼提出了更具体的计算机体系。计算机由5部分组成：&lt;br /&gt;&lt;ol&gt;&lt;li&gt;执行单元&lt;/li&gt;&lt;li&gt;运算部件&lt;/li&gt;&lt;li&gt;内存&lt;/li&gt;&lt;li&gt;I/O&lt;/li&gt;&lt;li&gt;程序计数器PC&lt;/li&gt;&lt;/ol&gt;执行单元根据PC指示的地址去内存中读取指令，然后指令可以读写内存，将内存取出的数字交给运算部件运算。冯.诺依曼机器中指令和数据是同一存储的。人通过I/O来与计算机交互。这个模型和图灵机基本类似：纸带就是内存，活动表也是内存的一部分，头就是执行和运算部件。程序就是活动表中左右移动纸带，读写纸带的活动序列。同样本质上来讲程序就是内存中的指令序列。&lt;br /&gt;&lt;br /&gt;后来编写程序的技术日新月异，各种概念技术层出不穷，但是本质上来说任何程序，静态的如C, Forturn，Pascal，稍微动态一点的C++，Java，动态的Python,  Lua，Ruby，传说中的 Lisp,Prolog最终都是内存中的指令序列。因为60年来计算机都是遵循冯.诺依曼模型的。&lt;br /&gt;&lt;br /&gt;虽然人自己到底是怎么描述世界的还不是很清楚，但是人描述世界的方式肯定和计算机描述世界的方式差别巨大，于是人们就不断的发展编程技术使得编程能更接近人描述世界的方式。首先是汇编。显然一串数字是很不好记住的，于是用助记符去代表难以理解的数字。比如讲0xCC表示为int 3。后来发展出第一种高级语言Forturn。&lt;br /&gt;&lt;br /&gt;60年代人们发现单纯的跳转指令，使得程序很不好理解（人不好理解，机器一点问题没有），于是发展出结构化程序设计，使得调用子程序（很多名字过程，函数，方法）有了标准。后来人们发现子程序一般要和程序处理的数据结合在一起，于是就发展了面向对象OO的技术。编译器自动完成在函数调用的时候传递this参数，省去了自己写的麻烦。后来发现程序编译完成后，没有源代码就无法知道该怎么调用，于是加入元数据让编译完成之后的组建也能自己描述自己。&lt;br /&gt;&lt;br /&gt;无论技术怎么更新，新技术只是自动的解决原来技术中不足的地方。比如用汇编照样可以写出面向对象的程序，但是用Java就方便的多，因为编译器帮你完成了许多工作，但是一个Java程序和一个汇编程序一样，最终执行的时候都是一条一条的计算机指令没有什么区比。&lt;br /&gt;&lt;br /&gt;第0章说过，C语言重要的一条原因就是C语言最贴近计算机的模型。C语言由一组函数构成，函数就是一段一段的指令序列。函数中有一个叫main的，程序从main开始执行起，就是指令序列的起点。一直到结束，就是一个完成的指令序列。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-1860368313206045345?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/1860368313206045345/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/c-03.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/1860368313206045345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/1860368313206045345'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/c-03.html' title='非典型性C语言教程- 0.3 计算机程序到底是什么'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-856503825143611459</id><published>2012-02-04T08:07:00.000-08:00</published><updated>2012-02-04T08:07:08.802-08:00</updated><title type='text'>非典型性C语言教程－0.1 shell，命令行</title><content type='html'>&lt;p&gt;在神话时代，要命令机器做事情只能用穿孔纸带。后来有了分时系统，于是就有了shell，也就是俗称的命令行。在图形化界面诞生之前，所有的操作系统都只有命令行界面。 现在的OS也大多都有命令行，好像唯一没有的就是苹果的MacOS。&lt;/p&gt;&lt;p&gt;与现在GUI（图形用户接口）中，是以数据文件为中心。比如你双击一个.txt文件，会自动为你打开文本编辑器，并用文本编辑器打开这个.txt文件。但 是在命令行中，以程序为中心。要打开一个文本文件，必须先运行文本编辑器，再用文本编辑器打开这个文本文件。下面先讲解MS的 cmd再说Unix的shell。&lt;p/&gt;&lt;p&gt;在MS-DOS的时代，系统引导之后就会启动command.exe程序，再由command.exe去启动别的程序。现在你可以通过附件，命令提示符来启动cmd窗口。&lt;p/&gt;&lt;a href="http://bp1.blogger.com/_Dhc_J360IPo/RjhA_TdOiYI/AAAAAAAAAAo/PznfFEAEF3w/s1600-h/cmd.JPG"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5059865637649549698" src="http://bp1.blogger.com/_Dhc_J360IPo/RjhA_TdOiYI/AAAAAAAAAAo/PznfFEAEF3w/s320/cmd.JPG" style="cursor: pointer; margin: 0pt 10px 10px 0pt;" /&gt;&lt;/a&gt;&lt;br/&gt;&lt;p&gt;这时你可以在提示符后面敲命令了。比如你敲一个cl -o hello hello,.c。这时cmd程序会分析这行命令，首先找cl。有些命令由cmd程序本身提供称之为内部命令，比如cd改变目录，dir列当前目录。显然C语言编译器cl不是cmd的内部命令。然后cmd就会在当前目录下找这个cl.exe，显然也没有。之后cmd就开始找PATH环境变量了。等等！你说什么是环境变量？环境变量就是系统运行时对每个程序都有效的一组变量，对于windows系统，我的电脑-&amp;gt;属性-&amp;gt;高级-&amp;gt;环境变量就会出现:&lt;/p&gt;&lt;a href="http://bp1.blogger.com/_Dhc_J360IPo/RjhBOTdOiZI/AAAAAAAAAAw/uPRnaDO_hWE/s1600-h/Ev.bmp"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5059865895347587474" src="http://bp1.blogger.com/_Dhc_J360IPo/RjhBOTdOiZI/AAAAAAAAAAw/uPRnaDO_hWE/s320/Ev.bmp" style="margin: 0pt 10px 10px 0pt;" /&gt;&lt;/a&gt;&lt;br/&gt;&lt;p&gt;这有两类，上面是当前用户的环境变量，下面是全局的环境变量。可以看到由一个叫PATH的环境变量。这个环境变量是一组目录名。&lt;p/&gt;&lt;p&gt;前面说到cmd，在当前目录也找不到cl.exe之后，就会找PATH环境变量，从PATH指示的目录一个一个的找。直到找到一个下有一个叫cl.exe的可执行文件为止。要是一个也找不到就会报告错误。找到之后，就会执行cl，并把后面的-o hello hello.c传递给cl，这个就是命令行参数。也就是main的参数。还有一点要注意的编译器是找hello.c文件可不会去找PATH变量，最好把hello.c放在当前目录下。&lt;p/&gt;&lt;p&gt;Unix系统下每一个用户一旦登陆，就会为用户启动一个shell程序。这时会出现一个提示符。这个提示符可能不同，$, #等等。执行gcc -o hello hello.c， 执行过程和windows的类似。有一点不同，就是Unix的shell不会在当前目录下找gcc。就是说Unix的shell不会在当前目录下找可执行文件。要是当前目录下有一个叫gcc的可执行程序，你必须敲./gcc，其中.表示当前目录。&lt;p/&gt;&lt;p&gt;顺便说下一个通用的相对路径, “.”表示当前目录，”..”表示上级目录。比如D:\xx\yy\zz\下有一个hello.c， 当前目录在D:\xx\yy\tt，那么命令就要变成cl -o hello ..\zz\hello.c。&lt;p/&gt;&lt;p&gt;好了到这里，是不是知道对如何编译一个C程序了。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-856503825143611459?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/856503825143611459/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/c01-shell.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/856503825143611459'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/856503825143611459'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/c01-shell.html' title='非典型性C语言教程－0.1 shell，命令行'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_Dhc_J360IPo/RjhA_TdOiYI/AAAAAAAAAAo/PznfFEAEF3w/s72-c/cmd.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-621868785942287808</id><published>2012-02-04T07:54:00.001-08:00</published><updated>2012-02-04T07:54:31.910-08:00</updated><title type='text'>非典型性C语言教程-0.0.1 标准（standard），实现（implementation</title><content type='html'>标准一般是由某个组织发布的一组规范。这个组织一般是标准化组织或某个大公司，或是一些大公司的联合。比如C++就是一个标准。C++一般指1998年由 ISO（国际标准化组织）发布的ISO/IEC 14882:1998。这个文件规定了C++语言应该遵循那些规范。比如函数必须有返回类型（与之对应C语言可以省略返回值），规定了vector的用法 等等。写程序的人最好按照标准写程序，写编译程序的人也最好按照标准写编译程序，以便使得按照标准写的程序能编译通过。&lt;br /&gt;各种标准的作用就是给大家一个规范，符合这个规范生产的产品可以集成在一起。比如，GB（国家标准）规定了插座提供220V，50HZ的交流电，于是供电 公司，和各种电器生产厂商都遵循标准。这样你才可以在任意一个商店买任意一种电器都能插到任意一个插座中，两者还能配合的很好。同理，大家都遵循C++标 准时，任意一个人写的遵循C++标准的C++程序就可以和任意遵循C++标准的程序库连接在一起，才能拿到任意一个编译器上都能通过编译，并且编译得到的 程序有一致的运行结果。&lt;br /&gt;实现就是遵循标准生产出的实际的产品。比如微软VS2005带的C++编译器cl.exe，就是一个C++标准的编译器实现。同样GNU组织的g++也是。&lt;br /&gt;&lt;br /&gt;实际上好多名词都是标准：&lt;br /&gt;&lt;ol&gt;&lt;li&gt;    MPI， Message Passing Interface，这个标准是为了使按标准编写的消息传递的并行程序有广泛的移植性。 官方网站是http://www.mpi-forum.org/。 它有非常多的实现，各种大型并行机器都有商业的MPI库，Intel也有自己的MPI库，还有诸多开源版本。（列这个在这，是因为刚刚上了并行计算课）&lt;/li&gt;&lt;li&gt;C++， 最近的标准是ISO 1998年发布的，简称C++98。这个标准直到最近才有完全符合标准的编译器。下一个版本的标准可能是2007&lt;/li&gt;&lt;li&gt;C，最早的标准是C89，是1989年ANSI标准化的，后来被ISO采纳。最近的标准是C99，1999年ISO发布。C99标准给C语言添加了许多新特性，比如const。&lt;/li&gt;&lt;li&gt;JavaScript， EMCAScript。原来由Netscape公司开发的脚本语言，后来标准化。&lt;/li&gt;&lt;/ol&gt;这里说一下这两个概念的原因是，好多人对这两个概念搞不清楚。经常以为某个实现就是全部，比如++就是VC， Java就是JBuilder，数据库就是 SQLServer。&lt;br /&gt;不拘泥某个具体实现，才能看的更远。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-621868785942287808?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/621868785942287808/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/c-001-standardimplementation.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/621868785942287808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/621868785942287808'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/c-001-standardimplementation.html' title='非典型性C语言教程-0.0.1 标准（standard），实现（implementation'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7472707667787761494.post-2290729860915108310</id><published>2012-02-04T07:47:00.000-08:00</published><updated>2012-02-07T21:55:29.313-08:00</updated><title type='text'>非典型性C语言教程－0</title><content type='html'>&lt;h1&gt;非典型性C语言教程－0&lt;/h1&gt;&lt;h2&gt;起因&lt;/h2&gt;自从实验室里面配备了Sun公司赞助的Ultra 20工作站之后，老师就不时的要求我给实验室的兄弟姐妹讲Solaris的使用和管理。我发现好多学生对C语言——传说中和Unix一起诞生，为了编写Unix而被创造的语言——基本就是不会。好一点的还能用VC6写个printf的Hello world，差一点的连这个也不会。确实学校的c语言教育实在是欠缺，好多学校c语言上机试验课还在用Turbo C2.0。 大部分学生学完c语言之后就停留在用TC2.0写个Hello world的层面上，换了windows＋VC6就不会用了。计算机是实践的科学，最重要的是自己动手做东西。搞一堆概念，吹的天花乱坠，结果不能用计算机去去解决一个实际的问题，学计算机就没有作用。学一门计算机程序设计语言最重要的是能用这门语言来解决实际的问题，学了一堆语言的概念，变量，指针，函数，结果用这个语言却写不出一个能运行的有用的程序，甚至别人给了一个写好的语言的组件连怎么用这个组件都不会，那你考试考再高的分，概念背的再熟有什么用。所以我想写这个C语言教程，从实用的角度去讲述C语言。我想到达的目标：要是对计算机一点不懂，估计不能从本教程学到任何东西。要是已经学过学校的C语言课，学过计算机的其他基础课，但是对有些问题不明白，看完本教程可以使你深刻的理解C语言，并能产生生产工业级的代码，而不是只能写些Hello world之类的玩具程序。下面开始正文:&lt;h2&gt;C语言的重要性&lt;/h2&gt;C语言是一种重要的语言，其重要性在于C语言非常接近当前机器的计算模型，它和机器的汇编程序可以一一对应。常见的操作系统Unix和Windows的内核都是C语言＋汇编编写的，其中汇编只用于平台相关的部分。很多语言和C语言有类似的语法结构，比如C++，而Java和C＃直接派生自C++。在性能要求严格的地方还是广泛使用C语言，比如嵌入式系统，比如控制火箭的程序。驱动程序基本都是用C语言编写的，道理和操作系统的内核用C语言编写一样。&lt;h3&gt;什么是C语言的源文件和头文件&lt;/h3&gt;C语言的source文件和head文件，都是简单的文本文件，也就是说你用任何的文本编辑器都可以编写。并不一定非要用VC或是什么其他的工具才能书写，你可以用记事本写，只需要将源文件的扩展命保存问.c，把头文件的扩展名保存为.h就可以了。需要注意的是源文件和头文件中除了双引号内的字符，和注释内的字符，都必须是&lt;span style="color: red;"&gt;标准的ASCII字符&lt;/span&gt;。不然就会出问题。比如用VC2005编译一个带全角空格的程序时。&lt;pre class="brush: c"&gt;#include &lt;stdio.h&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;    　// 注意这里有一个全角的空格，调整你的输入法就可以输入一个全角的空格。　&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;就会产生错误&lt;pre&gt;&lt;br /&gt;1&amp;gt;...\main.cpp(5) : error C3872: “x3000”: 此字符不允许在标识符中使用&lt;br /&gt;1&amp;gt;...\main.cpp(6) : error C2065: “　”: 未声明的标识符&lt;br /&gt;1&amp;gt;...\main.cpp(6) : error C2143: 语法错误: 缺少“;”(在“}”的前面)&lt;br /&gt;&lt;/pre&gt;&lt;ol&gt;&lt;li&gt;敲代码的时候敲入了中文的注释忘记改会输入法了，结果敲了一个中文的标点符号“；”“，”等等，结果编译器报错“未知的字符”，由于和英文的标点差异很小，不仔细看还真开不出来。&lt;/li&gt;&lt;li&gt;从网页或是Word文档，或是其他什么地方复制粘贴来的代码，常常会出现这种错误。&lt;/li&gt;&lt;/ol&gt;所以写代码的时候一定要注意输入法的状态。&lt;h2&gt;如何编译C语言&lt;/h2&gt;和其他的虚拟机或解释性语言不一样，要将一个或一组C语言文件变成一个真正可以执行的程序需要两步。首先用编译器（compiler）将源文件编译成目标文件，再用链接器（linker）将目标程序和需要的库文件链接到一起生成一个可执行文件。这个步骤按现在流行的说法叫构建（build）。我们还是逃不脱Hello world！&lt;pre class="brush: c"&gt;#include &lt;stdio.h&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;    printf("Hello world!\n");&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;为了将这个程序变成一个实际可以执行的程序，&lt;ol&gt;&lt;li&gt;在unix下用下面命令： cc -o hello hello.c 或者 gcc -o hello hello.c&lt;/li&gt;&lt;li&gt;在windows下用cl -o hello.exe hello.c 或者 bcc32 -o hello.exe hello.c &lt;li&gt;&lt;/ol&gt;大家发现这几个命令非常类似。因为最原始的就是cc -o hello hello.c，后面出的编译器都模仿了cc的参数命令。第一个是比较通用的C语言编译器，cc的意思是C comilper。Gcc原来的意思是Gnu C comilper后来 Gnu组织扩展了gcc的功能变成了 Gnu Comilper Collection。Cl是微软的编译器，bcc32则是Borland公司的编译器，也就是传说中TC2.0的后续版本。累了下回再写。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7472707667787761494-2290729860915108310?l=sttony.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sttony.blogspot.com/feeds/2290729860915108310/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://sttony.blogspot.com/2012/02/c0.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/2290729860915108310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7472707667787761494/posts/default/2290729860915108310'/><link rel='alternate' type='text/html' href='http://sttony.blogspot.com/2012/02/c0.html' title='非典型性C语言教程－0'/><author><name>Li Tong</name><uri>https://profiles.google.com/101720015111696063026</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-jW1zRYeciTw/AAAAAAAAAAI/AAAAAAAAAc4/cjKuuKna1RI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
