昵称:floerggyy
园龄:7年3个月
粉丝:1
关注:0

搜索

 
 

常用链接

  • 我的随笔
  • 我的评论
  • 我的参与
  • 最新评论
  • 我的标签

我的标签

  • c/c++ zlib minizip usage(1)

随笔分类(49)

  • C/C++(12) (rss)
  • dot net(15) (rss)
  • j2ee(1) (rss)
  • j2se technology(1) (rss)
  • network programing(dotnet) (rss)
  • Remoting technology(1) (rss)
  • sunshine life(15) (rss)
  • web(html/js/xml)(4) (rss)
  • WSE (rss)

随笔档案(49)

  • 2010年6月 (1)
  • 2008年6月 (1)
  • 2008年4月 (4)
  • 2008年3月 (4)
  • 2008年2月 (3)
  • 2007年12月 (1)
  • 2007年4月 (1)
  • 2007年3月 (3)
  • 2006年12月 (1)
  • 2006年11月 (2)
  • 2005年12月 (3)
  • 2005年10月 (2)
  • 2005年7月 (3)
  • 2005年5月 (2)
  • 2005年4月 (1)
  • 2005年3月 (2)
  • 2005年1月 (4)
  • 2004年12月 (11)

相册

  • my GF
  • other
  • this is me

open source site

  • http://csharp-source.net/
  • http://sourceforge.net
  • http://www.asp.net
  • http://www.codeproject.com
  • http://www.gotdotnet.com/
  • http://www.softviewer.com (rss)

some blogs

  • bestcomy (rss)
  • wayfarer (rss)
  • 宝玉 (rss)
  • 狂人思维 (rss)
  • 狂人思维~~~~这家伙的想法真的很超常^_^
  • 灵感之源 (rss)

积分与排名

  • 积分 - 36889
  • 排名 - 2898

最新评论

阅读排行榜

评论排行榜

推荐排行榜


Powered by: 博客园
模板提供:沪江博客
博客园 | 首页 | 发新随笔 | 发新文章 | 联系 | 订阅订阅 | 管理

2010年6月30日

vs下调试多个c项目联调

一.Debug版本和Release版本的区别

Debug通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。

只有Debug版本的程序才能设置断点、单步执行、使用TRACE/ASSERT等调试输出语句。Release版本不包含任何调试信息,所以体积小、运行速度快。

一般而言Debug版本会比Release版本多出*.ilk文件和*.pdb文件。

1.*.ilk文件

ilk后缀全称为“Incremental Linking”,意即增量链接。

VC6中,“Project Setting à Link (Category:General)”默认勾选“Link incrementally”;相应VC2005中,“项目属性à配置属性à链接器à常规à启用增量链接”默认选项为“是(/INCREMENTAL)”。

当选定渐增型编译链接时,链接器自动生成ILK文件,记录链接信息,也就是每次重新编译并不编译所有的源文件,只编译改动过的文件。而编译器怎么知道哪些编译过哪些未编译过呢,除了检查修改时间外,这个ilk文件也是很重要的信息。

2.*.pdb文件

pdb后缀全称为“Program Debug Database”,意即程序数据库文件。

VC6中,“Project Setting à Link (Category:General)”默认勾选“Generate debug info”, “Project Setting à Link (Category:Customize)”默认勾选“Use program database”;相应VC2005中,“项目属性à配置属性à链接器à调试”,默认“生成调试信息”选项为“是(/DEBUG)”,默认“生成程序数据库文件”处填写“.\Debug\*.pdb”。该选项对应的编译开关为/PDB。

符号文件(Symbol Files)是一个数据信息文件,它包含了应用程序二进制文件(比如EXE、DLL等)的调试信息,专门用来作调试之用,最终生成的可执行文件在运行时并不需要这个符号文件,但你的程序中所有的变量信息都记录在这个文件中。所以调试应用程序时,这个文件是非常重要的。用VC和 WinDbg调试程序时都要用到这个文件。

关于符号文件,参考《符号文件—Windows 应用程序调试必备》。

二.VC常用调试操作

快捷键
 作用
 
F5
 开始调试,逐断点调试
 
F9
 设置(取消)断点
 
Ctrl+F10
 调试到光标所在位置
 
F10
 单步调试,遇到子函数跳过
 
F11
 单步调试,遇到子函数跟踪进入内部
 
Shift+F11
 从当前函数中跳出
 
Shift+F5
 停止调试
 

    一般F9设断点,F5启动后,F10、F11和Shift+F11交替使用,以在多个断点处调试。

三.联合调试链接库(lib、dll)项目和应用程序(exe)项目?

对于链接库项目,必须要导入一个能够调用它的测试程序进来,通过应用程序的执行来达到调试的目的。

既然是调试,当然静态或动态链接库项目应生成带调试信息的Debug版本,VC6中“Project Setting à Link (Category:General)”默认勾选“Generate debug info”,相应VC2005中的“项目属性à配置属性à链接器à调试à生成调试信息”默认选项为“是(/DEBUG)”。

关于*.obj文件和*.lib文件

obj:Intermediate file,CPP对应的二进制代码格式,是未经重定位的!

lib:Object File Library,若干个obj的集合,本质与obj相同!

使用时,obj和lib是没有本质区别的,lib就是obj,使用lib地方都可以使用obj。

对于*.cpp文件中的static变量或函数,在*.obj或*.lib中既有符号信息又有实体定义。

对于*.cpp文件中的extern变量或函数,在*.obj或*.lib中一般都会有符号信息,实体既可以定义在本文件中,也可以在其他文件中定义。对于extern变量或函数,链接时,将在所有的*.obj或*.lib中查找实体。

Lib和Exe协调:

新建解决方案D:\ LibDemo\LibDemo(.dsw,.sln),在其下新建静态库(Win32 Static Library)项目MyLib(.dsp,.vcproj)和静态库测试项目(Win32 Console Application)MyLibDemo(.dsp,.vcproj)。首先需要为MyLibDemo项目附加头文件包含和链接库包含。

(1)若设置MyLibDemo为启动项目,执行F5调试命令,则在MyLib和MyLibDemo中的断点处都会暂停。在MyLibDemo中可F11进入MyLib中的函数定义处。

(2)若设置MyLib为启动项目,则要配置外部exe调用程序:

VC6中,“Project Setting àDebug(Category:General)”中的“Executable for debug session”处填写exe路径,例如:D:\ LibDemo\MyLibDemo\Debug\MyLibDemo.exe。相应VC2005中,“项目属性à配置属性à调试à命令”处填写exe路径。

执行F5调试命令,则在MyLib和MyLibDemo中的断点处都会暂停。效果同(1)。

对于不同解决方案(.dsw,.sln)下的Lib项目和Exe项目协同调试方法同上。

Dll和Exe协调:

dll项目往往会附带生成一个对应的lib,是dll导出函数和符号链接信息。同lib项目生成的lib有点不同,这里只有原型信息,实体代码在dll中。dll是可实际运行的二进制代码,其中有定位代码。

新建解决方案D:\DllDemo\DllDemo(.dsw,.sln),在其下新建动态库(Win32 Dynamic-Link Library)项目MyDll(.dsp,.vcproj)和动态库测试项目(Win32 Console Application)MyDllDemo(.dsp,.vcproj)。

