《计算机程序设计基础》课程学习指南(C语言)C语言常见问题详解

C语言常见问题详解C语言二进制、八进制、十六进制详解什么是二进制?在数学计算中,二进制计数系统的公分母是最小的,它以2为基数。你还记得在小学或中学时所学的不同的计数系统吗?笔者在上小学时,曾在一堂数学课中学过以6为基数的计数系统;你先数1,2,3,4,5,然后是10,11,12,13,14,15,然后是20,等等,实际上,应该先数0,1,2,3,4,5,然后是10,11,12,13,14,15,等等。从0开始数,能比较清楚地看出每6个数字组成一组一一因此6就是基数。注意,你应该从0开始一起数到比基数小1的数(因为基数是6,所以你应该从0数到5)。当你数到5后,接着应该开始数两位数。如果你思考一下,你就会发现这与以10为基数(十进制)的计数系统是类似的一一在你数到比基数小1的数(9)后,就转到两位数,并继续往下数。计算机中的计数系统以2为基数一一即二进制。由于以2为基数,所以你先数O,1,然后是10,11,然后是100,101,110,111,然后是1000,1001,1010,1011,1100,1101,1110,1111等等。与以6为基数时不同,在以2为基数时,在数到两位数之前,只需从O数到1。那么,为什么在计算机中要以2为基数呢?其原因在于计算机中使用了晶体管。晶体管使现代计算机的出现成为可能。晶体管就象电灯开关,电灯开关有"开"和关“两种状态,晶体管也是如此。你可以认为关“表示0,“开“表示1,这样,你就可以用一个晶体管(如果你愿意,也可以用一个电灯开关)来进行从。到1的计数了。仅仅使用两个数字(0到1)还不能做任何复杂的计算,但是我们还可以继续下去。假设有一个电灯开关控制面板,上面有4个大电灯开关,尽管每个开关只有两种状态,但是这些开关组合起来就会有16或2。(4个开关,每个2种状态)种不同的状态。这样,你就可以用4个开关来进行从0到15的计数了。进制计数幕开关十进制值00201121102311224100510161107111238100091001101010111011110012110113141110151111上表说明了很重要的三点:通过把开关并排放在一起,你就可以用它们来计数了一一在本例中最多可以数到15(总共16次计数);你可以把每个开关看作是一个二进制位,就象十进制系统中的十进制位一样;如果每个开关都代表一个二进制位,那么它们刚好也都代表一个2的幂(2°,21,22,23,等等)
C语言常见问题详解 C语言二进制、八进制、十六进制详解 什么是二进制? 在数学计算中,二进制计数系统的公分母是最小的,它以2为基数。你还记得在小学或中学时所 学的不同的计数系统吗?笔者在上小学时,曾在一堂数学课中学过以6为基数的计数系统;你先数1, 2,3,4,5,然后是10,11,12,13,14,15,然后是20,等等,实际上,应该先数0,1,2, 3,4,5,然后是10,1l,12,13,14,15,等等。从0开始数,能比较清楚地看出每6个数字组成 一组——因此6就是基数。注意,你应该从0开始一起数到比基数小1的数(因为基数是6,所以你应该 从0数到5)。当你数到5后,接着应该开始数两位数。如果你思考一下,你就会发现这与以10为基数 (十进制)的计数系统是类似的——在你数到比基数小1的数(9)后,就转到两位数,并继续往下数。 计算机中的计数系统以2为基数——即二进制。由于以2为基数,所以你先数O,1,然后是10, 11,然后是100,101,110,111,然后是1000,1001,1010,1011,1100,1101,1110,1111, 等等。与以6为基数时不同,在以2为基数时,在数到两位数之前,只需从O数到1。 那么,为什么在计算机中要以2为基数呢?其原因在于计算机中使用了晶体管。晶体管使现代计算 机的出现成为可能。晶体管就象电灯开关,电灯开关有"开"和"关"两种状态,晶体管也是如此。你可 以认为"关"表示0,"开"表示1,这样,你就可以用一个晶体管(如果你愿意,也可以用一个电灯开关) 来进行从。到1的计数了。仅仅使用两个数字(0到1)还不能做任何复杂的计算,但是我们还可以继续 下去。假设有一个电灯开关控制面板,上面有4个大电灯开关,尽管每个开关只有两种状态,但是这 些开关组合起来就会有16或2。(4个开关,每个2种状态)种不同的状态。这样,你就可以用4个开关 来进行从0到15的计数了。 进制计数 - 开关 十进制值 幂 - 0 0 1 1 20 10 2 21 11 3 100 4 22 101 5 110 6 111 7 1000 8 23 1001 9 1010 10 1011 11 1100 12 1101 13 1110 14 1111 15 - 上表说明了很重要的三点: 通过把开关并排放在一起,你就可以用它们来计数了——在本例中最多可以数到15(总共16次计 数); 你可以把每个开关看作是一个二进制位,就象十进制系统中的十进制位一样; 如果每个开关都代表一个二进制位,那么它们刚好也都代表一个2的幂(20,2 1,2 2,2 3,等等)

