预处理指令
以一个井号开头的行都叫做预处理指令。除了#include指令外,我们还经常用到#define指令。#define指令可以告诉编译器,编译时把代码中出现的特定标识当作什么来处理。例如,我们可以这样写:#define NAME_OF_MY_POTENTIAL_GF "ZPR"
这样,编译器会在编译前把代码中出现NAME_OF_MY_POTENTIAL_GF的地方全部替换成"ZPR"。这种替换是无条件的,但是有一个例外:当指定的标识属于某个字符串(被引号引起来)时替换不会发生。例如,下面两行代码会输出NAME_OF_MY_POTENTIAL_GF defined as: ZPRprintf("NAME_OF_MY_POTENTIAL_GF defined as: ");
printf(NAME_OF_MY_POTENTIAL_GF);
其中,后面那个NAME_OF_MY_POTENTIAL_GF被自动替换为"ZPR"。如果哪一天ZPR不要我了,我就可以非常方便地让整个程序适用于另一个MM。
C语言中通常会用#define代替const。例如,下面的代码假设了输入数据n<=2000。#include <stdio.h>
#define MAX 2000
int main()
{
int f[MAX][MAX];
int i,j,n;
scanf("%d",&n);
for ( i=0; i<n; i++ )
{
for ( j=0; j<=i; j++ )
{
f[i][j] = j ? (f[i-1][j] + f[i-1][j-1]) % 10000 : 1;
printf( "%5d" , f[i][j] );
}
printf("n");
}
return 0;
}
下面的这些指令也是合法的:#define begin {
#define end }
#define and &&
#define or ||
#define定义的指令允许带参数。例如,下面的定义也是合法的:#define sqr(x) x*x
观察下面的这个程序:#include <stdio.h>
#define begin {
#define end }
#define writeln(num) printf("%dn",num)
#define sqr(x) x*x
int main()
begin
writeln(sqr(100));
writeln(sqr(10+2));
end
程序输出:10000
32
为什么第二个输出的数是32不是144?不要忘了sqr中的x不是一个变量,编译器仅仅是把x替换为10+2,因此sqr(10+2)的结果是10+2*10+2,当然是32咯。为了避免这种情况,这样写就没问题了:#define sqr(x) ( (x) * (x) )
下面这个定义很常用:#define MAX(a,b) ( ((a) > (b)) ? (a) : (b) )
如果你想写出一个很有个性的C代码,反复使用#define是一个不错的选择。例如,这段代码就极具个性,一个光棍的形象跃然于屏幕上。然而,真正把#define发挥得淋漓尽致的,还是要数这段代码。
static声明
在函数中的变量声明前加一个static可以使这个变量具有“记忆性”。观察下面的程序:#include <stdio.h>
void printNum()
{
int a=1;
static int b=1;
printf("%d %dn", a++, b++);
}
int main()
{
int i;
for ( i=1; i<=5; i++ )
printNum();
return 0;
}
程序输出:1 1
1 2
1 3
1 4
1 5
short类型和int类型的范围
最初我们列出的C语言类型和Pascal类型的对比只能提供一个参考。事实上不同的编译器中short和int的范围可能不同。你可以查一下前面说过的limits.h来确定这些类型的实际范围。通常short是16位整数,long是32位整数。在Windows下Dev-C++中int类型是32位。
对64位整型的处理
和Free Pascal一样,对64位整数类型的处理总是比较麻烦。
首先,对long long赋值很可能会发生错误,你可以在常数后添加一个LL表明这是long long类型。其次,C语言中有些函数是要区分数据类型的,你需要根据数据类型选用恰当的函数。最后,long long类型的输出很可能也有问题,此时你可以用"%lld"来替换"%d",表明输出的是一个long long类型。在Windows下总要装点怪,我在Windows编译时非要用"%I64d"才行。
下面的程序代码在Windows下Dev-C++中一切正常。#include <stdio.h>
#include <stdlib.h>
int main()
{
long long a;
a = -5841314520LL;
a = llabs(a);
a = a + 1;
printf("%I64d",a);
return 0;
}
查漏补缺
这个系列到这里就结束了。还有我没有说到的语法点吗?欢迎大家补充。
后记
C语言速成手册到这里就结束了。这很可能是网上现有的原创C语言教材中讲解最快,篇幅最短的,因为它只适合已经学过其它语言,了解程序设计基础知识的人。这一系列的文章略过了大量的概念讲解、示例代码和习题,你可以自己在网上阅读一些C语言程序作为补充。以后我可能还会写一些类似的文章介绍其它语言。下一步我计划写C与C++的区别,对象和类的介绍以及C++的新特性。再以后我可能会向Java或者Ruby的方向发展。
祝各位努力转C的OIer暑假愉快。
Matrix67原创
转贴请注明出处
……你把#define的好处说得太准确了
事实上,关于#define还有两个运算符: #和##
#用于把宏参数转换为字符串,例如
#define PLUS(A, B) printf(#A " + " #B " is %d.n", (A) + (B))
这样PLUS(3, 2);会输出3 + 2 is 5
int alpha = 3, beta = 2;
PLUS(alpha, beta);会输出alpha + beta is 5.
##用于把两个东西组合成一个,例如
#define PRINT(X) printf("%d", n ## X)
int n1 = 1, n2 = 2, n3 = 3, n4 = 4;
则PRINT(i);将会输出ni(1<=i<=4)的值.
但注意这个i只能是很实在的常数,不能是变量,应为如果i是变量,n ## i的结果将会得到ni,但事实上没有ni(变量名)这个东西存在
回复:嗯,谢谢补充,我说漏了
为什么?莫非您把n看成h了?-_-|||
回复:知道1111是光棍节么[lol]
Er…其实今年的1111是我们学校百年校庆……
怎么实现PASCAL中的trunc()啊。。
忽略小数部分+转为整型
怎么输出较大的unsigned long long 类型啊。。。
你
太猥琐了 居然想到这样
#define begin {
#define end }
#define and &&
#define or ||
正好适合我!
这个手册太棒了 thx 语文好的人就是不一样
这个系列对我很有帮助 THX~
说好的C++呢
这个手册太棒了
终于撸到最后一章了。。。话说matrix大大 杨辉三角那个程序我用dev c++跑显示: Process exited with return value 255 貌似是数组溢了 max改成500就OK了。。。T T度娘了下没结果 只能向你寻求帮助了