同Lib和Exe协调一样,首先需要为Exe项目附加头文件(.h)包含和链接库(.lib)包含。

(1)若设置MyDllDemo为启动项目,为了使MyDll.dll对调试exe可见,设置MyDllDemo的调试工作目录(Working directory)为..\MyDll\Debug。

执行F5调试命令,则在MyDll和MyDllDemo中的断点处都会暂停。在MyDllDemo中可F11进入MyDll中的函数定义处。

(2)若设置MyDll为启动项目,则要配置外部exe调用程序:

VC6中,“Project Setting àDebug(Category:General)”中的“Executable for debug session”处填写exe路径,例如:D:\DllDemo\MyDllDemo\Debug\MyDllDemo.exe。相应VC2005中,“项目属性à配置属性à调试à命令”处填写exe路径。

为了使MyDll.dll对调试exe可见,设置调试工作目录(Working directory)为.\Debug。

执行F5调试命令,则在MyDll和MyDllDemo中的断点处都会暂停。效果同(1)。

对于不同解决方案(.dsw,.sln)下的Dll项目和Exe项目协同调试方法同上。

在(1)和(2)中,除了指定调试工作目录外,还可以处理生成后事件,将生成的链接库文件直接复制到应用程序Debug目录下。具体的,在VC6中“Project Setting àPost-built step”或VC2005中“项目属性à配置属性à生成事件à生成后事件”输入生成后处理命令:copy .\Debug\MyDll.dll ..\MyDllDemo\Debug\MyDll.dll。当然,还可以将MyLib(MyDll)的输出目录直接指向MyLibDemo(MyDllDemo)的Debug下。

四.VC调试小结

我们在VC2005中printf函数调用处设置断点,F11 将打开printf函数的源码文件C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\printf.c进入printf函数内部,实际上“工具à选项à项目和解决方案àVC++目录à源文件”中包含了crt源代码的路径:$(VCInstallDir)crt\src。

而在VC6中,C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC不存在,故试图F11进入printf内部时,将弹出“Find Source”对话框,提示“Please enter the path for PRINTF.C”文件。

调试VC时,编译器之所以能够跟踪进入C库函数,是因为编译器本身附带提供了Debug版本的CRT库。

VC6中的MSVCRTD.DLL-MSVCRTD.LIB-MSVCRTD.PDB(对应VC2005中msvcr80d.dll-msvcrtd.lib)为C Runtime Library的Debug版本,其中包含了C运行库的调试信息。

VC6中的MSVCP60D.DLL-MSVCPRTD.LIB-MSVCP60D.PDB(对应VC2005中msvcp80d.dll - msvcprtd.lib)为C++ Runtime Library的Debug版本,其中包含了C++运行库的调试信息。

鉴于Debug版本对调试信息的记录和DllàLib(*.obj,*.lib)àSrc(*.c,*.cpp)的对应关系,在VC中我们就可以设置断点跟踪调试代码。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/phunxm/archive/2010/01/17/5203931.aspx 

posted @ 2010-06-30 23:40 floerggyy 阅读(214) 评论(0) 编辑
 

2008年6月11日

摘抄
从msdn里找到的  
   
  To   convert   the   managed   DLL   to   mixed   mode    
   
  1.Link   with   /NOENTRY.   In   Solution   Explorer,   right-click   the   project   node   and   click   Properties.   In   the   project's   Property   Pages   dialog   box,   click   Linker,   and   then   click   Command   Line.   Add   this   switch   to   the   Additional   Options   field.    
   
  2.Link   msvcrt.lib.   In   the   project's   Property   Pages   dialog   box,   click   Linker,   and   then   click   Input.   Add   msvcrt.lib   to   the   Additional   Dependencies   property.    
   
  3.Remove   nochkclr.obj.   On   the   Input   page   (same   page   as   previous   step),   remove   nochkclr.obj   from   the   Additional   Dependencies   property.    
   
  4.Link   in   the   CRT.   On   the   Input   page   (same   page   as   previous   step),   add   __DllMainCRTStartup@12   to   the   Force   Symbol   References   property.
posted @ 2008-06-11 14:48 floerggyy 阅读(42) 评论(0) 编辑
 

2008年4月15日

C语言locale介绍
转载:http://www.chinaunix.net/jh/6/834459.html

locale 是国际化与本土化过程中的一个非常重要的概念,个人认为,对于中文用户来说,通常会涉及到的国际化或者本土化,大致包含三个方面:看中文,写中文,与 window中文系统的兼容和通信。从实际经验上看来,locale的设定与看中文关系不大,但是与写中文,及window分区的挂载方式有很密切的关系。本人认为就像一个纯英文的Windows能够浏览中文,日文或者意大利文网页一样,你不需要设定locale就可以看中文。那么,为什么要设定 locale呢?什么时候会用到locale呢? 

Tags: locale 设定 原因 解释 

一、为什么要设定locale 正如前面我所讲的,设定locale与你能否浏览中文的网页没有直接的关系,即便你把locale设置成en_US.ISO-8859-1这样一个标准的英文locale你照样可以浏览中文的网页,只要你的系统里面有相应的字符集(这个都不一定需要)和合适的字体(如simsun),浏览器就可以把网页翻译成中文给你看。具体的过程是网络把网页传送到你的机器上之后,浏览器会判断相应的编码的字符集,根据网页采用的字符集,去字体库里面找合适的字体,然后由文字渲染工具把相应的文字在屏幕上显示出来。 

在下文本人会偶尔把字符集比喻成密码本,个人觉得对于一些东西比较容易理解,假如你不习惯的话,把全文copy到任何文本编辑器,用字符集替换密码本即可。 

那有时候网页显示乱码或者都是方框是怎么回事呢?个人认为,显示乱码是因为设定的字符集不对(或者没有相应的字符集),例如网页是用UTF-8编码的,你非要用GB2312去看,而系统根据GB2312去找字体,然后在屏幕上显示,当然是一堆的乱码,也就是说你用一个错误的密码本去翻译发给你的电报,当然内容那叫一个乱;至于有些时候浏览的网页能显示一部分汉字,但有很多的地方是方框,能够显示汉字说明浏览器已经正确的判断出了网页的编码,并在字体库里面找到了相应的文字,但是并不是每个字体库都包含某个字符集全部的字体的缘故,有些时候会显示不完全,找一个比较全的支持较多字符集的字体就可以了。 

既然我能够浏览中文网页,那为什么我还要设定locale呢? 

其实你有没有想过这么一个问题,为什么gentoo官方论坛上中文论坛的网页是用UTF-8编码的(虽然大家一直强烈建议用GB2312编码),但是新浪网就是用GB2312编码的呢?而Xorg的官方网页竟然是ISO-8859-15编码的,我没有设定这个locale怎么一样的能浏览呢?这个问题就像是你有所有的密码本,不论某个网站是用什么字符集编码的,你都可以用你手里的密码本把他们翻译过来,但问题是虽然你能浏览中文网页,但是在整个操作系统里面流动的还是英文字符。所以,就像你能听懂英语,也能听懂中文。 最根本的问题是:你不可以写中文。 

当你决定要写什么东西的时候,首先要决定的一件事情是用那种语言,对于计算机来说就是你要是用哪一种字符集,你就必须告诉你的linux系统,你想用那一本密码本去写你想要写的东西。知道为什么需要用GB2312字符集去浏览新浪了吧,因为新浪的网页是用GB2312写的。 