此外,请注意,在表中出现2的幕的地方,计数结果就要增加一个二进制位。这与十进制系统是相同的,每增加一个十进制位时,这个新的十进制位也正是一个10的幂(1=10°,10=101100=102,等等)。明白了这一点后,你就可以很容易地把二进制数转换为十进制数了,例如,二进制数10111就是(1×24)+(0×23)+(1×22)+(1×21)+(1×29),它等于十进制的(16+0+4+2+1)或23。1011101011,一个大得多的二进制数,就是(1×29)+(0×2°)+(1×2)+(1×26)+(1×25)+(0×24)+(1×23)+(0×22)+(1×21)+(1×2°),它等于+进制的(512+0+128+64+32+0+8+0+2+1)或747。那么所有这些和我们有什么关系呢?在计算机领域中,存在着位(bit),半字节(nibble)和字节(byte)。一个半字节是4位,一个字节是8位。什么是一个位呢?它就是一个晶体管。因此,一个字节就是8个相邻的晶体管,就象表20.1中的4个开关一样。记住,如果你有4个组合在一起的开关(或晶体管),你就可以数24或16,你可以把这看作是由开关组成的一个半字节。如果一个半字节是4个晶体管组合在一起,那么一个字节就是8个晶体管组合在一起。你可以用8个晶体管数到2。或256,从另一个角度看,这意味看一个字节(含8个晶体管)可以表示256个不同的数字(从0到255)。再深入一点,Intel386,486和Pentium处理器被叫做32位处理器,这意味着这些Intel芯片所进行的每一次运算都是32位宽或32个晶体管宽的。32个晶体管,或32位,等价于232或4,294,967,296,即它们能表示超过40亿个不同的数字。当然,上述介绍还不能解释计算机是如何利用这些数字产生那种神奇的计算能力的,但它至少解释了计算机为什么要使用以及是如何使用二进制计数系统的。什么是八进制?八进制是以8为基数的一种计数系统。在八进制系统中,你是这样计数的:0,1,2,3,4,5,6,7,10,11,12,13,等等。下面比较了八进制(第二行)和十进制第一行)中的计数过程:0,1,2,3,4,5,6,7,8,9,10.11,12,13,14,15,160,1,2,3,4,5,6,7,10,11,12,13,14,15,16,17,20注意,在八进制中,在数到7后,就要增加一个八进制位,第二个八进制位显然就是8?(等于十进制的8)。如果你数到第三个八进制位(八进制的100),那将是8?或十进制的64,因此,八进制的100等于十进制的64。现在,八进制已经不像以前那样常用了,这主要是因为现在的计算机使用的是8,16,32或64位处理器,最适合它们的计数系统是二进制或十六进制。C语言支持八进制字符集,这种字符要用反斜杠字符来标识。例如,在C程序中,下面的语句并不少见if(x==1007)break;这里的"1007"恰好就是ASCII值为7的字符;该语句用来检查终端鸣笛字符。另一个常见的八进制数是"1033",即Escape字符(在程序中它通常表示为"1033")。然而,八进制数现在已经很少见了它们被十六进制数代替了。什么是十六进制?十六进制(hexadecimal,缩写为hex)是以16为基数的计数系统,它是计算机中最常用的计数系统。十六进制中的计数过程为:0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10,1112,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,等等。十六进制中的字母是几个单位数标识符,表示十进制的10到15。要记住在不同基数下的计数规则,即从0数到比基数小1的数字,在十六进制中这个数就是十进制的15。因为西式数字中没有表示大于9的单位数,所以就用A,B,C,D,E和F来表示十进制的10到15。在十六进制中,数到F之后,就要转到两位数上,也就是10H或0x10。下面对十六进制(第二行)和十进制(第一行)的计数过程作一下比较:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10
此外,请注意,在表中出现2的幂的地方,计数结果就要增加一个二进制位。这与十进制系统是 相同的,每增加一个十进制位时,这个新的十进制位也正是一个10的幂(1=100,10=101, 100=102,等等)。明白了这一点后,你就可以很容易地把二进制数转换为十进制数了,例如,二进 制数10111就是(1×2 4 )+(0×2 3 )+(1×2 2 )+(1×2 1 )+(1×2 0 ),它等于十进制的(16+0+4+2+1)或23。10 1110 1011,一个大得多的二进制数,就是(1×2 9 )+(0×2 8 )+(1×2 7 )+(1×2 6 )+(1×2 5 )+(0×2 4 )+(1×2 3 )+ (0×2 2 )+(1×2 1 )+(1×2 0 ),它等于十进制的(512+0+128+64+32+0+8+0+2+1)或747。 那么所有这些和我们有什么关系呢? 在计算机领域中,存在着位(bit),半字节(nibble)和字节(byte)。一个半字节是4位,一个字节是8 位。什么是一个位呢?它就是一个晶体管。因此,一个字节就是8个相邻的晶体管,就象表20.1中的 4个开关一样。记住,如果你有4个组合在一起的开关(或晶体管),你就可以数24或16,你可以把这 看作是由开关组成的一个半字节。如果一个半字节是4个晶体管组合在一起,那么一个字节就是8个 晶体管组合在一起。你可以用8个晶体管数到2。或256,从另一个角度看,这意味着一个字节(含8个 晶体管)可以表示256个不同的数字(从0到 255)。再深入一点,Intel 386,486和Pentium处理器被叫 做32位处理器,这意味着这些Intel芯片所进行的每一次运算都是32位宽或32个晶体管宽的。32个晶 体管,或32位,等价于232或4,294,967,296,即它们能表示超过40亿个不同的数字。 当然,上述介绍还不能解释计算机是如何利用这些数字产生那种神奇的计算能力的,但它至少解 释了计算机为什么要使用以及是如何使用二进制计数系统的。 什么是八进制? 八进制是以8为基数的一种计数系统。在八进制系统中,你是这样计数的:0,1,2,3,4,5, 6,7,10,11,12,13,等等。下面比较了八进制(第二行)和十进制(第一行)中的计数过程: 0,l,2,3,4,5,6,7,8,9,10.11,12,13,14,15,16 0,1,2,3,4,5,6,7,10,11,12,13,14,15,16,17,20 注意,在八进制中,在数到7后,就要增加一个八进制位,第二个八进制位显然就是8?(等于十进 制的8)。如果你数到第三个八进制位(八进制的100),那将是8?或十进制的64,因此,八进制的100 等于十进制的64。 现在,八进制已经不像以前那样常用了,这主要是因为现在的计算机使用的是8,16,32或64位处 理器,最适合它们的计数系统是二进制或十六进制。 C语言支持八进制字符集,这种字符要用反斜杠字符来标识。例如,在C程序中,下面的语句并 不少见: if(x=='\007') break; 这里的"\007"恰好就是ASCII值为7的字符;该语句用来检查终端鸣笛字符。另一个常见的八进制 数是"\033",即Escape字符(在程序中它通常表示为"\033")。然而,八进制数现在已经很少见了—— 它们被十六进制数代替了。 什么是十六进制? 十六进制(hexadecimal,缩写为hex)是以16为基数的计数系统,它是计算机中最常用的计数系 统。十六进制中的计数过程为:0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10,11, 12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,等等。十六进制中的字母是几 个单位数标识符,表示十进制的10到15。要记住在不同基数下的计数规则,即从0数到比基数小1的 数字,在十六进制中这个数就是十进制的15。因为西式数字中没有表示大于9的单位数,所以就用 A,B,C,D,E和F来表示十进制的10到15。在十六进制中,数到F之后,就要转到两位数上,也就 是10H或0x10。下面对十六进制(第二行)和十进制(第一行)的计数过程作一下比较: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,. 1,2,3,4,5,6,7,8,9,A, B, C, D, E, F, 10

