??xml version="1.0" encoding="utf-8" standalone="yes"?>
gcc and g++分别是gnu的c & c++~译?gcc/g++在执行编译工作的时候,d需??
1.预处?生成.i的文件[预处理器cpp]
2.预处理后的文g不{换成汇编语言,生成文g.s[~译器egcs]
3.有汇~变为目标代?机器代码)生成.o的文件[汇编器as]
4.q接目标代码,生成可执行程序[链接器ld]
[参数详解]
-x language filename
讑֮文g所使用的语a,使后~名无?对以后的多个有效.也就是根据约定C语言的后
~名称?c的,而C++的后~名是.C或?cpp,如果你很个性,军_你的C代码文g的后~
名是.pig 哈哈Q那你就要用q个参数,q个参数对他后面的文件名都v作用Q除非到?
下一个参数的使用?
可以使用的参数吗有下面的q些
`c', `objective-c', `c-header', `c++', `cpp-output', `assembler', and `a
ssembler-with-cpp'.
看到英文Q应该可以理解的?
例子用法:
gcc -x c hello.pig
-x none filename
x上一个选项Q也是让gccҎ(gu)文g名后~Q自动识别文件类?
例子用法:
gcc -x c hello.pig -x none hello2.c
-c
只激z预处理,~译,和汇~?也就是他只把E序做成obj文g
例子用法:
gcc -c hello.c
他将生成.o的obj文g
-S
只激z预处理和编译,是指把文g~译成ؓ(f)汇编代码?
例子用法
gcc -S hello.c
他将生成.s的汇~代码,你可以用文本~辑器察?
-E
只激z预处理,q个不生成文?你需要把它重定向C个输出文仉?
例子用法:
gcc -E hello.c > pianoapan.txt
gcc -E hello.c | more
慢慢看吧,一个hello word 也要与处理成800行的代码
-o
制定目标名称,~省的时?gcc ~译出来的文件是a.out,很难?如果你和我有同感
Q改掉它,哈哈
例子用法
gcc -o hello.exe hello.c (?windows用习(fn)惯了)
gcc -o hello.asm -S hello.c
-pipe
使用道代替~译中(f)时文?在用非gnu汇编工具的时?可能有些问题
gcc -pipe -o hello.exe hello.c
-ansi
关闭gnu c中与ansi c不兼容的Ҏ(gu)?Ȁzansi c的专有特?包括止一些asm inl
ine typeof关键?以及(qing)UNIX,vax{预处理?
-fno-asm
此选项实现ansi选项的功能的一部分Q它止asm,inline和typeof用作关键字?
-fno-strict-prototype
只对g++起作?使用q个选项,g++对不带参数的函?都认为是没有昑ּ的对参数
的个数和cd说明,而不是没有参?
而gcc无论是否使用q个参数,都将Ҏ(gu)有带参数的函?认ؓ(f)城没有显式说明的cd
-fthis-is-varialble
是向传lc++看齐,可以使用this当一般变量?
-fcond-mismatch
允许条g表达式的W二和第三参数类型不匚w,表达式的值将为voidcd
-funsigned-char
-fno-signed-char
-fsigned-char
-fno-unsigned-char
q四个参数是对charcdq行讄,军_charcd讄成unsigned char(前两个参
?或?signed char(后两个参?
-include file
包含某个代码,单来?是便以某个文g,需要另一个文件的时?可以用它设
?功能q当于在代码中使用#include<filename>
例子用法:
gcc hello.c -include /root/pianopan.h
-imacros file
file文g的宏,扩展到gcc/g++的输入文?宏定义本wƈ不出现在输入文g?
-Dmacro
相当于C语言中的#define macro
-Dmacro=defn
相当于C语言中的#define macro=defn
-Umacro
相当于C语言中的#undef macro
-undef
取消对Q何非标准宏的定义
-Idir
在你是用#include"file"的时?gcc/g++?x)先在当前目录查找你所制定的头文g,?
果没有找?他回到缺省的头文件目录找,如果使用-I制定了目??
回先在你所制定的目录查?然后再按常规的顺序去?
对于#include<file>,gcc/g++?x)?I制定的目录查?查找不到,然后到pȝ的缺
省的头文件目录查?
-I-
是取消前一个参数的功能,所以一般在-Idir之后使用
-idirafter dir
?I的目录里面查扑֤?讲到q个目录里面查找.
-iprefix prefix
-iwithprefix dir
一般一起??I的目录查扑֤??x)到prefix+dir下查?
-nostdinc
使编译器不再pȝ~省的头文g目录里面扑֤文g,一般和-I联合使用,明确限定?
文g的位|?
-nostdin C++
规定不在g++指定的标准\l中搜烦,但仍在其他\径中搜烦,.此选项在创libg++?
使用
-C
在预处理的时?不删除注释信?一般和-E使用,有时候分析程序,用这个很方便?
-M
生成文g兌的信息。包含目标文件所依赖的所有源代码你可以用gcc -M hello.c
来测试一下,很简单?
-MM
和上面的那个一P但是它将忽略?include<file>造成的依赖关pR?
-MD
?M相同Q但是输出将导入?d的文仉?
-MMD
?MM相同Q但是输出将导入?d的文仉?
-Wa,option
此选项传递optionl汇~程?如果option中间有逗号,将option分成多个选项,?
后传递给?x)汇~程?
-Wl.option
此选项传递optionl连接程?如果option中间有逗号,将option分成多个选项,?
后传递给?x)连接程?
-llibrary
制定~译的时候用的?
例子用法
gcc -lcurses hello.c
使用ncurses库编译程?
-Ldir
制定~译的时候,搜烦库的路径。比如你自己的库Q可以用它制定目录,不然
~译器将只在标准库的目录找。这个dir是目录的名U?
-O0
-O1
-O2
-O3
~译器的优化选项?个别,-O0表示没有优化,-O1为缺省|-O3优化U别最高
-g
只是~译器,在编译的时候,产生调试信息?
-gstabs
此选项以stabs格式声称调试信息,但是不包括gdb调试信息.
-gstabs+
此选项以stabs格式声称调试信息,q且包含仅供gdb使用的额外调试信?
-ggdb
此选项尽可能的生成gdb的可以用的调试信息.
-static
此选项禁止用动态库Q所以,~译出来的东西,一般都很大Q也不需要什?
动态连接库Q就可以q行.
-share
此选项尽量用动态库Q所以生成文件比较小Q但是需要系l由动态库.
-traditional
试图让编译器支持传统的C语言Ҏ(gu)?
[参考资料]
-Linux/UNIX高~程
中科U旗软g技术有限公司编?清华大学出版Cև?
-Gcc man page
[ChangeLog]
-2002-08-10
ver 0.1 发布最初的文档
-2002-08-11
ver 0.11 修改文档格式
-2002-08-12
ver 0.12 加入了对静态库Q动态库的参?
-2002-08-16
ver 0.16 增加了gcc~译?个阶D늚命o(h)
q行 gcc/egcs
**********q行 gcc/egcs***********************
GCC ?GNU ?C ?C++ ~译器。实际上QGCC 能够~译三种语言QC、C++ ?O
bject CQC 语言的一U面向对象扩展)。利?gcc 命o(h)可同时编译ƈq接 C ?C++
源程序?
如果你有两个或少数几?C 源文Ӟ也可以方便地利用 GCC ~译、连接ƈ生成?
执行文g。例如,假设你有两个源文?main.c ?factorial.c 两个源文Ӟ现在要编
译生成一个计阶乘的E序?
代码:
-----------------------
清单 factorial.c
-----------------------
int factorial (int n)
{
if (n <= 1)
return 1;
else
return factorial (n - 1) * n;
}
-----------------------
清单 main.c
-----------------------
#include <stdio.h>
#include <unistd.h>
int factorial (int n);
int main (int argc, char **argv)
{
int n;
if (argc < 2)
{
printf ("Usage: %s n\n", argv [0]);
return -1;
}
else
{
n = atoi (argv[1]);
printf ("Factorial of %d is %d.\n", n, factorial (n));
}
return 0;
}
-----------------------
利用如下的命令可~译生成可执行文Ӟq执行程序:(x)
$ gcc -o factorial main.c factorial.c
$ ./factorial 5
Factorial of 5 is 120.
GCC 可同时用来编?C E序?C++ E序。一般来_(d)C ~译器通过源文件的后缀
名来判断?C E序q是 C++ E序。在 Linux 中,C 源文件的后缀名ؓ(f) .cQ?C++ ?
文g的后~名ؓ(f) .C ?.cpp。但是,gcc 命o(h)只能~译 C++ 源文Ӟ而不能自动和 C
++ E序使用的库q接。因此,通常使用 g++ 命o(h)来完?C++ E序的编译和q接Q该E?
序会(x)自动调用 gcc 实现~译。假设我们有一个如下的 C++ 源文Ӟhello.CQ:(x)
#include <iostream>
void main (void)
{
cout << "Hello, world!" << endl;
}
则可以如下调?g++ 命o(h)~译、连接ƈ生成可执行文Ӟ(x)
$ g++ -o hello hello.C
$ ./hello
Hello, world!
**********************gcc/egcs 的主要选项*********
gcc 命o(h)的常用选项
选项 解释
-ansi 只支?ANSI 标准?C 语法。这一选项禁?GNU C 的某些特Ԍ
例如 asm ?typeof 关键词?
-c 只编译ƈ生成目标文g?
-DMACRO 以字W串?”定?MACRO 宏?
-DMACRO=DEFN 以字W串“DEFN”定?MACRO 宏?
-E 只运?C 预编译器?
-g 生成调试信息。GNU 调试器可利用该信息?
-IDIRECTORY 指定额外的头文g搜烦路径DIRECTORY?
-LDIRECTORY 指定额外的函数库搜烦路径DIRECTORY?
-lLIBRARY q接时搜索指定的函数库LIBRARY?
-m486 针对 486 q行代码优化?
-o FILE 生成指定的输出文件。用在生成可执行文g时?
-O0 不进行优化处理?
-O ?-O1 优化生成代码?
-O2 q一步优化?
-O3 ?-O2 更进一步优化,包括 inline 函数?
-shared 生成׃n目标文g。通常用在建立׃n库时?
-static 止使用׃nq接?
-UMACRO 取消?MACRO 宏的定义?
-w 不生成Q何警告信息?
-Wall 生成所有警告信息?
]]>
AuthorQsungo (TW@Javaworld) 文章原文Q?A >http://www.javaworld.com.tw/jute/post/view?bid=10&id=53262&sty=1&tpg=1&age=0
Eclipse除了可以開發Java之外Q還支援了許多語aQ現在先介紹
C、C++的開發環境設定,以後有機會再介紹其它的。Enjoy itQ?
OSQWindows XP Professional SP1
使用版本QEclipse 2.1.2
一.首先要下載CDTQEclipse 2.1.2使用者,請下載這項Q?
CDT 1.2 Full for Windows R2.1.1 1.2.0 GA - Full - Windows?
Eclipse 2.1.3使用者請下載QCDT 1.2.1?
Eclipse 3.0 M7使用者請下載QCDT 2.0 M7?
Eclipse 3.0 M8使用者請下載QCDT 2.0 M8?
Eclipse 3.0 M9使用者請下載QCDT 2.0 M9?
下載E址Q?/FONT>http://www.eclipse.org/cdt/
安裝Q將解壓^後的features、plugins整個資料夾複製到Eclipse安裝資料
裡,重新開啟Eclipse卛_?
?下載可在Windows上用的GNU C、C++R譯器,這裡要下載的是:(x)MinGW?
Download頁面很長的一Ԍ請選擇這個版本:(x)
MinGW bin MinGW-3.1.0-1.exe 14863 kb Sep 15, 2003 11:14
下載E址Q?/FONT>http://www.mingw.org/download.shtml
安裝Q安裝目錄選C槽,然後狂點下一?Next)p了。安裝完後\徑是?
?>C:\MinGW?
?先在Command Line模式下測試編譯與埯。先C:\MinGW\bin底下?
mingw32-make.exe更名為make.exeQ因為待會在Eclipse使用時它預設
會抓pȝ(dng)裡make這個檔名而不是mingw32-make?
(a:(x)如果不更名或是還有其他makeE式時,也可以在E後的Eclipsea定
中,在make targets view的地方,新增一個task時,build command 取消
use default , 使用 mingw32-makeQ或在project properties->make project ->
make 改為 mingw32-make ) -- ?B> snpshu 補充?/FONT>
在環境變數裡加入下列a定Q?
PATH Q?C:\MinGW\bin; (如果pȝ(dng)已經有裝其它C/C++R譯器,請把C:\MinGW\bin加在最前面?
LIBRARY_PATH QC:\MinGW\lib
C_INCLUDE_PATH QC:\MinGW\include
CPLUS_INCLUDE_PATH QC:\MinGW\include\c++\3.2.3;C:\MinGW\include\c++\3.2.3\mingw32;
C:\MinGW\include\c++\3.2.3\backward;C:\MinGW\include
先用文字編輯器R寫測試用的原始檔,檔名Qmain.cpp?
1
2
3
4
5
6
7
8#include <iostream>
using namespace std;
int main(void) {
cout << "Can You Feel My WorldQ? ;
return 0;
}
在Command Line下編譯指令:(x)
1
C:\g++ main.cpp -O3 -o hello
(O3的O是英文大??)
R譯成功後:(x)便會產生hello.exe的執行檔?
埯畫面如下Q?
1
2
3
4
5
6
7
8
9
10Microsoft Windows XP [版本 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
C:\Documents and Settings\Sungo>cd\
C:\>g++ main.cpp -O3 -o hello
C:\>hello
Can You Feel My WorldQ?
C:\>
a:(x)-O3 旗標表示採最高級R譯最?jng)_Q編譯速度最慢,但產生的埯?
檔案會最,埯速度會最快;-o 旗標表示編譯完?.exe重新更名?
◎步驟一.開啟Eclipse後,首先先開啟C/C++用視景?
Windows->Open Perspective->C/C++ Development
◎步驟二.建立一個C++用的案?
File-New->Project->C++->Standard Make C++ Project
(接下來的步驟跟徏立一般的Java案一樣,皆採預設卛_)
◎步驟三.把我們剛剛寫的main.cpp import進來Q加到專案裡?
File->Import->File System->瀏覽C:\main.cpp
◎步驟四.建立一個makefile?
File->New->FileQ檔案名E填Qmakefile?不需打副檔名)
makefile內容如下Q?
1
2all:
g++ main.cpp -g -o run
注意Qmakefile^排要以Tab鍵作^排Q不能以I格4作縮排,
否則Build會有問題?/FONT>
◎步驟五.a定Make Targets?
Windows-Show View->Make Targets
在Make Targets視窗裡按滑鼠右鍵QAdd Build Target
Qname打:(x)R譯。Build Target打:(x)all?
◎步驟六.R譯?
在剛剛徏立的Make Targets "R譯" 上點滑鼠2下,x開始R譯Q?
此時我們可以發現hello.exe已經產生在我們專案下了。可在底?
C-Build視窗看到以下輸出i果Q?
1
2make -k all
g++ main.cpp -g -o run
◎步驟七. *.exe埯前設定。因為在Windows下RunQ所以要先作個設?
Q請開啟Project->Properties->C/C++ Make Project->Binary Parser頁面?
Binary Parser下拉式選單,ELF ParserҎ(gu)PE Windows Parser?
◎步驟八.埯?
Run->Run as->C Local Application?
在底下Consloe視窗看到hello.exe的執行結果?
a:(x)當原始檔有修改,要重新編譯時Q只要滑鼠雙擊我們在步驟?
所建立的Make Targets "R譯"Q即可Rebuilding?
]]>
1. 用预处理指o(h)#define 声明一个常敎ͼ用以表明1q中有多秒Q忽略闰q问题)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
我在q想看到几g事情Q?
1). #define 语法的基本知识(例如Q不能以分号l束Q括L(fng)使用Q等{)
2). 懂得预处理器ؓ(f)你计常数表辑ּ的|因此Q直接写Z是如何计一q中有多秒而不是计出实际的|是更清晰而没有代L(fng)?
3). 意识到这个表辑ּ一?6位机的整型数溢出-因此要用到长整型W号L,告诉~译器这个常数是的长整型数?
4). 如果你在你的表达式中用到ULQ表C无W号长整型)Q那么你有了一个好的v炏V记住,W一印象很重要?BR>
2. 写一个“标准”宏MINQ这个宏输入两个参数q返回较?yu)的一个?BR>
#define MIN(A,B) ((A) <= (B) (A) : (B))
q个试是ؓ(f)下面的目的而设的:(x)
1). 标识#define在宏中应用的基本知识。这是很重要的,因ؓ(f)直到嵌入(inline)操作W变为标准C的一部分Q宏是方便生嵌入代码的唯一Ҏ(gu)Q对于嵌入式pȝ来说Qؓ(f)了能辑ֈ要求的性能Q嵌入代码经常是必须的方法?
2). 三重条g操作W的知识。这个操作符存在C语言中的原因是它使得~译器能产生比if-then-else更优化的代码Q了解这个用法是很重要的?
3). 懂得在宏中小心地把参数用括号括v?
4). 我也用这个问题开始讨论宏的副作用Q例如:(x)当你写下面的代码时会(x)发生什么事Q?
least = MIN(*p++, b);
3. 预处理器标识#error的目的是什么?
如果你不知道{案Q请看参考文?。这问题对区分一个正常的伙计和一个书呆子是很有用的。只有书呆子才会(x)读C语言课本的附录去扑և象这U?
问题的答案。当然如果你不是在找一个书呆子Q那么应试者最好希望自׃要知道答案?BR>
d@环(Infinite loopsQ?BR>
4. 嵌入式系l中l常要用到无限@环,你怎么L(fng)C~写d@环呢Q?BR>
q个问题用几个解x案。我首选的Ҏ(gu)是:(x)
while(1) { }
一些程序员更喜Ƣ如下方案:(x)
for(;;) { }
q个实现方式让我为难Q因个语法没有确切表辑ֈ底怎么回事。如果一个应试者给个作为方案,我将用这个作Z个机?x)去探究他们q样做的
基本原理。如果他们的基本{案是:(x)“我被教着q样做,但从没有惛_qؓ(f)什么。”这?x)给我留下一个坏印象?
W三个方案是?goto
Loop:
...
goto Loop;
应试者如l出上面的方案,q说明或者他是一个汇~语aE序员(q也许是好事Q或者他是一个想q入新领域的BASIC/FORTRANE序员?BR>
数据声明QData declarationsQ?
5. 用变量al出下面的定?
a) 一个整型数QAn integerQ?
b) 一个指向整型数的指针(A pointer to an integerQ?
c) 一个指向指针的的指针,它指向的指针是指向一个整型数QA pointer to a pointer to an integerQ?
d) 一个有10个整型数的数l(An array of 10 integersQ?
e) 一个有10个指针的数组Q该指针是指向一个整型数的(An array of 10 pointers to integersQ?
f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integersQ?
g) 一个指向函数的指针Q该函数有一个整型参数ƈq回一个整型数QA pointer to a function that takes an integer as an argument and returns an integerQ?
h) 一个有10个指针的数组Q该指针指向一个函敎ͼ该函数有一个整型参数ƈq回一个整型数Q?An array of ten pointers to functions that take an integer argument and return an integer Q?BR>
{案是:(x)
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
Zl常声称q里有几个问题是那种要翻一下书才能回答的问题,我同意这U说法。当我写q篇文章ӞZ定语法的正性,我的查了一下书?
但是当我被面试的时候,我期望被问到q个问题Q或者相q的问题Q。因为在被面试的q段旉里,我确定我知道q个问题的答案。应试者如果不知道
所有的{案Q或臛_大部分答案)Q那么也没有ؓ(f)q次面试做准备,如果该面试者没有ؓ(f)q次面试做准备,那么他又能ؓ(f)什么出准备呢?
Static
6. 关键字static的作用是什么?
q个单的问题很少有h能回{完全。在C语言中,关键字static有三个明昄作用Q?
1). 在函CQ一个被声明为静态的变量在这一函数被调用过E中l持其g变?
2). 在模块内Q但在函C外)Q一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量?
3). 在模块内Q一个被声明为静态的函数只可被这一模块内的其它函数调用。那是Q这个函数被限制在声明它的模块的本地范围内用?
大多数应试者能正确回答W一部分Q一部分能正回{第二部分,同是很少的h能懂得第三部分。这是一个应试者的严重的缺点,因ؓ(f)他显然不懂得本地化数据和代码范围的好处和重要性?BR>
Const
7Q关键字const是什么含意?
我只要一听到被面试者说Q“const意味着常数”,我就知道我正在和一个业余者打交道。去qDan Saks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:(x)Embedded Systems Programming)的每一位读者应该非常熟(zhn)const能做什么和不能做什?如果你从没有d那篇文章Q只要能说出const意味着“只诠Z就可以了。尽这个答案不是完全的{案Q但我接受它作ؓ(f)一个正的{案。(如果你想知道更详l的{案Q仔l读一下Saks的文章吧。)如果应试者能正确回答q个问题Q我问他一个附加的问题Q下面的声明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前两个的作用是一Pa是一个常整型数。第三个意味着a是一个指向常整型数的指针Q也是Q整型数是不可修改的Q但指针可以Q。第四个意思a是一个指向整型数的常指针Q也是_(d)指针指向的整型数是可以修改的Q但指针是不可修改的Q。最后一个意味着a是一个指向常整型数的常指针(也就是说Q指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答q些问题Q那么他q我留下了一个好印象。顺带提一句,也许你可能会(x)问,即不用关键字constQ也q是能很Ҏ(gu)写出功能正确的程序,那么我ؓ(f)什么还要如此看重关键字const呢?我也如下的几下理由:(x)
1). 关键字const的作用是为给M代码的h传达非常有用的信息,实际上,声明一个参Cؓ(f)帔R是ؓ(f)了告诉了用户q个参数的应用目的。如果你曾花很多旉清理其它人留下的垃圾Q你׃(x)很快学会(x)感谢q点多余的信息。(当然Q懂得用const的程序员很少?x)留下的垃圾让别人来清理的。)
2). 通过l优化器一些附加的信息Q用关键字const也许能生更紧凑的代码?
3). 合理C用关键字const可以使编译器很自然地保护那些不希望被改变的参敎ͼ防止其被无意的代码修攏V简而言之,q样可以减少bug的出现?BR>
Volatile
8. 关键字volatile有什么含?q给Z个不同的例子?BR>
一个定义ؓ(f)volatile的变量是说这变量可能?x)被意想不到地改变,q样Q编译器׃?x)去假设q个变量的g。精地说就是,优化器在用到q个变量时必Lơ都心地重新读取这个变量的|而不是用保存在寄存器里的备份。下面是volatile变量的几个例子:(x)
1). q行讑֤的硬件寄存器Q如Q状态寄存器Q?
2). 一个中断服务子E序中会(x)讉K到的非自动变?Non-automatic variables)
3). 多线E应用中被几个Q务共享的变量
回答不出q个问题的h是不?x)被雇䄦的。我认ؓ(f)q是区分CE序员和嵌入式系l程序员的最基本的问题。嵌入式pȝE序员经常同g、中断、RTOS{等打交道,所用这些都要求volatile变量。不懂得volatile内容会(x)带来N?
假设被面试者正地回答了这是问题(嗯,怀疑这否会(x)是这PQ我稍微深I一下,看一下这家伙是不是直正懂得volatile完全的重要性?
1). 一个参数既可以是constq可以是volatile吗?解释Z么?
2). 一个指针可以是volatile 吗?解释Z么?
3). 下面的函数有什么错误:(x)
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:(x)
1). 是的。一个例子是只读的状态寄存器。它是volatile因ؓ(f)它可能被意想不到地改变。它是const因ؓ(f)E序不应该试囑֎修改它?
2). 是的。尽这q不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时?
3). q段代码的有个恶作剧。这D代码的目的是用来返指针*ptr指向值的qxQ但是,׃*ptr指向一个volatile型参敎ͼ~译器将产生cM下面的代码:(x)
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
׃*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,q段代码可能q不是你所期望的^方|正确的代码如下:(x)
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
位操作(Bit manipulationQ?BR>
9. 嵌入式系lL要用户对变量或寄存器q行位操作。给定一个整型变量aQ写两段代码Q第一个设|a(chn)的bit 3Q第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变?BR>
对这个问题有三种基本的反?
1). 不知道如何下手。该被面者从没做qQ何嵌入式pȝ的工作?
2). 用bit fields。Bit fields是被扔到C语言死角的东西,它保证你的代码在不同~译器之间是不可UL的,同时也保证了的你的代码是不可重用的。我最q不q看到Infineon为其较复杂的通信芯片写的驱动E序Q它用到了bit fields因此完全Ҏ(gu)无用Q因为我的编译器用其它的方式来实现bit fields的。从道dԌ(x)永远不要让一个非嵌入式的家伙_实际硬件的辏V?
3). ?#defines ?bit masks 操作。这是一个有极高可移植性的Ҏ(gu)Q是应该被用到的Ҏ(gu)。最佳的解决Ҏ(gu)如下Q?
#define BIT3 (0x1<<3)
static int a;
void set_bit3(void)
{
a |= BIT3;
}
void clear_bit3(void)
{
a &= ~BIT3;
}
一些h喜欢|和清除D定义一个掩码同时定义一些说明常敎ͼq也是可以接受的。我希望看到几个要点Q说明常数、|=?amp;=~操作?BR>
讉K固定的内存位|(Accessing fixed memory locationsQ?
10. 嵌入式系l经常具有要求程序员去访问某特定的内存位|的特点。在某工E中Q要求设|一l对地址?x67a9的整型变量的gؓ(f)0xaa66。编译器是一个纯_的ANSI~译器。写代码d成这一d?BR>
q一问题?gu)试你是否知道?f)了访问一l对地址把一个整型数强制转换QtypecastQؓ(f)一指针是合法的。这一问题的实现方式随着个h风格不同而不同。典型的cM代码如下Q?
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa55;
一个较晦ӆ的方法是Q?
*(int * const)(0x67a9) = 0xaa55;
即你的品味更接q第二种Ҏ(gu)Q但我徏议你在面试时使用W一U方案?BR>
中断QInterruptsQ?
11. 中断是嵌入式pȝ中重要的l成部分Q这D了很多编译开发商提供一U扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字__interrupt。下面的代码׃用了__interrupt关键字去定义了一个中断服务子E序(ISR)Q请评论一下这D代码的?BR>
__interrupt double compute_area (double radius)
{
double area = PI * radius * radius;
printf(" Area = %f", area);
return area;
}
q个函数有太多的错误了,以至让h不知从何说v了:(x)
1). ISR 不能q回一个倹{如果你不懂q个Q那么你不会(x)被雇用的?
2). ISR 不能传递参数。如果你没有看到q一点,你被雇用的机?x)等同第一V?
3). 在许多的处理?~译器中QQ点一般都是不可重入的。有些处理器/~译器需要让额处的寄存器入栈Q有些处理器/~译器就是不允许在ISR中做点q算。此外,ISR应该是短而有效率的,在ISR中做点q算是不明智的?
4). 与第三点一脉相承,printf()l常有重入和性能上的问题。如果你丢掉了第三和W四点,我不?x)太为难你的。不用说Q如果你能得到后两点Q那么你的被雇用前景来光明了?BR>
代码例子QCode examplesQ?BR>12 . 下面的代码输出是什么,Z么?
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) puts("> 6") : puts("<= 6");
}
q个问题?gu)试你是否懂得C语言中的整数自动转换原则Q我发现有些开发者懂得极这些东ѝ不如何,q无W号整型问题的答案是输出是?gt;6”。原因是当表辑ּ中存在有W号cd和无W号cd时所有的操作数都自动转换为无W号cd?因此-20变成了一个非常大的正整数Q所以该表达式计出的结果大?。这一点对于应当频J用到无W号数据cd的嵌入式pȝ来说是丰帔R要的。如果你{错了这个问题,你也到了得不到q䆾工作的边~?BR>
13. 评h(hun)下面的代码片断:(x)
unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
/*1's complement of zero */
对于一个int型不?6位的处理器ؓ(f)_(d)上面的代码是不正的。应~写如下Q?BR>
unsigned int compzero = ~0;
q一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的l验里,好的嵌入式程序员非常准确地明白硬件的l节和它的局限,然而PC机程序往往把硬件作Z个无法避免的烦恼?
Cq个阶段Q应试者或者完全垂头气了或者信心满满志在必得。如果显然应试者不是很好,那么q个试在q里l束了。但如果昄应试者做得不错,那么我就扔出下面的追加问题,q些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提些问题,我希望更多看到应试者应付问题的Ҏ(gu)Q而不是答案。不如何,你就当是q个׃吧?BR>
动态内存分配(Dynamic memory allocationQ?BR>
14. 管不像非嵌入式计算机那么常见,嵌入式系l还是有从堆QheapQ中动态分配内存的q程的。那么嵌入式pȝ中,动态分配内存可能发生的问题是什么?
q里Q我期望应试者能提到内存片Q碎片收集的问题Q变量的持行旉{等。这个主题已l在ESP杂志中被q泛地讨了(主要?P.J. Plauger, 他的解释q远过我这里能提到的Q何解释)Q所有回q头看一下这些杂志吧Q让应试者进入一U虚假的安全感觉后,我拿么一个小节目Q下面的代码片段的输出是什么,Z么?
char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");
q是一个有的问题。最q在我的一个同事不l意?gl了函数mallocQ得C一个合法的指针之后Q我才想到这个问题。这是上面的代码,该代码的输出是“Got a valid pointer”。我用这个来开始讨L(fng)一问题Q看看被面试者是否想到库例程q样做是正确。得到正的{案固然重要Q但解决问题的方法和你做军_的基本原理更重要些?BR>
Typedef
15. Typedef 在C语言中频J用以声明一个已l存在的数据cd的同义字。也可以用预处理器做cM的事。例如,思考一下下面的例子Q?
#define dPS struct s *
typedef struct s * tPS;
以上两种情况的意N是要定义dPS ?tPS 作ؓ(f)一个指向结构s指针。哪U方法更好呢Q(如果有的话)Z么?
q是一个非常微妙的问题QQ何h{对q个问题Q正当的原因Q是应当被恭喜的。答案是Qtypedef更好。思考下面的例子Q?
dPS p1,p2;
tPS p3,p4;
W一个扩展ؓ(f)
struct s * p1, p2;
上面的代码定义p1Z个指向结构的指,p2Z个实际的l构Q这也许不是你想要的。第二个例子正确地定义了p3 和p4 两个指针?BR>
晦ӆ的语?BR>
16. C语言同意一些o(h)人震惊的l构,下面的结构是合法的吗Q如果是它做些什么?
int a = 5, b = 7, c;
c = a+++b;
q个问题做个测验的一个愉快的l尾。不你怸怿Q上面的例子是完全合乎语法的。问题是~译器如何处理它Q水q不高的~译作者实际上?x)争个问题,?gu)最处理原则Q编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:(x)
c = a++ + b;
因此, q段代码持行后a = 6, b = 7, c = 12?
如果你知道答案,或猜出正答案,做得好。如果你不知道答案,我也不把q个当作问题。我发现q个问题的最大好处是:q是一个关于代码编写风|代码的可L,代码的可修改性的好的话题
English Version |
![]() |
重要日期 报名开?/B> 11?1日星期一 入围?/B> 12?2日星期一 d?/B> 1?0日星期五 |
价?5万元?BR>高科技奖品 |
日期 | 旉 * | 状?/FONT> |
11?1日星期一 | 9:00 | 注册开?/FONT> |
12?2日星期一 | 9:00 | 注册l束 |
12?2日星期一 | 12:00 | 资格赛开?/FONT> |
12?3日星期二 | 12:00 | 资格赛结?/FONT> |
12?9日星期一 | 21:00 | W一?500名参赛?/FONT> |
12?2日星期四 | 21:00 | W二?250名参赛?/FONT> |
1?0日星期五 | 待定 | 冠军?50名参赛?/FONT> |
* 上述旉皆ؓ(f)北京旉。冠军赛日期有可能发生变化,h意届旉知?/FONT> |
参赛?/FONT> | 奖品 |
W??(׃h(hun)?0,000人民? | 一l高端个人编E工作站 |
W?至第4?(每位奖品价?0,000人民? | 一台笔记本?sh)脑Q?PDA手机Q?以及(qing)一ƑօC人随w听 |
W??0?每位奖品价?,000人民? | 一台数字相机,PDA手机Q?以及(qing)一ƑօC人随w听 |
W?1?0?每位奖品价?,000人民? | PDA手机Q?以及(qing)一ƑօC人随w听 |
W?1?0?(每位奖品价?,000人民? | 一ƑօC人随w听 |
I have noticed that some people seem to have problems with bitwise operators, so I decided to write this brief tutorial on how to use them.
Bits, what are they you may ask?
Well, simply put, bits are the individual ones and zeros that make up every thing we do with computers. All the data you use is stored in your computer using bits. A BYTE is made up of eight bits, a WORD is two BYTEs, or sixteen bits. And a DWORD is two WORDS, or thirty two bits.
0 1 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 1 1 1 0 1 0 0 0 1 1 1 1 0 0 0 || | | | || |+- bit 31 | | | bit 0 -+| | | | | | +-- BYTE 3 ---+--- BYTE 2 ---+--- BYTE 1 ---+-- BYTE 0 ---+ | | | +----------- WORD 1 --------+----------- WORD 0 ---------+ | | +--------------------------- DWORD -----------------------+
The beauty of having bitwise operators is that you can use a BYTE, WORD or DWORD as a small array or structure. Using bitwise operators you can check or set the values of individual bits or even a group of bits.
When working with bits, it is kind of hard to express every number using just ones and zeros, which is known as binary notation. To get around this we use hexadecimal (base 16) numbers.
As you may or may not know, it takes four bits to cover all the numbers from zero to fifteen, which also happens to be the range of a single digit hexadecimal number. This group of four bits, or half a BYTE, is called a nibble. As there are two nibbles in a BYTE, we can use two hexadecimal digits to show the value of one BYTE.
NIBBLE HEX VALUE ====== ========= 0000 0 0001 1 0010 2 0011 3 0100 4 0101 5 0110 6 0111 7 1000 8 1001 9 1010 A 1011 B 1100 C 1101 D 1110 E 1111 F
So if we had one BYTE containing the letter 'r' (ASCII code 114) it would look like this:
0111 0010 binary 7 2 hexadecimal
We could write it as '0x72'
There are six bitwise operators. They are:
& The AND operator
| The OR operator
^ The XOR operator
~ The Ones Complement or Inversion operator
>> The Right Shift operator
<< The Left Shift operator.
The & (AND) operator compares two values, and returns a value that has its bits set if, and only if, the two values being compared both have their corresponding bits set. The bits are compared using the following table
1 & 1 == 1 1 & 0 == 0 0 & 1 == 0 0 & 0 == 0
An ideal use for this is to set up a mask to check the values of certain bits. Say we have a BYTE that contains some bit flags, and we want to check if bit four bit is set.
BYTE b = 50; if ( b & 0x10 ) cout << "Bit four is set" << endl; else cout << "Bit four is clear" << endl;
This would result in the following calculation
00110010 - b & 00010000 - & 0x10 ---------- 00010000 - result
So we see that bit four is set.
The | (OR) operator compares two values, and returns a value that has its bits set if one or the other values, or both, have their corresponding bits set. The bits are compared using the following table
1 | 1 == 1 1 | 0 == 1 0 | 1 == 1 0 | 0 == 0
An ideal use for this is to ensure that certain bits are set. Say we want to ensure that bit three of some value is set
BYTE b = 50; BYTE c = b | 0x04; cout << "c = " << c << endl;
This would result in the following calculation
00110010 - b | 00000100 - | 0x04 ---------- 00110110 - result
The ^ (XOR) operator compares two values, and returns a value that has its bits set if one or the other value has its corresponding bits set, but not both. The bits are compared using the following table
1 ^ 1 == 0 1 ^ 0 == 1 0 ^ 1 == 1 0 ^ 0 == 0
An ideal use for this is to toggle certain bits. Say we want toggle the bits three and four
BYTE b = 50; cout << "b = " << b << endl; b = b ^ 0x18; cout << "b = " << b << endl; b = b ^ 0x18; cout << "b = " << b << endl;
This would result in the following calculations
00110010 - b ^ 00011000 - ^ 0x18 ---------- 00101010 - result 00101010 - b
^ 00011000 - ^ 0x18 ---------- 00110010 - result
The ~ (Ones Complement or inversion) operator acts only on one value and it inverts it, turning all the ones int zeros, and all the zeros into ones. An ideal use of this would be to set certain bytes to zero, and ensuring all other bytes are set to one, regardless of the size of the data. Say we want to set all the bits to one except bits zero and one
BYTE b = ~0x03; cout << "b = " << b << endl; WORD w = ~0x03; cout << "w = " << w << endl;
This would result in the following calculations
00000011 - 0x03 11111100 - ~0x03 b 0000000000000011 - 0x03 1111111111111100 - ~0x03 w
Another ideal use, is to combine it with the & operator to ensure that certain bits are set to zero. Say we want to clear bit four
BYTE b = 50; cout << "b = " << b << endl; BYTE c = b & ~0x10; cout << "c = " << c << endl;
This would result in the following calculations
00110010 - b & 11101111 - ~0x10 ---------- 00100010 - result
The >> (Right shift) and << (left shift) operators move the bits the number of bit positions specified. The >> operator shifts the bits from the high bit to the low bit. The << operator shifts the bits from the low bit to the high bit. One use for these operators is to align the bits for whatever reason (check out the MAKEWPARAM, HIWORD, and LOWORD macros)
BYTE b = 12; cout << "b = " << b << endl; BYTE c = b << 2; cout << "c = " << c << endl; c = b >> 2; cout << "c = " << c << endl;
This would result in the following calculations
00001100 - b 00110000 - b << 2 00000011 - b >> 2
Another interesting thing that can be done using bits is to have bit fields. With bit fields you can set up minature structures within a BYTE, WORD or DWORD. Say, for example, we want to keep track of dates, but we want to use the least amount of memory as possible. We could declare our structure this way
struct date_struct { BYTE day : 5, // 1 to 31 month : 4, // 1 to 12 year : 14; // 0 to 9999 } date;
In this example, the day field takes up the lowest 5 bits, month the next four, and year the next 14 bits. So we can store the date structure in twenty three bits, which is contained in three BYTEs. The twenty fourth bit is ignored. If I had declared it using an integer for each field, the structure would have taken up 12 BYTEs.
|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0| | | | | +------ year -------------+ month + day --+
Now lets pick this declaration apart to see what we are doing.
First we will look at the data type we are using for the bit field structure. In this case we used a BYTE. A BYTE is 8 bits, and by using it, the compiler will allocate one BYTE for storage. If however, we use more than 8 bits in our structure, the compiler will allocate another BYTE, as many BYTEs as it takes to hold our structure. If we had used a WORD or DWORD, the compiler would have allocated a total of 32 bits to hold our structure.
Now lets look at how the various fields are declared. First we have the variable (day, month, and year), followed by a colon that separates the variable from the number of bits that it contains. Each bit field is separated by a comma, and the list is ended with a semicolon.
Now we get to the struct declaration. We put the bit fields into a struct like this so that we can use convention structure accessing notation to get at the structure members. Also, since we can not get the addresses of bit fields, we can now use the address of the structure.
date.day = 12; dateptr = &date; dateptr->year = 1852;
FindLowestAncestor(Struct TreeNode *pRoot, Struct TreeNode *pNode1, Struct TreeNode *pNode2)
{
if (pRoot==NULL)
return NULL;
if (pRoot==pNode1 && pRoot==pNode2)
return pRoot;
Struct TreeNode *pTemp;
if (pTemp = FindLowestAncestor(pRoot->pLeft,pNode1,pNode2))
return pTemp;
if (pTemp = FindLowestAncestor(pRoot->pRight,pNode1,pNode2))
return pTemp;
if (FindLowestAncestor(pRoot,pNode1,pNode1) && FindLowestAncestor(pRoot,pNo
de2,pNode2)) return pRoot;
return NULL;
}
注:(x)p1是指向charcd的指针的指针Q?BR> p2是指向const charcd的指针的指针Q?BR> p3是指向charcd的const指针Q?BR> p4是指向const charcd的const指针Q?BR> p5是指向charcd的指针的const指针Q?BR> p6是指向const charcd的指针的const指针Q?BR> p7是指向charcdconst指针的const指针Q?BR> p8是指向const charcd的const指针的const指针?BR>
原文地址Q?A >http://www.codeproject.com/cpp/complex_declarations.asp
Yin Feilong
Address: Room 110 Building
Phone: (86-25) 8359-4465 +86135-8519-7909
E-mail: yinfeil@gmail.com Homepage: http://www.seman.cn
Objective:
C++ Software Design Engineer
Education:
B.E Department of Information Management,
GPA: Overall: 3.2/4.0
Academic Main Courses:
Development Tools of Management Information System
Management Information Systems and software Engineering
Information Analysis and Policy Making, Information Retrieval and Storage
Programming Languages (C), Data Structures, Database Systems
Computer Network, System Science and Techniques, Information Organization
Computer Abilities:
Certification:
National Computer Rank Examination Grade Three(NCRE-3)
Qualification of Computer and Software Technology Proficiency: Software Designer
Skills:
Expert: C/C++, Visual Foxpro, HTML, Asp, CSS
Intermediate: Rational Rose, SQL Server, XML, Java, Project 2003
Beginner: C#, Asp.net, Visual C++, Oracle
English Skills:
Have a good command of both spoken and written English. Past CET-4
Experiences:
Developer. Lily-Studio of
Designed and implemented the Community of Lily Alumni
Editor in chief of the magazine Network Guide
Lab Manager. Information Technology Lab. June 2004 ?Present
Supervisor of Network Application, Designed and implemented FTP?/SPAN>SMTP-based mail Server?/SPAN>VPN ?/SPAN>Web Server
Designed and implemented 2 websites of Department of Information Management and
Designed and implemented the platform of Tech-Learn Information
Translate some parts of Web-based Analysis for competitive.
Honors:
Football?/SPAN>Ping pong