为了让你的Linux能够输入中文,就需要把系统的locale设定成中文的(严格说来是locale中的语言类别LC_CTYPE ),例如zh_CN.GB2312、zh_CN.GB18030或者zh_CN.UTF-8。很多人都不明白这些古里古怪的表达方式。这个外星表达式规定了什么东西呢?这个问题稍后详述,现在只需要知道,这是locale的表达方式就可以了。 

二、到底什么是locale? locale这个单词中文翻译成地区或者地域,其实这个单词包含的意义要宽泛很多。Locale是根据计算机用户所使用的语言,所在国家或者地区,以及当地的文化传统所定义的一个软件运行时的语言环境。 

这个用户环境可以按照所涉及到的文化传统的各个方面分成几个大类,通常包括用户所使用的语言符号及其分类(LC_CTYPE),数字 (LC_NUMERIC),比较和排序习惯(LC_COLLATE),时间显示格式(LC_TIME),货币单位(LC_MONETARY),信息主要是提示信息,错误信息, 状态信息, 标题, 标签, 按钮和菜单等(LC_MESSAGES),姓名书写方式(LC_NAME),地址书写方式(LC_ADDRESS),电话号码书写方式 (LC_TELEPHONE),度量衡表达方式(LC_MEASUREMENT),默认纸张尺寸大小(LC_PAPER)和locale对自身包含信息的概述(LC_IDENTIFICATION)。 

所以说,locale就是某一个地域内的人们的语言习惯和文化传统和生活习惯。一个地区的locale就是根据这几大类的习惯定义的,这些locale定义文件放在/usr/share/i18n/locales目录下面,例如en_US, zh_CN and de_DE@euro都是locale的定义文件,这些文件都是用文本格式书写的,你可以用写字板打开,看看里边的内容,当然出了有限的注释以外,大部分东西可能你都看不懂,因为是用的Unicode的字符索引方式。 

对于de_DE@euro的一点说明,@后边是修正项,也就是说你可以看到两个德国的locale: /usr/share/i18n/locales/de_DE@euro /usr/share/i18n/locales/de_DE 打开这两个locale定义,你就会知道它们的差别在于de_DE@euro使用的是欧洲的排序、比较和缩进习惯,而de_DE用的是德国的标准习惯。 

上面我们说到了zh_CN.GB18030的前半部分,后半部分是什么呢?大部分Linux用户都知道是系统采用的字符集。 

三、什么是字符集? 字符集就是字符,尤其是非英语字符在系统内的编码方式,也就是通常所说的内码,所有的字符集都放在/usr/share/i18n/charmaps,所有的字符集也都是用Unicode编号索引的。Unicode用统一的编号来索引目前已知的全部的符号。而字符集则是这些符号的编码方式,或者说是在网络传输,计算机内部通信的时候,对于不同字符的表达方式,Unicode是一个静态的概念,字符集是一个动态的概念,是每一个字符传递或传输的具体形式。就像 Unicode编号U59D0是代表姐姐的“姐”字,但是具体的这个字是用两个字节表示,三个字节,还是四个字节表示,是字符集的问题。例如:UTF-8字符集就是目前流行的对字符的编码方式,UTF-8用一个字节表示常用的拉丁字母,用两个字节表示常用的符号,包括常用的中文字符,用三个表示不常用的字符,用四个字节表示其他的古灵精怪的字符。而GB2312字符集就是用两个字节表示所有的字符。需要提到一点的是Unicode除了用编号索引全部字符以外,本身是用四个字节存储全部字符,这一点在谈到挂载windows分区的时候是非常重要的一个概念。所以说你也可以把Unicode看作是一种字符集(我不知道它和UTF-32的关系,反正UTF-32就是用四个字节表示所有的字符的),但是这样表述符号是非常浪费资源的,因为在计算机世界绝大部分时候用到的是一个字节就可以搞定的 26个字母而已。所以才会有UTF-8,UTF-16等等,要不然大同世界多好,省了这许多麻烦。 

四、zh_CN.GB2312到底是在说什么? Locale 是软件在运行时的语言环境, 它包括语言(Language), 地域 (Territory) 和字符集(Codeset)。一个locale的书写格式为: 语言[_地域[.字符集]]. 所以说呢,locale总是和一定的字符集相联系的。下面举几个例子: 

1、我说中文,身处中华人民共和国,使用国标2312字符集来表达字符。 zh_CN.GB2312=中文_中华人民共和国+国标2312字符集。 

2、我说中文,身处中华人民共和国,使用国标18030字符集来表达字符。 zh_CN.GB18030=中文_中华人民共和国+国标18030字符集。 

3、我说中文,身处中华人民共和国台湾省,使用国标Big5字符集来表达字符。 zh_TW.BIG5=中文_台湾.大五码字符集 

4、我说英文,身处大不列颠,使用ISO-8859-1字符集来表达字符。 en_GB.ISO-8859-1=英文_大不列颠.ISO-8859-1字符集 

5、我说德语,身处德国,使用UTF-8字符集,习惯了欧洲风格。 de_DE.UTF-8@euro=德语_德国.UTF-8字符集@按照欧洲习惯加以修正 