注意,十进制的10等于十六进制的A。与前面讨论过的计数系统一样,每增加一个十六进制位实际上就增加了一个16的幕,即16%(1),161(16),162(256),163(4096),等等。因此,十六进制数3F可以展开为(3×161)+(F×169),等于十进制的(48+15)或63;十六进制数13F可以展开为(1×16)+(3×161)+(F×16),等于十进制的(256+48+15)或319。在c程序中,这两个数用0x3F或0x13F这样的形式来表示,其中的"0x"前缀用来告诉编译程序(和程序员)该数字应被当作十六进制数来处理。如果不加"Ox"前缀,你就无法判断一个数究竟是十六进制数还是十进制数(或者是八进制数)。通过比较二进制、十进制和十六进制·你就会发现:"十"在二进制中是"1010",在十进制中是10",在十六进制中是"A";。。十六"在二进制中是"10000"或"10000",在十进制中是"16",在十六进制中是10"。这意味着什么呢?因为今天的16,32和64位处理器的位宽恰好都是16的倍数,所以在这些类型的计算机中用十六进制作为计数系统是非常合适的。十六进制位和二进位之间有一种"倍数"关系。在上表的最后一行中,二进制值被分为两部分(10000)。4个二进制位(或者4位)可以计数到15(包括0在内共16个不同的数字),而4位(bit)正好等于个半字节(nibble)。在上表中你还可以发现,一个十六进制位同样可以计数到15(包括。在内共16个不同的数字),因此,一个十六进制位可以代表4个二进制位。一个很好的例子就是用二进制表示十进制的15和16,在二进制中,十进制的15就是1111,正好是4个二进制位能表示的最大数字;在十六进制中,十进制的15就是F,也正好是一个十六进制位能表示的最大数字。十进制的16要用5个二进制位(10000)或两个十六进制位(10)来表示。下面把前文提到过的两个数字(0x3F和0x13F)转换为二进制:3F11111113F100111111如果把前面的空格换为0,并且把二进制位分成4位一组,那么看起来就会清楚一些3F00011111113F100111111你并不一定要把二进制位分成4位一组,只不过当你明白了4个二进制位等价于一个十六进制位后,计数就更容易了。为了证明上述两组数字是相等的,可以把二进制值转换为十进制值(十六进制值到十进制值的转换已经在前文中介绍过了);二进制的111111就是(1×25)+(1×24)+(1×23)+(1×2-)+(1×2')+(1×2°),等于十进制的(32+16+8+4+2+1)或63,与0x3F的转换结果相同。二进制的100111111就是(1×28)+(0×2)+0×26)+(1×25)+(1×24)+(1×23)+(1×23)++(1×21)+(1×29),等于+进制的(256+32+16+8+4+2+1)或319。因此,十六进制和二进制能象手掌和手套那样相互匹配。如何决定使用那种整数类型?如果需要大数值(大于32,767或小于32,767),使用long型。否则,如果空间很重要(如有大数组或很多结构),使用short型。除此之外,就使用int型。如果严格定义的溢出特征很重要而负值无关紧要,或者你希望在操作二进制位和字节时避免符号扩展的问题,请使用对应的无符号类型。但是,要注意在表达式中混用有符号和无符号值的情况尽管学符类型(无其是无符号学符型)可以当成"小整型使用,但由于不可预知的符号扩展和代码增大有时这样做可能得不偿失。使用无符号字符型有所帮助。在选择浮点型和双精度浮点型时也有类似的权衡。但如果一个变量的指针必须为特定的类型时,以上规则不再适用。怎样把一个十六进制的值赋给一个变量?C语言支持二进制、八进制、十进制和十六进制的计数系统,在表示一个数字时,用某个特殊的字符来区别其所属的计数系统是必要的。在表示二进制数时,要在数字的未尾加上"b"(如101b);在表示八进制数时,要使用反斜杠(如1014):在表示十六制数时,要使用"0x"学符序列(如0x34):显然,在表示十进制数时,不需要任标识符,因为十进制是缺省的计数系统要把一个十六进制的值赋给一个变量,你可以象下面这样做:
注意,十进制的10等于十六进制的A。与前面讨论过的计数系统一样,每增加一个十六进制位, 实际上就增加了一个16的幂,即160 (1),161 (16),162 (256),163 (4096),等等。因此,十六进制数 3F可以展开为(3×161 )+(F×160 ),等于十进制的(48+15)或63;十六进制数13F可以展开为(1×162 )+ (3×161 )+(F×160 ),等于十进制的(256+48+15)或319。在c程序中,这两个数用0x3F或0x13F这样的 形式来表示,其中的"0x"前缀用来告诉编译程序(和程序员)该数字应被当作十六进制数来处理。如果 不加"0x"前缀,你就无法判断一个数究竟是十六进制数还是十进制数(或者是八进制数)。 通过比较二进制、十进制和十六进制·你就会发现:"十"在二进制中是"1010",在十进制中 是"10",在十六进制中是"A";。十六"在二进制中是"1 0000"或"10000",在十进制中是"16",在十 六进制中是"10"。这意味着什么呢?因为今天的16,32和64位处理器的位宽恰好都是16的倍数,所以 在这些类型的计算机中用十六进制作为计数系统是非常合适的。 十六进制位和二进位之间有一种"倍数"关系。在上表的最后一行中,二进制值被分为两部分(1 0000)。4个二进制位(或者4位)可以计数到15(包括0在内共16个不同的数字),而4位(bit)正好等于一 个半字节(nibble)。在上表中你还可以发现,一个十六进制位同样可以计数到15(包括。在内共l 6个不 同的数字),因此,一个十六进制位可以代表4个二进制位。一个很好的例子就是用二进制表示十进制 的15和16,在二进制中,十进制的15就是1111,正好是4个二进制位能表示的最大数字;在十六进制 中,十进制的15就是F,也正好是一个十六进制位能表示的最大数字。十进制的16要用5个二进制位 (1 0000)或两个十六进制位(10)来表示。下面把前文提到过的两个数字(0x3F和0x13F)转换为二进 制: 3F 111111 13F 100111111 如果把前面的空格换为0,并且把二进制位分成4位一组,那么看起来就会清楚一些: 3F 0 0011 1111 13F 1 0011 1111 你并不一定要把二进制位分成4位一组,只不过当你明白了4个二进制位等价于一个十六进制位 后,计数就更容易了。为了证明上述两组数字是相等的,可以把二进制值转换为十进制值(十六进制 值到十进制值的转换已经在前文中介绍过了);二进制的111111就是(1×2 5 )+(1×2 4 )+(1×2 3 )+(1×2 2 )+ (1×2 1 )+(1×2 0 ),等于十进制的(32+16+8+4+2+1)或63,与0x3F的转换结果相同。二进制的1 0011 1111就是(1×2 8 )+(0×2 7 )+(0×2 6 )+(1×2 5 )+(1×2 4 )+(1×2 3 )+(1×2 2 )++(1×2 1 )+(1×2 0 ),等于十进制的 (256+32+1 6+8+4+2+1)或319。因此,十六进制和二进制能象手掌和手套那样相互匹配。 如何决定使用那种整数类型? 如果需要大数值(大于32, 767 或小于32, 767), 使用long 型。否则, 如果空间很重要(如有大数组 或很多结构), 使用short 型。除此之外, 就使用int 型。 如果严格定义的溢出特征很重要而负值无关紧要, 或者你希望在操作二进制位和字节时避免符号 扩展的问题, 请使用对应的无符号类型。但是, 要注意在表达式中混用有符号和无符号值的情况。 尽管字符类型(尤其是无符号字符型) 可以当成"小" 整型使用, 但由于不可预知的符号扩展和代码 增大有时这样做可能得不偿失。使用无符号字符型有所帮助。在选择浮点型和双精度浮点型时也有 类似的权衡。但如果一个变量的指针必须为特定的类型时, 以上规则不再适用。 怎样把一个十六进制的值赋给一个变量? c语言支持二进制、八进制、十进制和十六进制的计数系统,在表示一个数字时,用某个特殊的 字符来区别其所属的计数系统是必要的。在表示二进制数时,要在数字的末尾加上"b"(如101b);在 表示八进制数时,要使用反斜杠(如\014);在表示十六制数时,要使用"0x"字符序列(如0x34);显 然,在表示十进制数时,不需要任何标识符,因为十进制是缺省的计数系统。 要把一个十六进制的值赋给一个变量,你可以象下面这样做:

int x;X=0x20;* put hex 20(32 in decimal) into x */x=0x20';/ *puttheAsCll characterwhose value ishex20 intox */只有了解了十六进制计数系统,你才能知道要赋的值应该如何表示。怎样把一个八进制的值赋给一个变量?把一个八进制的值赋给一个变量与把一个十六进制的值赋给一个变量一样简单int x;x=1033;/*put octal 33 (decimal 27)intox*/x="033';/ * puttheAsCll characterwhosevalue is octal 33 intox*同样,只有了解了八进制计数系统,你才能知道要赋的值应该如何表示。C语言的char,short,int和long类型分别有多长?其长度分别为一字节,至少两字节,至少两字节和至少4字节。除此之外,不要再依赖任何约定。char类型的长度被定义为一个8位字节,这很简单。short类型的长度至少为两字节。在有些计算机上,对于有些编译程序,short类型的长度可能为4字节,或者更长。int类型是一个整数的自然"大小,其长度至少为两字节,并且至少要和short类型一样长。在16位计算机上,in类型的长度可能为两字节;在32位计算机上,可能为4字节;当64位计算机流行起来后,int类型的长度可能会达到8字节。这里说的都是"可能",例如,早期的Motorala68000是一种16/32位的混合型计算机,依赖于不同的命令行选项,一个68000编译程序能产生两学节长或4字节长的int类型。long类型至少和int类型一样长(因此,它也至少和short类型一样长)。long类型的长度至少为4字节。32位计算机上的编译程序可能会使short,int和long类型的长度都为4字节一一也可能不会。如果你需要一个4字节长的整型变量,你不要想当然地以为int或long类型能满足要求,而要用typedef把一种固有的类型(一种确实存在的类型)定义为你所需要的类型,并在它的前后加上相应的#ifdef指令:#ifdefFOUR_BYTE_LONGtypedef long int4;#endif如果你需要把一个整型变量以字节流的方式写到文件中或网络上,然后再从不同的计算机上读出来,你可能就会用到这样的类型。如果你需要一个两字节长的整型变量,你可能会遇到一些麻烦!因为并不一定有这样的类型。但是,你总是可以把一个较小的值存放到一个由两个char类型组成的数组中16位和32位的数是怎样存储的?一个16位的数占两个字节的存储空间,即高位字节和低位字节。如果你是在纸上书写一个16位的数,你总是会把高位字节写在前面,而把低位字节写在后面。然而,当这个数被存储到内存中时,并没有固定的存储顺序。如果我们用M和L分别表示高位字节和低位字节,那么可以有两种方式把这两个字节存储到内存中,即M在前L在后或者L在前M在后。把M存储在前的顺序被称为"正向(forward)"或"高位优先(bigendian)"顺序;把L存储在前的顺序被称为“逆向(reverse)"或"低位优先(little一endian)"顺序
int x ; x=0x20; /* put hex 20(32 in decimal) into x */ x='0x20' ; / * put the ASCII character whose value is hex 20 into x * / 只有了解了十六进制计数系统,你才能知道要赋的值应该如何表示。 怎样把一个八进制的值赋给一个变量? 把一个八进制的值赋给一个变量与把一个十六进制的值赋给一个变量一样简单: int x ; x=\033; / * put octal 33 (decimal 27) into x * / x='\033' ; / * put the ASCII character whose value is octal 33 into x * / 同样,只有了解了八进制计数系统,你才能知道要赋的值应该如何表示。 C语言的char,short,int和long类型分别有多长? 其长度分别为一字节,至少两字节,至少两字节和至少4字节。除此之外,不要再依赖任何约 定。 char类型的长度被定义为一个8位字节,这很简单。 short类型的长度至少为两字节。在有些计算机上,对于有些编译程序,short类型的长度可能为4 字节,或者更长。 int类型是一个整数的"自然"大小,其长度至少为两字节,并且至少要和short类型一样长。在16位 计算机上,int类型的长度可能为两字节;在32位计算机上,可能为4字节;当64位计算机流行起来 后,int类型的长度可能会达到8字节。这里说的都是"可能",例如,早期的Motorala 68000是一种16 /32位的混合型计算机,依赖于不同的命令行选项,一个68000编译程序能产生两字节长或4字节长 的int类型。 long类型至少和int类型一样长(因此,它也至少和short类型一样长)。long类型的长度至少为4字 节。32位计算机上的编译程序可能会使short,int和long类型的长度都为4字节——也可能不会。 如果你需要一个4字节长的整型变量,你不要想当然地以为int或long类型能满足要求,而要用 typedef把一种固有的类型(一种确实存在的类型)定义为你所需要的类型,并在它的前后加上相应的 #ifdef指令: #ifdef FOUR_BYTE_LONG typedef long int4; #endif 如果你需要把一个整型变量以字节流的方式写到文件中或网络上,然后再从不同的计算机上读出 来,你可能就会用到这样的类型。 如果你需要一个两字节长的整型变量,你可能会遇到一些麻烦!因为并不一定有这样的类型。但 是,你总是可以把一个较小的值存放到一个由两个char类型组成的数组中。 16位和32位的数是怎样存储的? 一个16位的数占两个字节的存储空间,即高位字节和低位字节。如果你是在纸上书写一个16位 的数,你总是会把高位字节写在前面,而把低位字节写在后面。然而,当这个数被存储到内存中 时,并没有固定的存储顺序。 如果我们用M和L分别表示高位字节和低位字节,那么可以有两种方式把这两个字节存储到内存 中,即M在前L在后或者L在前M在后。把M存储在前的顺序被称为"正向(forward)"或"高位优先(big— endian)"顺序;把L存储在前的顺序被称为"逆向(reverse)"或"低位优先(little—endian)"顺序

big一endian这个术语的含义是数的"高位(bigend)"存储在前,同时这也是对《Gulliver'sTravels》这本书中的一个词的引用,在该书中big一endian一词是指那些从大头开始吃一个煮鸡蛋的人。大多数计算机按正向顺序存储一个数,IntelCPU按逆向顺序存储一个数,因此,如果试图将基于IntelCPU的计算机连到其它类型的计算机上,就可能会引起混乱。一个32位的数占4个字节的存储空间,如果我们按有效位从高到低的顺序,分别用Mm,MI,Lm和LI表示这4个字节,那么可以有4!(4的阶乘,即24)种方式来存储这些字节。在过去的这些年中,人们在设计计算机时,几乎用遍了这24种方式。然而,时至今天,只有两种方式是最流行的,一种是(Mm,MIl,Lm,LD,也就是高位优先顺序,另一种是(LI,Lm,MI,Mm),也就是低位优先顺序。和存储16位的数一样,大多数计算机按高位优先顺序存储32位的数,但基于IntelCPU的计算机按低位优先顺序存储32位的数。编写C语言程序时为什么要使用静态变量静态变量作为一个局部变量是很合适的,它在函数退出后不会失去其本身的值。例如,有一个要被调用很多次的函数,它的一部分功能就是计算自己被调用的次数。你不能用一个简单的局部变量来实现这部分功能,因为每次进入该函数时,这个变量都没有被初始化。如果把这个计数变量说明为静态的,那么它就会象一个全局变量那样保留自己的当前值。那么为什么不直接使用一个全局变量呢?你可以使用一个全局变量,而且这样做没有错误。问题是使用了大量全局变量的程序维护起来很麻烦,尤其是有许多函数都各自访问一个全局变量的程序。再说一遍,这样做没有错误,这只是一个程序设计和可读性是否好的问题。如果你把这样的变量说明为静态的,你就可以提醒自己(或者其它可能读你的程序的人)它是局部变量,但要象全局变量那样被处理(保留自己的值)。如果你把它说明为全局的,那么读这个程序的人一定会认为有很多地方要引用它,尽管实际上并不是这样。总而言之,当你需要一个能保持自己的值的局部变量时,使用静态变量是一种好的编程习惯C语言里的移位和乘以2这两种方式中哪一种更好?不管你采用哪种方式,任何合格的优化编译程序都会产生相同的代码,因此你可以采用使程序的上下文更易读的那种方式。你可以用DOS/WindoWS上的CODEVIEW或UNIX机上的反汇编程序通常被称为"dis"这样的工具来查看下述程序的汇编代码:例.4乘以2和左移一位经常是相同的voidmainOtunsigned int test_nbr=300;test_nbr*=2testnbr=300test_nbr<<=1;子C语言中,说明一个变量和定义一个变量有什么区别?说明一个变量意味着向编译程序描述变量的类型,但并不为变量分配存储空间。定义一个变量意味着在说明变量的同时还要为变量分配存储空间。在定义一个变量的同时还可以对变量进行初始化。下例说明了一个变量和一个结构,定义了两个变量,其中一个定义带初始化externintdecll;/*thisisadeclaration*/structdecl24intmember,I; / * this just declares the type--no variable mentioned * /int def1=8;/*this is a definition *
big—endian这个术语的含义是数的"高位(big end)"存储在前,同时这也是对 《Gulliver'sTravels》这本书中的一个词的引用,在该书中big—endian一词是指那些从大头开始吃一 个煮鸡蛋的人。 大多数计算机按正向顺序存储一个数,Intel CPU按逆向顺序存储一个数,因此,如果试图将基 于Intel CPU的计算机连到其它类型的计算机上,就可能会引起混乱。 一个32位的数占4个字节的存储空间,如果我们按有效位从高到低的顺序,分别用Mm,Ml,Lm 和Ll表示这4个字节,那么可以有4!(4的阶乘,即24)种方式来存储这些字节。在过去的这些年中,人 们在设计计算机时,几乎用遍了这24种方式。然而,时至今天,只有两种方式是最流行的,一种是 (Mm,MI,Lm,LD,也就是高位优先顺序,另一种是(Ll,Lm,Ml,Mm),也就是低位优先顺序。 和存储16位的数一样,大多数计算机按高位优先顺序存储32位的数,但基于Intel CPU的计算机按低 位优先顺序存储32位的数。 编写C语言程序时为什么要使用静态变量 静态变量作为一个局部变量是很合适的,它在函数退出后不会失去其本身的值。例如,有一个要 被调用很多次的函数,它的一部分功能就是计算自己被调用的次数。你不能用一个简单的局部变量 来实现这部分功能,因为每次进入该函数时,这个变量都没有被初始化。如果把这个计数变量说明 为静态的,那么它就会象一个全局变量那样保留自己的当前值。 那么为什么不直接使用一个全局变量呢?你可以使用一个全局变量,而且这样做没有错误。问题 是使用了大量全局变量的程序维护起来很麻烦,尤其是有许多函数都各自访问一个全局变量的程 序。再说一遍,这样做没有错误,这只是一个程序设计和可读性是否好的问题。如果你把这样的变 量说明为静态的,你就可以提醒自己(或者其它可能读你的程序的人)它是局部变量,但要象全局变量 那样被处理(保留自己的值)。如果你把它说明为全局的,那么读这个程序的人一定会认为有很多地方 要引用它,尽管实际上并不是这样。 总而言之,当你需要一个能保持自己的值的局部变量时,使用静态变量是一种好的编程习惯。 C语言里的移位和乘以2这两种方式中哪一种更好? 不管你采用哪种方式,任何合格的优化编译程序都会产生相同的代码,因此你可以采用使程序的 上下文更易读的那种方式。你可以用DOS/Windows上的CODEVIEW或UNIX机上的反汇编程序(通 常被称为"dis")这样的工具来查看下述程序的汇编代码: 例. 4乘以2和左移一位经常是相同的 void main() { unsigned int test_nbr = 300; test_nbr * =2; test_nbr = 300; test_nbr << = 1; } C语言中,说明一个变量和定义一个变量有什么区别? 说明一个变量意味着向编译程序描述变量的类型,但并不为变量分配存储空间。定义一个变量意 味着在说明变量的同时还要为变量分配存储空间。在定义一个变量的同时还可以对变量进行初始 化。下例说明了一个变量和一个结构,定义了两个变量,其中一个定义带初始化: extern int decll; / * this is a declaration * / struct decl2 { int member; } ; / * this just declares the type-no variable mentioned * / int def1 = 8; / * this is a definition * /