注意不是[email]de_DE@euro.UTF[/email]-8,所以完全的locale表达方式是 [语言[_地域][.字符集] [@修正值] 

生成的locale放在/usr/lib/locale/目录中,并且每个locale都对应一个文件夹,也就是说创建了[email]de_DE@euro.UTF[/email]-8 locale之后,就生成/usr/lib/locale/de_DE@euro.UTF-8/目录,里面是具体的每个locale的内容。 

五、怎样去自定义locale 在gentoo生成locale还是很容易的,首先要在USE里面加入userlocales支持,然后编辑locales.build文件,这个文件用来指示glibc生成locale文件。 很多人不明白每一个条目是什么意思。 其实根据上面的说明现在应该很明确了。 

File: /etc/locales.build en_US/ISO-8859-1 en_US.UTF-8/UTF-8 

zh_CN/GB18030 zh_CN.GBK/GBK zh_CN.GB2312/GB2312 zh_CN.UTF-8/UTF-8 

上面是我的locales.build文件,依次的说明是这样的: 

en_US/ISO-8859-1:生成名为en_US的locale,采用ISO-8859-1字符集,并且把这个locale作为英文_美国locale类的默认值,其实它和en_US.ISO-8859-1/ISO-8859-1没有任何区别。 

en_US.UTF-8/UTF-8:生成名为en_US.UTF-8的locale,采用UTF-8字符集。 

zh_CN/GB18030:生成名为zh_CN的locale,采用GB18030字符集,并且把这个locale作为中文_中国locale类的默认值,其实它和zh_CN.GB18030/GB18030没有任何区别。 

zh_CN.GBK/GBK:生成名为zh_CN.GBK的locale,采用GBK字符集。 zh_CN.GB2312/GB2312:生成名为zh_CN.GB2312的locale,采用GB2312字符集。 zh_CN.UTF-8/UTF-8:生成名为zh_CN.UTF-8的locale,采用UTF-8字符集。 

关于默认locale,默认locale可以简写成en_US或者zh_CN的形式,只是为了表达简单而已没有特别的意义。 

Gentoo在locale定义的时候掩盖了一些东西,也就是locale的生成工具:localedef。 在编译完glibc之后你可以用这个localedef 再补充一些locale,就会更加理解locale了。具体的可以看 localedef 的manpage。 

$localedef -f 字符集 -i locale定义文件 生成的locale的名称 例如 $localedef -f UTF-8 -i zh_CN zh_CN.UTF-8 

上面的定义方法和在locales.build中设定zh_CN.UTF-8/UTF-8的结果是一样一样的。 

六、locale的五脏六腑 

刚刚生成了几个locale,但是为了让它们生效,必须告诉Linux系统使用那(几)个locale。这就需要对locale的内部机制有一点点的了解。在前面我已经提到过,locale把按照所涉及到的文化传统的各个方面分成12个大类,这12个大类分别是: 1、语言符号及其分类(LC_CTYPE) 2、数字(LC_NUMERIC) 3、比较和排序习惯(LC_COLLATE) 4、时间显示格式(LC_TIME) 5、货币单位(LC_MONETARY) 6、信息主要是提示信息,错误信息, 状态信息, 标题, 标签, 按钮和菜单等(LC_MESSAGES) 7、姓名书写方式(LC_NAME) 8、地址书写方式(LC_ADDRESS) 9、电话号码书写方式(LC_TELEPHONE) 10、度量衡表达方式(LC_MEASUREMENT) 11、默认纸张尺寸大小(LC_PAPER) 12、对locale自身包含信息的概述(LC_IDENTIFICATION)。 

其中,与中文输入关系最密切的就是 LC_CTYPE, LC_CTYPE 规定了系统内有效的字符以及这些字符的分类,诸如什么是大写字母,小写字母,大小写转换,标点符号、可打印字符和其他的字符属性等方面。而locale定义zh_CN中最最重要的一项就是定义了汉字(Class “hanzi”)这一个大类,当然也是用Unicode描述的,这就让中文字符在Linux系统中成为合法的有效字符,而且不论它们是用什么字符集编码的。 

LC_CTYPE % This is a copy of the "i18n" LC_CTYPE with the following modifications: - Additional classes: hanzi 

copy "i18n" 

class "hanzi"; / % ..;/ ..;/ ;;;;;;;;/ ;;;;;;;;/ ;;;; END LC_CTYPE 

在en_US的locale定义中,并没有定义汉字,所以汉字不是有效字符。所以如果要输入中文必须使用支持中文的locale,也就是zh_XX,如zh_CN,zh_TW,zh_HK等等。 

另外非常重要的一点就是这些分类是彼此独立的,也就是说LC_CTYPE,LC_COLLATE和 LC_MESSAGES等等分类彼此之间是独立的,可以根据用户的需要设定成不同的值。这一点对很多用户是有利的,甚至是必须的。例如,我就需要一个能够输入中文的英文环境,所以我可以把LC_CTYPE设定成zh_CN.GB18030,而其他所有的项都是en_US.UTF-8。 

七、怎样设定locale呢? 

设定locale就是设定12大类的locale分类属性,即 12个LC_*。除了这12个变量可以设定以外,为了简便起见,还有两个变量:LC_ALL和LANG。它们之间有一个优先级的关系: LC_ALL>LC_*>LANG 可以这么说,LC_ALL是最上级设定或者强制设定,而LANG是默认设定值。 1、如果你设定了LC_ALL=zh_CN.UTF-8,那么不管LC_*和LANG设定成什么值,它们都会被强制服从LC_ALL的设定,成为 zh_CN.UTF-8。 2、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_*=en_US.UTF-8,并且没有设定LC_ALL的话,那么系统的locale设定以LC_*=en_US.UTF-8。 3、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_*,和LC_ALL均未设定的话,系统会将LC_*设定成默认值,也就是LANG的值 zh_CN.UTF-8 。 4、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_CTYPE=en_US.UTF-8,其他的LC_*,和LC_ALL均未设定的话,那么系统的locale设定将是:LC_CTYPE=en_US.UTF-8,其余的 LC_COLLATE,LC_MESSAGES等等均会采用默认值,也就是LANG的值,也就是LC_COLLATE=LC_MESSAGES=……= LC_PAPER=LANG=zh_CN.UTF-8。 

所以,locale是这样设定的: 1、如果你需要一个纯中文的系统的话,设定LC_ALL= zh_CN.XXXX,或者LANG= zh_CN.XXXX都可以,当然你可以两个都设定,但正如上面所讲,LC_ALL的值将覆盖所有其他的locale设定,不要作无用功。 2、如果你只想要一个可以输入中文的环境,而保持菜单、标题,系统信息等等为英文界面,那么只需要设定LC_CTYPE=zh_CN.XXXX,LANG= en_US.XXXX就可以了。这样LC_CTYPE=zh_CN.XXXX,而LC_COLLATE=LC_MESSAGES=……= LC_PAPER=LANG=en_US.XXXX。 3、假如你高兴的话,可以把12个LC_*一一设定成你需要的值,打造一个古灵精怪的系统: LC_CTYPE=zh_CN.GBK/GBK(使用中文编码内码GBK字符集); LC_NUMERIC=en_GB.ISO-8859-1(使用大不列颠的数字系统) LC_MEASUREMEN=de_DE@euro.ISO-8859-15(德国的度量衡使用ISO-8859-15字符集) 罗马的地址书写方式,美国的纸张设定……。估计没人这么干吧。 4、假如你什么也不做的话,也就是LC_ALL,LANG和LC_*均不指定特定值的话,系统将采用POSIX作为lcoale,也就是C locale。
posted @ 2008-04-15 17:53 floerggyy 阅读(617) 评论(0) 编辑
 

2008年4月5日

C语言宏定义总结
转自:http://topcool99.ycool.com/post.1797687.html

宏定义了一个代表特定内容的标识符。
 预处理过程会把源代码中出现的宏标识符替换成宏定义时的值。
 宏最常见的用法是定义代表某个值的全局符号。
 宏的第二种用法是定义带参数的宏,这样的宏可以象函数一样被调用,但它是在调用语句处展开宏,并用调用时的实际参数来代替定义中的形式参数。
 
  1.#define指令
    #define MAX_NUM 10
    int array[MAX_NUM];
    for(i=0;i<MAX_NUM;i++)  /*……*/
 #define VERSION "Version 1.0 Copyright(c) 2003"
  2.带参数的#define指令
   #define IS_EVEN(n)   ((n)%2==0)
   #define MAX(x,y)     ((x)>(y) ? (x) :(y))
    #define Cube(x) (x)*(x)*(x)
    可以是任何数字表达式甚至函数调用来代替参数x。
  3.#运算符
    #的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号。例如:
        #define _STR(s)     #s
        #define WARN_IF(EXP)    \
        do{ if (EXP)    \
            fprintf(stderr, "Warning: " #EXP "\n"); }   \
        while(0)

        那么实际使用中会出现下面所示的替换过程:
        WARN_IF (divider == 0);

     被替换为

        do
     {
            if (divider == 0)
          fprintf(stderr, "Warning" "divider == 0" "\n");
        } while(0);
 这样每次divider(除数)为0的时候便会在标准错误流上输出一个提示信息。
 
 再例如下面的例子:
     #define  FILL(a)   {a, #a}

     enum IDD{OPEN, CLOSE};
     typedef struct MSG{
        IDD id;
        const char * msg;
     }MSG;

     MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
     相当于:
       MSG _msg[] = {{OPEN, "OPEN"},
                     {CLOSE, "CLOSE"}}; 

  4.##运算符
    ##运算符用于把参数连接到一起。
 预处理程序把出现在##两侧的参数合并成一个符号。
 看下面的例子:

            #define NUM(a,b,c) a##b##c
            #define STR(a,b,c) a##b##c

            main()
            {
                printf("%d\n",NUM(1,2,3));
                printf("%s\n",STR("aa","bb","cc"));
            }

        最后程序的输出为:
                 123
                 aabbcc
 再看下面的例子:
 struct command
    {
     char * name;
     void (*function) (void);
    };

    #define COMMAND(NAME) { NAME, NAME ## _command }

   // 然后你就用一些预先定义好的命令来方便的初始化一个command结构的数组了:

    struct command commands[] = {
     COMMAND(quit),
     COMMAND(help),
     ...
    }

    COMMAND宏在这里充当一个代码生成器的作用,这样可以在一定程度上减少代码密度,间接地也可以减少不留心所造成的错误。我们还可以n个##符号连接 n+1个Token。比如:
    #define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##d

    typedef struct _record_type LINK_MULTIPLE(name,company,position,salary);
    // 这里这个语句将展开为:
    // typedef struct _record_type name_company_position_salary;
  5.特殊的宏
    #error指令将使编译器显示一条错误信息,然后停止编译。
    #line指令可以改变编译器用来指出警告和错误信息的文件号和行号。
    #pragma指令没有正式的定义。编译器可以自定义其用途。典型的用法是禁止或允许某些烦人的警告信息。
 ...在C宏中称为Variadic Macro,也就是变参宏。

  Compiled on Dec 23 1996 at 22:18:48

 6.预定义宏
  __LINE__   被编译的文件的行数
  __FILE__   被编译的文件的名字
  __DATE__   编译的日期(格式"Mmm dd yyyy")
  __TIME__   编译的时间(格式"hh:mm:ss")
  __STDC__   如果编译器接受标准C,那么值为1

  printf("Compiled on %s at %s\n", __DATE__, __TIME__);

  每次程序开始执行,程序都会显示,用于确认版本:
    Compiled on Dec 23 1996 at 22:18:48
    下面的宏可以帮助我们查明错误的根源:

    #define CHECK_ZERO(divisor)  \
       if (divisor == 0)  \
       printf("*** Attempt to divide by zero on line %d  "  \
       "of file %s  ***\n",__LINE__, __FILE__)

     CHECK_ZERO宏应该在除法运算前被调用:
        CHECK_ZERO(j);k = i / j;
    如果j是0,会显示出如下形式的信息:
    *** Attempt to divide by zero on line 9 of file FOO.c ***
    通用的、用于错误检测的宏——assert宏;

  7.注意
    宏名和参数的括号间不能有空格;
 宏替换只作替换,不做计算,不做表达式求解;
 函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存;
 函数只有一个返回值,利用宏则可以设法得到多个值;
 宏展开使源程序变长,函数调用不会;
 宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值);
 使用条件编译可以使目标程序变小,运行时间变短;
 预编译使问题或算法的解决方案增多,有助于我们选择合适的解决方案。

posted @ 2008-04-05 18:35 floerggyy 阅读(1531) 评论(0) 编辑
 
原码、反码、补码
转自:http://homey123.ycool.com/post.2674427.html

补码的设计目的是
:

⑴使符号位能与有效值部分一起参加运算,从而简化运算规则.
⑵使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计
 1、原码、反码和补码的表示方法 
 (1)    原码:
            在数值前直接加一符号位的表示法。
            例如:      符号位 数值位
            [+7]原=   0    0000111 B
            [-7]原=   1    0000111 B

(3)补码的表示方法
1)模的概念:把一个计量单位称之为模或模数。例 如,时钟是以12进制进行计数循环的,即以12为模。在时钟上,时针加上(正拨)12的整数位或减去(反拨)12的整数位,时针的位置不变。14点钟在舍 去模12后,成为(下午)2点钟(14=14-12=2)。从0点出发逆时针拨10格即减去10小时,也可看成从0点出发顺时针拨2格(加上2小时),即 2点(0-10=-10=-10+12=2)。因此,在模12的前提下,-10可映射为+2。由此可见,对于一个模数为12的循环系统来说,加2和减10 的效果是一样的;因此,在以12为模的系统中,凡是减10的运算都可以用加2来代替,这就把减法问题转化成加法问题了(注:计算机的硬件结构中只有加法 器,所以大部分的运算都必须最终转换为加法)。10和2对模12而言互为补数。
同理,计算机的运算部件与寄存器都有一定字长的限制(假设字长为8),因此它的运算也是一种模运算。当计数器计满8位也就是256个数后会产生溢出,又从头开始计数。产生溢出的量就是计数器的模,显然,8位二进制数,它的模数为28=256。在计算中,两个互补的数称为“补码”。
 
2)补码的表示:
    正数:正数的补码和原码相同。
    负数         负数:负数的补码则是符号位为“1”,数值部分按位取反后再在末位(最低位)加1。也就是“反码+1”。
例如:       符号位 数值位
      [+7]补=   0   0000111 B
      [-7 ]补=   1   1111001 B
补码在微型机中是一种重要的编码形式,请注意:
a.             采用补码后,可以方便地将减法运算转化成加法运算,运算过程得到简化。正数的补码即是它所表示的数的真值,而负数的补码的数值部份却不是它所表示的数的真值。采用补码进行运算,所得结果仍为补码。
b.            与原码、反码不同,数值0的补码只有一个,即       [0]补=00000000B。
c.             若字长为8位,则补码所表示的范围为-128~+127;进行补码运算时,应注意所得结果不应超过补码所能表示数的范围。
2.原码、反码和补码之间的转换
由于正数的原码、补码、反码表示方法均相同,不需转换。
在此,仅以负数情况分析。
(1)    已知原码,求补码。
例:已知某数X的原码为10110100B,试求X的补码和反码。
解:由[X]原=10110100B知,X为负数。求其反码时,符号位不变,数值部分按位求反;求其补码时,再在其反码的末位加1。
1 0 1 1 0 1 0 0   原码
 
1 1 0 0 1 0 1 1   反码,符号位不变,数值位取反
                     1   +1
1 1 0 0 1 1 0 0   补码
故:[X]补=11001100B,[X]反=11001011B。
(2)    已知补码,求原码。
分析:按照求负数补码的逆过程,数值部分应是最低位减1,然后取反。但是对二进制数来说,先减1后取反和先取反后加1得到的结果是一样的,故仍可采用取反加1 有方法。
例:已知某数X的补码11101110B,试求其原码。
解:由[X]补=11101110B知,X为负数。求其原码表示时,符号位不变,数值部分按位求反,再在末位加1。
1 1 1 0 1 1 1 0   补码
 
1 0 0 1 0 0 0 1   符号位不变,数值位取反
                     1   +1
1 0 0 1 0 0 1 0   原码
1.3.2 有符号数运算时的溢出问题
请大家来做两个题目:

两正数相加怎么变成了负数???
1)(+72)+(+98)=?

0 1 0 0 1 0 0 0 B    +72
     + 0 1 1 0 0 0 1 0 B    +98
        1 0 1 0 1 0 1 0 B    -42

两负数相加怎么会得出正数???
2)(-83)+(-80)=?

1 0 1 0 1 1 0 1 B    -83
     + 1 0 1 1 0 0 0 0 B    -80
        0 1 0 1 1 1 0 1 B    +93
  思考:这两个题目,按照正常的法则来运算,但结果显然不正确,这是怎么回事呢?
   答案:这是因为发生了溢出。
如果计算机的字长为n位,n位二进制数的最高位为符号位,其余n-1位为数值位,采用补码表示法时,可表示的数X的范围是   -2n-1≤X≤2n-1-1
当n=8时,可表示的有符号数的范围为-128~+127。两个有符号数进行加法运算时,如果运算结果超出可表示的有符号数的范围时,就会发生溢出,使计算结果出错。很显然,溢出只能出现在两个同符号数相加或两个异符号数相减的情况下。
对 于加法运算,如果次高位(数值部分最高位)形成进位加入最高位,而最高位(符号位)相加(包括次高位的进位)却没有进位输出时,或者反过来,次高位没有进 位加入最高位,但最高位却有进位输出时,都将发生溢出。因为这两种情况是:两个正数相加,结果超出了范围,形式上变成了负数;两负数相加,结果超出了范 围,形式上变成了正数。
而对于减法运算,当次高位不需从最高位借位,但最高位却需借位(正数减负数,差超出范围),或者反过来,次高位需从最高位借位,但最高位不需借位(负数减正数,差超出范围),也会出现溢出。
在 计算机中,数据是以补码的形式存储的,所以补码在c语言的教学中有比较重要的地位,而讲解补码必须涉及到原码、反码。本部分演示作何一个整数的原码、反 码、补码。过程与结果显示在列表框中,结果比较少,不必自动清除,而过程是相同的,没有必要清除。故需设清除各部分及清除全部的按钮。测试时注意最大、最 小正负数。用户使用时注意讲解不会溢出:当有一个数的反码的全部位是1才会溢出,那么它的原码是10000...,它不是负数,故不会溢出。

在n位的机器数中,最高位为符号位,该位为零表示为正,为一表示为负;其余n-1位为数值位,各位的值可为零或一。当真值为正时,原码、反码、补码数值位 完全相同;当真值为负时,原码的数值位保持原样,反码的数值位是原码数值位的各位取反,补码则是反码的最低位加一。注意符号位不变。

            注意:
               a. 数0的原码有两种形式:
                  [+0]原=00000000B    
                  [-0]原=10000000B
               b. 8位二进制原码的表示范围:-127~+127
 (2)反码:
         正数:正数的反码与原码相同。
         负数:负数的反码,符号位为“1”,数值部分按位取反。
         例如:     符号位 数值位
         [+7]反= 0   0000111 B
         [-7]反= 1   1111000 B
         注意:
            a. 数0的反码也有两种形式,即
               [+0]反=00000000B
               [- 0]反=11111111B
            b. 8位二进制反码的表示范围:-127~+127
posted @ 2008-04-05 18:30 floerggyy 阅读(632) 评论(0) 编辑
 

2008年4月1日

Endian的由来及big-edian 和little-endian

转载:http://www.eygle.com/digest/2007/01/whats_mean_endian.html

一、引子
  在各种计算机体系结构中,对于字节、字等的存储机制有所不同,因而引发了
计算机通信领域中一个很重要的问题,即通信双方交流的信息单元(比特、字节、
字、双字等等)应该以什么样的顺序进行传送。如果不达成一致的规则,通信双方
将无法进行正确的编/译码从而导致通信失败。目前在各种体系的计算机中通常采
用的字节存储机制主要有两种:
big-edian和little-endian。本文简要描述这两种存储机制的来历、特点和区别。
  
  为了叙述方便,下面先对本文中将要用到的两个术语做简单的定义。
  1、MSB
  MSB是Most Significant Bit/Byte的首字母缩写,通常译为最重要的位或者最
重要的字节。它通常用来表明在一个bit序列(如一个byte是8个bit组成的一个序
列)或者一个byte序列(如word是两个byte组成的一个序列)中对整个序列取值影
响最大的那个bit/byte。
  2、LSB
  LSB是Least Significant Bit/Byte的首字母缩写,通常译为最不重要的位或
者最不重要的字节。它通常用来表明在一个bit序列(如一个byte是8个bit组成的
一个序列)或者一个byte序列(如word是两个byte组成的一个序列)中对整个序
列取值影响最小的那个bit/byte。


二、endian的由来
  1、Definition
  endian: The ordering of bytes in a multi-byte number.
定义:在计算机系统体系结构中用来描述在多字节数中各个字节的存储顺序。


  2、Etymology
  The term comes from Swift's "Gulliver's Travels" via the famous paper
"On Holy Wars and a Plea for Peace" by Danny Cohen, USC/ISI IEN 137,
1980-04-01.
  The Lilliputians, being very small, had correspondingly small political
problems. The Big-Endian and Little-Endian parties debated over whether
soft-boiled eggs should be opened at the big end or the little end.[From:
Free On-Line Dictionary Of Computing or Jargon File]
  词源:据Jargon File记载,endian这个词来源于Jonathan
Swift在1726年写的讽刺小说 "Gulliver's Travels"(《格利佛游记》)。该小说
在描述Gulliver畅游小人国时碰到了如下的一个场景。在小人国里的小人因为非常
小(身高6英寸)所以总是碰到一些意想不到的问题。有一次因为对水煮蛋该从大的
一端(Big-End)剥开还是小的一端(Little-End)剥开的争论而引发了一场战争,
并形成了两支截然对立的队伍:支持从Big-End剥开的人Swift就称作Big-Endians
而支持从Little-End剥开的人就称作Little-Endians……(后缀ian表明的就是支持
某种观点的人:-)。Endian这个词由此而来。
  
  1980年,Danny Cohen在其著名的论文"On Holy Wars and a Plea for Peace"
中为了平息一场关于在消息中字节该以什么样的顺序进行传送的争论而引用了该词。
该文中,Cohen非常形象贴切地把支持从一个消息序列的MSB开始传送的那伙人叫做
Big-Endians,支持从LSB开始传送的相对应地叫做Little-Endians。此后Endian这
个词便随着这篇论文而被广为采用。


三、各种endian
  1、big-endian
  A computer architecture in which, within a given multi-byte numeric
representation, the most significant byte has the lowest address (the
word is stored "big-end-first").  
Most processors, including the IBM 370 family, the PDP-10, the
Motorola microprocessor families, and most of the various RISC designs
current in mid-1993, are big-endian. [From: Free On-Line Dictionary Of
Computing or Jargon File]
  big-endian:计算机体系结构中一种描述多字节存储顺序的术语,在这种机制
中最重要字节(MSB)存放在最低端的地址上。采用这种机制的处理器有IBM3700系
列、PDP-10、Mortolora微处理器系列和绝大多数的RISC处理器。


 