int def2;/ *this is a definition*/换句话说,说明一个变量相当于告诉编译程序在程序的某个位置将用到一个变量,这里给出了它的名称和类型,定义一个变量则相当于告诉编译程序具有这个名称和这种类型的变量就在这里"。一个变量可以被说明许多次,但只能被定义一次。因此,不应该在头文件中定义变量,因为一个头文件可能会被一个程序的许多源文件所包含。C语言可以在头文件中说明或定义变量吗?被多个文件存取的全局变量可以并且应该在一个头文件中说明,并且必须在一个源文件中定义。变量不应该在头文件中定义,因为一个头文件可能被多个源文件包含,而这将导致变量被多次定义。如果变量的初始化只发生一次,ANSIC标准充许变量有多次外部定义;但是,这样做没有任何好处,因此最好避免这样做,以使程序有更强的可移植性。注意:变量的说明和定义是两个不同的概念。仅供一个文件使用的全局"变量应该被说明为static,而且不应该出现在头文件中。对不同类型的C语言变量进行算术运算会有问题吗?C有三类固有的数据类型:指针类型、整数类型和浮点类型。指针类型的运算限制最严,只限于以下两种运算:-两个指针相减,仅在两个指针指向同一数组中的元素时有效。运算结果与对应于两个指针的数组下标相减的结果相同。+指针和整数类型相加。运算结果为一个指针,该指针与原指针之间相距n个元素,n就是与原指针相加的整数。浮点类型包括float,double和longdouble这三种固有类型。整数类型包括char,unsignedchar,short,unsignedshort,int,unsignedint,long和unsignedlong。对这些类型都可进行以下4种算术运算:+加-减*乘/除对整数类型不仅可以进行上述4种运算,还可进行以下几种运算:%取模或求余>>右移<<左移&按位与「按位或7按位异或!逻辑非取反尽管C允许你使用"混合模式"的表达式(包含不同类型的算术表达式),但是,在进行运算之前,它会把不同的类型转换成同一类型(前面提到的指针运算除外)。这种自动转换类型的过程被称为"运算符升级(operatorpromotion)"。对于C语言什么时候应该使用register修饰符?它真的有用吗?
int def2; / * this is a definition * / 换句话说,说明一个变量相当于告诉编译程序"在程序的某个位置将用到一个变量,这里给出了 它的名称和类型",定义一个变量则相当于告诉编译程序"具有这个名称和这种类型的变量就在这 里"。 一个变量可以被说明许多次,但只能被定义一次。因此,不应该在头文件中定义变量,因为一 个头文件可能会被一个程序的许多源文件所包含。 C语言可以在头文件中说明或定义变量吗? 被多个文件存取的全局变量可以并且应该在一个头文件中说明,并且必须在一个源文件中定义。 变量不应该在头文件中定义,因为一个头文件可能被多个源文件包含,而这将导致变量被多次定 义。如果变量的初始化只发生一次,ANSIC标准允许变量有多次外部定义;但是,这样做没有任何 好处,因此最好避免这样做,以使程序有更强的可移植性。 注意:变量的说明和定义是两个不同的概念。 仅供一个文件使用的"全局"变量应该被说明为static,而且不应该出现在头文件中。 对不同类型的C语言变量进行算术运算会有问题吗? C有三类固有的数据类型:指针类型、整数类型和浮点类型。 指针类型的运算限制最严,只限于以下两种运算: - 两个指针相减,仅在两个指针指向同一数组中的元素时有效。运算结果与对应于两个指针的 数组下标相减的结果相同。 + 指针和整数类型相加。运算结果为一个指针,该指针与原指针之间相距n个元素,n就是与原 指针相加的整数。 浮点类型包括float,double和longdouble这三种固有类型。整数类型包括char,unsigned char, short,unsigned short,int,unsigned int,long和unsigned long。对这些类型都可进行以下4种算术 运算: + 加 - 减 * 乘 / 除 对整数类型不仅可以进行上述4种运算,还可进行以下几种运算: % 取模或求余 >> 右移 << 左移 & 按位与 | 按位或 ^ 按位异或 ! 逻辑非 ~ 取反 尽管C允许你使用"混合模式"的表达式(包含不同类型的算术表达式),但是,在进行运算之 前,它会把不同的类型转换成同一类型(前面提到的指针运算除外)。这种自动转换类型的过程被称 为"运算符升级(operator promotion)"。 对于C语言什么时候应该使用register修饰符?它真的有用吗?