+----------+
| 0x34 |<-- 0x00000021
+----------+
| 0x12 |<-- 0x00000020
+----------+
图1:双字节数0x1234以big-endian的方式存在起始地址0x00000020中


  在Big-Endian中,对于bit序列中的序号编排方式如下(以双字节数0x8B8A为
例):
bit 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+----------------------------------------+
val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
+----------------------------------------+
^ 0x8B 0x8A ^
MSB LSB
图2:Big-Endian的bit序列编码方式


  注1:通常在TCP/IP协议栈所说的网络序(Network Order)就是遵循Big-Endian
规则。在TCP/IP网络通信中,通信双方把消息按照如图2的方式进行编码,然后按
从MSB(Bit0)到LSB的顺序在网络上传送。
  2、little-endian
   A computer architecture in which, within a given
16- or 32-bit word,bytes at lower addresses have lower significance (the
word is stored "little-end-first"). The PDP-11 and VAX families of
computers and Intel microprocessors and a lot of communications and
networking hardware are little-endian.
  The term is sometimes used to describe the ordering of units other
than bytes; most often, bits within a byte. [From: Free On-Line Dictionary
Of Computing or Jargon File]
  little-endian:计算机体系结构中一种描述多字节存储顺序的术语,在这种机
制中最不重要字节(LSB)存放在最低端的地址上。采用这种机制的处理器有PDP-11、
VAX、Intel系列微处理器和一些网络通信设备。该术语除了描述多字节存储顺序外
还常常用来描述一个字节中各个比特的排放次序。


+----------+
| 0x12 |<-- 0x00000021
+----------+
| 0x34 |<-- 0x00000020
+----------+
  图3:双字节数0x1234以little-endian的方式存在起始地址0x00000020中


  在Little-Endian中,对于bit序列中的序号编排和Big-Endian刚好相反,其方
式如下(以双字节数0x8B8A为例):


bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+-----------------------------------------+
val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
+-----------------------------------------+
^ 0x8B 0x8A ^
MSB LSB
图4:Little-Endian的bit序列编码方式


  注2:通常我们说的主机序(Host Order)就是遵循Little-Endian规则。所以
当两台主机之间要通过TCP/IP协议进行通信的时候就需要调用相应的函数进行主机
序(Little-Endian)和网络序(Big-Endian)的转换。
注3:正因为这两种机制对于同一bit序列的序号编排方式恰恰相反,所以《现
代英汉词典》中对MSB的翻译为“最高有效位”欠妥,故本文定义为“最重要的bit
/byte”。


  3、middle-endian:
   Neither big-endian nor little-endian. Used of
perverse byte orders such as 3-4-1-2 or 2-1-4-3, occasionally found in
the packed decimal formats of some minicomputer manufacturers.[From:
Free On-Line Dictionary Of Computing or Jargon File]
  middle-endian:除了big-endian和little-endian之外的多字节存储顺序就是
middle-endian,比如以4个字节为例:象以3-4-1-2或者2-1-4-3这样的顺序存储的
就是middle-endian。这种存储顺序偶尔会在一些小型机体系中的十进制数的压缩格
式中出现。
四、收尾
  要详细解释这两种编码顺序已经超出本文所涉及的内容,如果你有兴趣的话可
以参考上面提及的Danny Cohen的论文("On Holy Wars and a Plea for Peace"),
该论文详细的描述了这两种编码顺序的历史、所基于的数学理论和各自拥护者争论
的焦点等知识,绝对可以大饱你打破沙锅问到底的内心需要。



什么是字节序?
  字节序,顾名思义字节的顺序,再多说两句就是大于一个字节类型的数据在内存中的存放顺序(一个字节的数据当然就无需谈顺 序的问题了)。其实大部分人在实际的开发中都很少会直接和字节序打交道。唯有在跨平台以及网络程序中字节序才是一个应该被考虑的问题。在所有的介绍字节序 的文章中都会提到字节序分为两类:Big-Endian和Little-Endian。引用标准的Big-Endian和Little-Endian的定 义如下:
a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
c) 网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序。
PS:有些文章中称低位字节为最低有效位,高位字节为最高有效位。
Big endian means that the most significant byte of any multibyte data field is stored at the lowest memory address, which is also the address of the larger field.
Little endian means that the least significant byte of any multibyte data field is stored at the lowest memory address, which is also the address of the larger field.

  什么是高/低地址端 什么是高/低字节
  首先我们要知道我们C程序映像中内存的空间布局情况:在《C专家编程》中或者《Unix环境高级编程》中有关于内存空间布局情况的说明,大致如下图:
----------------------- 最高内存地址 0xffffffff
| 栈底
.
. 栈
.
栈顶
-----------------------
|
|
\|/

NULL (空洞)

/|\
|
|
-----------------------
堆
-----------------------
未初始化的数据
----------------(统称数据段)
初始化的数据
-----------------------
正文段(代码段)
----------------------- 最低内存地址 0x00000000

以上图为例如果我们在栈上分配一个unsigned char buf[4],那么这个数组变量在栈上是如何布局的呢?看下图:
栈底 (高地址)
----------
buf[3]
buf[2]
buf[1]
buf[0]
----------
栈顶 (低地址)
现 在我们弄清了高/低地址,接着考虑高/低字节。如果我们有一个32位无符号整型0x12345678,那么高位是什么,低位又是什么呢?其实很简单。在十 进制中我们都说靠左边的是高位,靠右边的是低位,在其他进制也是如此。就拿 0x12345678来说,从高位到低位的字节依次是0x12、0x34、0x56和0x78。
高/低地址端和高/低字节都弄清了。我们再来回顾一下Big-Endian和Little-Endian的定义,并用图示说明两种字节序:
以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:


Big-Endian: 低地址存放高位,如下图:
栈底 (高地址)
---------------
buf[3] (0x78) -- 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) -- 高位
---------------
栈顶 (低地址)

Little-Endian: 低地址存放低位,如下图:
栈底 (高地址)
---------------
buf[3] (0x12) -- 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) -- 低位
--------------
栈顶 (低地址)

  现有的平台上Intel的X86采用的是Little-Endian,而像Sun的SPARC采用的就是Big-Endian。那么在跨平台或网络程序中如何实现字节序的转换呢?这个通过C语言的移位操作很容易实现,例如下面的宏: 

#if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)

#define htons(A)   (A)
#define htonl(A)    (A)
#define ntohs(A)   (A)
#define ntohl(A)    (A)

#elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)

#define htons(A)    ((((uint16)(A) & 0xff00) >> 8) | \
                              (((uint16)(A) & 0x00ff) << 8))
#define htonl(A)    ((((uint32)(A) & 0xff000000) >> 24) | \
                             (((uint32)(A) & 0x00ff0000) >> 8) | \
                             (((uint32)(A) & 0x0000ff00) << 8) | \
                             (((uint32)(A) & 0x000000ff) << 24))
#define ntohs htons
#define ntohl htohl

#else

#error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both."

#endif

 

  如何检查处理器是big-endian还是little-endian?
  由于联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性就可以轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。例如:
  int checkCPUendian(){
       union {
            unsigned int a;
            unsigned char b;            
       }c;
       c.a = 1;
       return (c.b == 1);       
  }  /*return 1 : little-endian, return 0:big-endian*/
  

posted @ 2008-04-01 19:14 floerggyy 阅读(913) 评论(0) 编辑
 

2008年3月30日