register修饰符暗示编译程序相应的变量将被频繁使用,如果可能的话,应将其保存在CPU的寄存器中,以加快其存取速度。但是,使用register修饰符有几点限制。首先,register变量必须是能被CPU寄存器所接受的类型。这通常意味着register变量必须是一个单个的值,并且其长度应小于或等于整型的长度。但是,有些机器的寄存器也能存放浮点数。其次,因为register变量可能不存放在内存中,所以不能用取址运算符"&"来获取register变量的地址。如果你试图这样做,编译程序就会报告这是一个错误。register修饰符的用处有多大还受其它一些规则的影响。因为寄存器的数量是有限的,而且某些寄存器只能接受特定类型的数据(如指针和浮点数),因此,真正能起作用的register修饰符的数目和类型都依赖于运行程序的机器,而任何多余的register修饰符都将被编译程序所忽略。在某些情况下,把变量保存在寄存器中反而会降低运行速度,因为被占用的寄存器不能再用于其它自的,或一者变量被使用的次数不够多,不足以抵消装入和存储变量所带来的额外开销那么,什么时候应该使用register修饰符呢?回答是,对现有的大多数编译程序来说,永远不要使用register修饰符。早期的C编译程序不会把变量保存在寄存器中,除非你命令它这样做,这时register修饰符是C语言的一种很有价值的补充。然而,随着编译程序设计技术的进步,在决定哪些变量应该被存到寄存器中时,现在的C编译程序能比程序员作出更好的决定。实际上,许多C编译程序会忽略register修饰符,因为尽管它完全合法,但它仅仅是暗示而不是命令。在极罕见的情况下,程序运行速度很慢,而你也知道这是因为有一个变量被存储在内存中,也许你最后会试图在该变量前面加上register修饰符,但是,如果这并没有加快程序的运行速度,你也不要感到奇怪。C语言浮点数比较(floating-pointcomparisons)的可靠性如何?浮点数是计算机编程中的"魔法(blackart)",原因之一是没有一种理想的方式可以表示一个任意的数字。电子电气工程协会(IEEE)已经制定出浮点数的表示标准,但你不能保证所使用的每台机器都遵循这一标准。即使你使用的机器遵循这一标准,还存在更深的问题。从数学意义上讲,两个不同的数字之间有无穷个实数。计算机只能区分至少有一位(bit)不同的两个数字。如果要表示那些无穷无尽的各不相同的数字,就要使用无穷数目的位。计算机只能用较少的位(通常是32位或64位)来表示一个很大的范围内的数字,因此它只能近似地表示大多数数字。由于浮点数是如此难对付,因此比较一个浮点数和某个值是否相等或不等通常是不好的编程习惯。但是,判断一个浮点数是否大于或小于某个值就安全多了。例如,如果你想以较小的步长依次使用一个范围内的数字,你可能会编写这样一个程序:#includeconst float first = 0.0const float last=70.0const float small=0.007main ()float f;for (f=first; f !=last &&f<last+1.0; f +=small)printf("f is now %gln", f);1
register修饰符暗示编译程序相应的变量将被频繁使用,如果可能的话,应将其保存在CPU的寄 存器中,以加快其存取速度。但是,使用register修饰符有几点限制。 首先,register变量必须是能被CPU寄存器所接受的类型。这通常意味着register变量必须是一个 单个的值,并且其长度应小于或等于整型的长度。但是,有些机器的寄存器也能存放浮点数。 其次,因为register变量可能不存放在内存中,所以不能用取址运算符"&"来获取register变量的 地址。如果你试图这样做,编译程序就会报告这是一个错误。 register修饰符的用处有多大还受其它一些规则的影响。因为寄存器的数量是有限的,而且某些 寄存器只能接受特定类型的数据(如指针和浮点数),因此,真正能起作用的register修饰符的数目和 类型都依赖于运行程序的机器,而任何多余的register修饰符都将被编译程序所忽略。 在某些情况下,把变量保存在寄存器中反而会降低运行速度,因为被占用的寄存器不能再用于 其它目的,或—者变量被使用的次数不够多,不足以抵消装入和存储变量所带来的额外开销。 那么,什么时候应该使用register修饰符呢?回答是,对现有的大多数编译程序来说,永远不要使 用register修饰符。早期的C编译程序不会把变量保存在寄存器中,除非你命令它这样做,这时 register修饰符是C语言的一种很有价值的补充。然而,随着编译程序设计技术的进步,在决定哪些 变量应该被存到寄存器中时,现在的C编译程序能比程序员作出更好的决定。 实际上,许多C编译程序会忽略register修饰符,因为尽管它完全合法,但它仅仅是暗示而不是 命令。 在极罕见的情况下,程序运行速度很慢,而你也知道这是因为有一个变量被存储在内存中,也 许你最后会试图在该变量前面加上register修饰符,但是,如果这并没有加快程序的运行速度,你也 不要感到奇怪。 C语言浮点数比较(floating-point comparisons)的可靠性如何? 浮点数是计算机编程中的"魔法(black art)",原因之一是没有一种理想的方式可以表示一个任意的 数字。电子电气工程协会(IEEE)已经制定出浮点数的表示标准,但你不能保证所使用的每台机器都 遵循这一标准。 即使你使用的机器遵循这一标准,还存在更深的问题。从数学意义上讲,两个不同的数字之间有 无穷个实数。计算机只能区分至少有一位(bit)不同的两个数字。如果要表示那些无穷无尽的各不相同 的数字,就要使用无穷数目的位。计算机只能用较少的位(通常是32位或64位)来表示一个很大的范围 内的数字,因此它只能近似地表示大多数数字。 由于浮点数是如此难对付,因此比较一个浮点数和某个值是否相等或不等通常是不好的编程习 惯。但是,判断一个浮点数是否大于或小于某个值就安全多了。例如,如果你想以较小的步长依次 使用一个范围内的数字,你可能会编写这样一个程序: #include const float first = 0.0; const float last = 70.0 const float small= 0.007 main ( ) { float f; for (f=first; f !=last && f<last+1.0; f +=small) printf("f is now %g\n", f); }

然而,舍入误差(roundingerror)和变量small的表示误差可能导致f永远不等于last(f可能会从稍小于last的一个数增加到一个稍大于last的数),这样,循环会跳过last。加入不等式"fO;f+=small):C语言编程中,什么时候应该使用const修饰符使用const修饰符有几个原因:第一个原因是这样能使编译程序找出程序中不小心改变变量值的错误。请看下例while(*str=0)/*programmermeanttowrite*str!=0*/1I * some codehere*/strq++;子其中的"=“符号是输入错误。如果在说明str时没有使用const修饰符,那么相应的程序能通过编译但不能被正确执行。第二个原因是效率。如果编译程序知道某个变量不会被修改,那么它可能会对生成的代码进行某些优化。如果一个函数参数是一个指针,并且你不希望它所指向的数据被该函数或该函数所调用的函数修改,那么你应该把该参数说明为cons指针。如果一个函数参数通过值(而不是通过指针)被传递给函数,并且你不希望其值被该函数所调用的函数修改,那么你应该把该参数说明为const。然而,在实际编程中,只有在编译程序通过指针存取这些数据的效率比拷贝这些数据更高时,才把这些参数说明为const。一个C语言变量可以同时被说明为const和volatile吗可以。const修饰符的含义是变量的值不能被使用了const修饰符的那段代码修改,但这并不意味着它不能被这段代码以外的其它手段修改。例如,通过一个volatileconst指针t来存取timer结构。函数time_addition(本身并不修改t->value的值,因此t->value被说明为const。不过,计算机的硬件会修改这个值,因此t->value又被说明为volatile。如果同时用const和volatile来说明一个变量,那么这两个修饰符随便哪个在先都行。在C语言中,表示真和假的最好方法是什么?在c语言中,任何等于零的东西都被认为是假,任何等于非零值的东西都被认为是真,因此,最常见的定义就是假为0,真为1。许多程序中都包含了具有如下定义的头文件
然而,舍入误差(rounding error)和变量small的表示误差可能导致f永远不等于last(f可能会从稍小 于last的一个数增加到一个稍大于last的数),这样,循环会跳过last。加入不等式"f0;f+=small) ; C语言编程中,什么时候应该使用const修饰符 使用const修饰符有几个原因: 第一个原因是这样能使编译程序找出程序中不小心改变变量值的错误。 请看下例: while ( * str=0) / * programmer meant to write * str! =0 * / { / * some code here * / strq++; } 其中的"="符号是输入错误。如果在说明str时没有使用const修饰符,那么相应的程序能通过编 译但不能被正确执行。 第二个原因是效率。如果编译程序知道某个变量不会被修改,那么它可能会对生成的代码进行某 些优化。 如果一个函数参数是一个指针,并且你不希望它所指向的数据被该函数或该函数所调用的函数修 改,那么你应该把该参数说明为const指针。如果一个函数参数通过值(而不是通过指针)被传递给函 数,并且你不希望其值被该函数所调用的函数修改,那么你应该把该参数说明为const。然而,在实 际编程中,只有在编译程序通过指针存取这些数据的效率比拷贝这些数据更高时,才把这些参数说 明为const。 一个C语言变量可以同时被说明为const和volatile吗 可以。const修饰符的含义是变量的值不能被使用了const修饰符的那段代码修改,但这并不意味 着它不能被这段代码以外的其它手段修改。 例如,通过一个volatile const指针t来存取timer结构。函数time_addition()本身并不修改t->value 的值,因此t->value被说明为const。不过,计算机的硬件会修改这个值,因此t->value又被说明为 volatile。如果同时用const和volatile来说明一个变量,那么这两个修饰符随便哪个在先都行。 在C语言中,表示真和假的最好方法是什么? 在c语言中,任何等于零的东西都被认为是假,任何等于非零值的东西都被认为是真,因此,最 常见的定义就是假为0,真为1。许多程序中都包含了具有如下定义的头文件:

#defineFALSE0#defineTRUE1如果你在编写Windows程序,你应该注意头文件windows.h中的TRUE和FALSE的确切定义。上述真和假的定义方式非常普遍,并且是完全可以接受的,然而,还有其它几种定义方式,请看下例:#defineFALSE0#defineTRUE!FALSE上例把FALSE定义为O,把TRUE定义为非零值。注意,即使是负数,如-1,也是非零值,因此也被认为是真,另一种定义方式是建立自己的枚举类型,如Boolean(或者BOOL),如下所示:enurnBOOLFALSE,TRUE3;在缺省情况下,枚举类型的第一个元素被赋值为O,因此,在上述枚举定义中,FALSE被赋值为0,TRUE被赋值为1。哪种方法最好呢?这个问题没有一个唯一的答案。如果你在编写一个WindoWs程序,那么TRUE和FALSE都是已经为定义好的,你没有必要再建立自己的定义,在其它情况下,你可以从前文所介绍的几种方法中选择一种。C语言空循环和无穷循环有的区别空循环并不会无休止地进行下去一一在重复预先指定的次数后,它就会退出循环。无穷循环会无休止地进行下去,并且永远不会退出循环。把空循环和无穷循环对比一下,就能很好地说明它们之间的区别。下面是一个空循环的例子:for(x=0;x<500000;x++);注意,在上例中,在for循环的闭括号后直接加入了一个分号。正如你可能已经知道的那样,c语言并不要求在for循环后加分号,通常只有包含在for循环中的语句后面才会带分号在for循环后面直接加入分号(并且不使用大括号),即可建立一个空循环一一实际上是一个不包含任何语句的循环。在上例中,当for循环执行时,变量x将自增500,000次,而在每一次自增运算期间,没有进行任何处理。那么,空循环有什么用呢?在大多数情况下,它的作用就是在程序中设置一次暂停。前面的例子将使程序"暂停"一段时间,即计算机数到500000所需的时间。然而,空循环还有更多的用处,请看下例:while(!kbhitO);这个例子用一个空循环来等待一次击键操作。当程序需要显示类似"PressAnyKeyToContinue"这样的信息时,这种方法是很有用的。无穷循环与空循环不同,它永远不会结束。下面是一个无穷循环的例子:while(1);在这个例子中,while语句中包含了一个非零常量,因此,while的条件永远为真,循环永远不会结束。注意,在闭括号后面直接加入一个分号,因此while语句中不包含任何其它语句,循环将无法终止(除非终止程序)。switch语句的最后一个分支可以不要break语句吗尽管switch语句的最后一个分支不一定需要break语句,但最好还是在switch语句的每个分支后面加上break语句,包括最后一个分支。这样做的主要原因是:你的程序很可能要让另一个人来维护,他可能要增加一些新的分支,但没有注意到最后一个分支没有break语句,结果使原来的最后一个分支受到其后新增分支的干扰而失效。在每个分支后面加上break语句将防止发生这种错误并增强程序的安全性
#define FALSE 0 #define TRUE 1 如果你在编写Windows程序,你应该注意头文件windows.h中的TRUE和FALSE的确切定义。上 述真和假的定义方式非常普遍,并且是完全可以接受的,然而,还有其它几种定义方式,请看下 例: #define FALSE 0 #define TRUE !FALSE 上例把FALSE定义为0,把TRUE定义为非零值。注意,即使是负数,如-1,也是非零值,因此 也被认为是真。 另一种定义方式是建立自己的枚举类型,如Boolean(或者BOOL),如下所示: enurn BOOL{ FALSE, TRUE }; 在缺省情况下,枚举类型的第一个元素被赋值为0,因此,在上述枚举定义中,FALSE被赋值为 0,TRUE被赋值为1。 哪种方法最好呢?这个问题没有一个唯一的答案。如果你在编写一个Windows程序,那么TRUE 和FALSE都是已经为定义好的,你没有必要再建立自己的定义,在其它情况下,你可以从前文所介 绍的几种方法中选择一种。 C语言空循环和无穷循环有的区别 空循环并不会无休止地进行下去——在重复预先指定的次数后,它就会退出循环。无穷循环会无 休止地进行下去,并且永远不会退出循环。把空循环和无穷循环对比一下,就能很好地说明它们之 间的区别。 下面是一个空循环的例子: for(x=0;x<500000;x++); 注意,在上例中,在for循环的闭括号后直接加入了一个分号。正如你可能已经知道的那样,c语 言并不要求在for循环后加分号,通常只有包含在for循环中的语句后面才会带分号。 在for循环后面直接加入分号(并且不使用大括号),即可建立一个空循环——实际上是一个不包含 任何语句的循环。在上例中,当for循环执行时,变量x将自增500,000次,而在每一次自增运算期 间,没有进行任何处理。 那么,空循环有什么用呢?在大多数情况下,它的作用就是在程序中设置一次暂停。前面的例子 将使程序"暂停"一段时间,即计算机数到500,000所需的时间。然而,空循环还有更多的用处,请看 下例: while(!kbhit()); 这个例子用一个空循环来等待一次击键操作。当程序需要显示类似"Press Any Key To Continue"这样的信息时,这种方法是很有用的。 无穷循环与空循环不同,它永远不会结束。下面是一个无穷循环的例子: while(1); 在这个例子中,while语句中包含了一个非零常量,因此,while的条件永远为真,循环永远不会 结束。注意,在闭括号后面直接加入一个分号,因此while语句中不包含任何其它语句,循环将无法 终止(除非终止程序)。 switch语句的最后一个分支可以不要break语句吗 尽管switch语句的最后一个分支不一定需要break语句,但最好还是在switch语句的每个分支后面 加上break语句,包括最后一个分支。 这样做的主要原因是:你的程序很可能要让另一个人来维护,他可能要增加一些新的分支,但没 有注意到最后一个分支没有break语句,结果使原来的最后一个分支受到其后新增分支的干扰而失 效。在每个分支后面加上break语句将防止发生这种错误并增强程序的安全性

此外,目前大多数优化编译程序都会忽略最后一条break语句,所以加入这条语句不会影响程序的性能。C语言switch语句必须包含default分支吗?不!但是为了进行错误检查或逻辑检查,还是应该在switch语句中加入default分支。例如,下述switch语句完全合法:switch (char_code)1case tyt:casey': printf ("You answered YES! In"); break;case'N':case'n':printf("YouansweredNOn");break1但是,如果一个未知字符被传递给这条switch语句,会出现什么情况呢?这时,程序将没有任何输出。因此,最好还是加入一个default分支,以处理这种情况:default:printf("Unknownresponse:%din",char_code);break;此外,default分支能给逻辑检查带来很多方便。例如,如果用switch语句来处理数目固定的条件,而且认为这些条件之外的值都属于逻辑错误,那么可以加入一个default分支来辨识逻辑错误。请看下列:void move_cursor (int direction)switch(direction)caseUP:cursor_upO);break;case DOwN:cursor_downO;break;caseLEFT:cursor_left(O;break;caseRIGHT:cursor_right();break;default:printf("Logicerroronlinenumber%ld!!!In",LiNE);break;11C语言编程中,什么时候用一条switch语句比用多条if语句更好?如果你有两个以上基于同一个数字(numeric)型变量的条件表达式,那么最好使用一条switch语句。例如,与其使用下述代码:if (x==l)printf ("x is equal to one. In");else if (x==2)printf ("x is equal to two. In");else if (x==3)printf ("x is equal to three. In");elseprintf ("x is not equal to one, two, or three. In");不如使用下述代码,它更易于阅读和维护:switch (x)Vcase 1: printf (x is equal to one. In");break;case 2:printf ("x is equal to two.In");break;case 3: printf (x is equal to three. In");break;
此外,目前大多数优化编译程序都会忽略最后一条break语句,所以加入这条语句不会影响程序 的性能。 C语言switch语句必须包含default分支吗? 不!但是为了进行错误检查或逻辑检查,还是应该在switch语句中加入default分支。 例如,下述switch语句完全合法: switch (char_code) { case tyt: case 'y': printf ( " You answered YES ! \n" ); break; case 'N': case 'n': printf ("You answered NO!\n"); break; } 但是,如果一个未知字符被传递给这条switch语句,会出现什么情况呢?这时,程序将没有任何 输出。因此,最好还是加入一个default分支,以处理这种情况: default: printf ("Unknown response : %d\n", char_code); break; . 此外,default分支能给逻辑检查带来很多方便。例如,如果用switch语句来处理数目固定的条 件,而且认为这些条件之外的值都属于逻辑错误,那么可以加入一个default分支来辨识逻辑错误。 请看下列: void move_cursor (int direction) { switch (direction) { case UP: cursor_up(); break; case DOWN: cursor_down(); break; case LEFT: cursor_left (); break; case RIGHT: cursor_ right ( ); break; default: printf ("Logic error on line number %ld!!! \n",_ LINE_ ); break; } } C语言编程中,什么时候用一条switch语句比用多条if语句更好? 如果你有两个以上基于同一个数字(numeric)型变量的条件表达式,那么最好使用一条switch语 句。 例如,与其使用下述代码: if (x==l) printf ("x is equal to one. \n"); else if (x==2) printf ("x is equal to two. \n"); else if (x==3) printf ("x is equal to three. \n"); else printf ("x is not equal to one, two, or three. \n"); 不如使用下述代码,它更易于阅读和维护: switch (x) { case 1: printf ("x is equal to one. \n"); break; case 2: printf ("x is equal to two. \n"); break; case 3: printf ('x is equal to three. \n"); break;
按次数下载不扣除下载券;
注册用户24小时内重复下载只扣除一次;
顺序:VIP每日次数-->可用次数-->下载券;
- 《计算机程序设计基础》课程学习指南(C语言)C语言常见英文单词.pdf
- 《计算机程序设计基础》课程学习指南(C语言)C语言常见错误中英文对照表.pdf
- 《计算机程序设计基础》课程教学大纲 C Programming Language(C语言).pdf
- 《计算机控制系统》课程教学资源(PPT课件)第7章 计算机控制系统设计与实现.ppt
- 《计算机控制系统》课程教学资源(PPT课件)第6章 分布式测控网络技术.ppt
- 《计算机控制系统》课程教学资源(PPT课件)第5章 计算机控制系统软件设计相关技术.ppt
- 《计算机控制系统》课程教学资源(PPT课件)第4章 先进控制技术.ppt
- 《计算机控制系统》课程教学资源(PPT课件)第3章 常规数字控制技术.ppt
- 《计算机控制系统》课程教学资源(PPT课件)第2章 计算机控制系统硬件设计相关技术.ppt
- 《计算机控制系统》课程教学资源(PPT课件)第1章 计算机控制系统概述.ppt
- 《计算机控制系统》课程教学资源(PPT课件)前言.ppt
- 《计算机控制系统》课程试题试卷(答案).doc
- 《计算机控制系统》课程试题试卷(题目).doc
- 《计算机控制系统》课程教学大纲.pdf
- 《数据结构》课程教学资源(PPT课件)第四章 数组、集合和矩阵.ppt
- 《数据结构》课程教学资源(PPT课件)第六章 树和二叉树(6.7 树与二叉树的转换 6.8 树的遍历).ppt
- 《数据结构》课程教学资源(PPT课件)第六章 树和二叉树(6.3 以结点类为基础的二叉树设计 6.4 二叉树类 6.5 线索二叉树 6.6 哈夫曼树).ppt
- 《数据结构》课程教学资源(PPT课件)第六章 树和二叉树(6.1 树 6.2 二叉树).ppt
- 《数据结构》课程教学资源(PPT课件)第八章 排序.ppt
- 《数据结构》课程教学资源(PPT课件)第五章 递归算法.ppt
- 《计算机程序设计基础》课程学习指南(C语言)C语言初学者编程规范-1/2.pdf
- 《计算机程序设计基础》课程学习指南(C语言)C语言初学者编程规范-2/2.pdf
- 《计算机程序设计基础》课程学习指南(C语言)给C语言初学者的学习建议.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 1 - Introduction.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 2 - Binary Representation.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 4 - Simple Data Types.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 5 - Standard IO.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 6 - Operators, Expressions and Statements.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 7 - Making Decisions.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 8 - Looping.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 3 - Hardware and Software.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 9 - Arrays.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 10 - Basics of Pointers.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 11 - Strings.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 12 - Basics of Functions.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 13 - More functions.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 14 - Files.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 15 - Data Structures.pdf
- 《计算机程序设计基础》课程授课教案(C语言)第1章 C语言概述.pdf
- 《计算机程序设计基础》课程授课教案(C语言)第2章 基本数据类型和运算符.pdf