转载
摘要: 当一个可执行程序exe在执行过程中,程序文件无法删除,这是因为系统将每个正在运行的程序对应的硬盘文件映射到内存,即虚拟内存,要实现自删除,关键一点在程序退出前将程序从内存映射中解放出来,然后再调用文件操作函数删除程序文件!typedef int (WINAPI *PFClose)(LPVOID); OSVERSIONINFO os_info; os_info.dwOSVersionInfoSize...阅读全文
posted @ 2008-03-30 14:27 floerggyy 阅读(44) 评论(0) 编辑
 
zip文件格式
摘要: File: APPNOTE.TXT - .ZIP File Format SpecificationVersion: 6.3.2 Revised: September 28, 2007Copyright (c) 1989 - 2007 PKWARE Inc., All Rights Reserved.The use of certain technological aspects disclose...阅读全文
posted @ 2008-03-30 12:18 floerggyy 阅读(736) 评论(0) 编辑
 

2008年3月16日

C 语言 相关资源 精选
摘要: 语言标准及文档● ISO C99http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf● ANSI C Rationalehttp://www.quut.com/c/rat/title.htmlFAQ (常见问题)● comp.lang.c FAQhttp://c-faq.com/● C-FAQ 中文版http://c-faq-chn.s...阅读全文
posted @ 2008-03-16 16:41 floerggyy 阅读(69) 评论(0) 编辑
 

2008年3月4日

zlib usage
摘要: We often get questions about how the deflate() and inflate() functions should be used.Users wonder when they should provide more input, when they should use more output,what to do with a Z_BUF_ERROR, ...阅读全文
posted @ 2008-03-04 09:33 floerggyy 阅读(507) 评论(0) 编辑
 

2008年2月17日

一段垃圾的代码(附malloc,calloc和realloc使用小结)
摘要: malloc 每次在分配的时候,可能分配的空间比实际要求的多些
realloc 并不保证调整后的内存空间和原来的内存空间保持同一内存地址
阅读全文
posted @ 2008-02-17 20:00 floerggyy 阅读(1993) 评论(0) 编辑
 

2008年2月13日

Stdcall and DLL tools of MSVC and MinGW
摘要: Stdcall and DLL tools of MSVC and MinGWThe __stdcall calling convention has been there for a very longtime. While older calling conventions like __pascal fell intooblivion, __stdcall became the standa...阅读全文
posted @ 2008-02-13 11:59 floerggyy 阅读(752) 评论(0) 编辑
 
转载 关于gcc的dlltool和dllwrap工具
摘要: 转自:http://hi.baidu.com/oofy/blog/item/fa788a23ebdb4947ad34dede.html一直没搞明白过这两个东西,今天花工夫用了一下.总结如下:mingw中创建dll有两种方式,一是使用 gcc -shared ...二是使用dllwrap ...dllwrap是一组工具的调用.gcc -shared是直接生成.dllwrap相对更灵活一些.不过gcc...阅读全文
posted @ 2008-02-13 11:36 floerggyy 阅读(1606) 评论(0) 编辑
 

2007年12月17日

技术转载(鼠标点击X窗口关闭IE的同时清空session,最基本的就是处理用户重复登陆需要用到,我想这个的关键在于如何捕捉到关闭IE这个动作,之后再根据自身的需要使用session.invalidate()或者session.removeAttribute( "xxx "))
摘要: 鼠标点击X窗口关闭IE的同时清空session,最基本的就是处理用户重复登陆需要用到,我想这个的关键在于如何捕捉到关闭IE这个动作,之后再根据自身的需要使用session.invalidate()或者session.removeAttribute( "xxx ")都是水到渠成的事情。阅读全文
posted @ 2007-12-17 15:54 floerggyy 阅读(380) 评论(0) 编辑
 

2007年4月14日

深夜闲聊
摘要: floer 23:45:09呵呵,我最理想的工作是去写代码 sophiya 23:45:19你啊 floer 23:45:24对啊 sophiya 23:45:26写代码不可能写一辈子啊 floer 23:45:33为什么啊 sophiya 23:45:55写代码是最底层的工作,虽然最辛苦 sophiya 23:45:58不对吗 floer 23:46:26也不是,最有创造性的东东 sophi...阅读全文
posted @ 2007-04-14 00:07 floerggyy 阅读(89) 评论(0) 编辑
 

2007年3月22日

揩夜床
摘要: 第一次来广州出差,住在广州中央海酒店。第一天晚上突然有人按门玲,领导去开的房门。问曰:“做什么的?”,领导说是问要不要加床。第二天晚上,又有人来按门玲,我去开的门。又是问要不要揩夜床,答到,不用。心里还在想,像这种准四星的酒店居然每晚有人来打扰。第三天,又是有人来问,我生气的答道:不用,以后不要再来打扰了。第四晚,在朋友的房间里玩,有人按门玲,我去开门,结果还是问,要不要揩夜床。终于不耐烦了,骂道...阅读全文
posted @ 2007-03-22 23:22 floerggyy 阅读(188) 评论(0) 编辑
 

2007年3月4日

见雨生财
摘要: 几个朋友说我比较幸运,2号到北京3号就下点小雨,今天又下一天的中雨。在外面跑了一天被淋的都快不行了。见雨生财!!!希望如此阅读全文
posted @ 2007-03-04 04:27 floerggyy 阅读(46) 评论(0) 编辑
 
thinkpad r60 9455试用不记
摘要: 仰慕小黑很久,这两年一直想小黑可惜没钱。前几天终于如偿所愿公司买了小黑,不再用那台“美国的神舟”了。以后就体验小黑了。虽然thinkpad早都被纳下lenovo旗下,但我依对它情有独钟。现在用的是小黑是R60 9455AR2比刚换下来的那台DELL的配置差了一小截。不过摸起来确实不一样,再加其“高科技”的东东让我弄了好久都没有玩转,也不太重2.2KG样子。简单说下试用感受吧,真的跟“美国的神舟”完...阅读全文
posted @ 2007-03-04 04:24 floerggyy 阅读(135) 评论(0) 编辑
 

2006年12月4日

为项目组发布一则招骋信息
摘要: 招聘人数:4人<br>工作地点:昆明 <br>岗位要求:<br>1)年龄25岁以上,35岁以下;学历:大专以上(含大专);<br>2)具有较强的计划、组织、协调能力和良好的沟通表达能力;<br>3)有1年以上软件项目开发经验(.net)或vc++;<br>4)具有较强的综合分析能力;<br&g...阅读全文
posted @ 2006-12-04 15:16 floerggyy 阅读(108) 评论(0) 编辑
 

2006年11月23日

深夜杂想
摘要: 窗外飞机起落的声音对我来说变得越来越自然了,好像是今夜是在这个公司的第有4个通宵了,敬业是我准则。都变成打杂了我,想静下来写几行代码都成问题了现在。项目时间太紧,压力太力、人手太少,辛苦了chocoboboy~辛苦了其他的兄弟们了,费心了我的领导们。。。此时只有这种感叹了。其实想法很多的,但或许都是有点理想,真正并不是那么顺利,或许再战两周就OVER了。想起上个月25号那几天拉着chocobobo...阅读全文
posted @ 2006-11-23 23:30 floerggyy 阅读(88) 评论(0) 编辑
 
仅列出标题  下一页