一、注意點
1.字符串輸出
#include<stdio.h>
int main()
{
puts("C語 言 中文網");
puts("C語言
中文網");
return 0;
}
第 5~6 行代碼是錯誤的,字符串必須在一行內結束,不能換行。
2.控制檯顏色設置
WORD
在windows.h
中定義,等同於unsigned short
,使用低4位表示文字(前景)顏色,高4位表示文字背景顏色,所以它的取值爲xx
。x爲一位16進制數,即0~F
都可以使用,可以隨意組合。
0~F 分別代表的顏色如下:
0 = 黑色 8 = 灰色 1 = 淡藍 9 = 藍色
2 = 淡綠 A = 綠色 3 = 湖藍 B = 淡淺綠
C = 紅色 4 = 淡紅 5 = 紫色 D = 淡紫
6 = 黃色 E = 淡黃 7 = 白色 F = 亮白
例如,將背景設置爲淡綠色,文字設置爲紅色:
#include <stdio.h>
#include <windows.h>
int main(){
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, 0x2C );
puts("C語言中文網");
return 0;
}
如果只希望設置文字顏色,背景保持黑色,那麼也可以只給出一位16進制數,例如:
SetConsoleTextAttribute(hConsole, 0xC ); //將文字顏色設置爲紅色
SetConsoleTextAttribute(hConsole, 0xF ); //將文字顏色設置爲白色
3.最簡單的數據類型及數據類型長度
說 明 | 字符型 | 短整型 | 整型 | 長整型 | 單精度浮點型 | 雙精度浮點型 | 無類型 |
---|---|---|---|---|---|---|---|
數據類型 | char | short | int | long | float | double | void |
在32位環境中,各種數據類型的長度一般如下:
說 明 | 字符型 | 短整型 | 整型 | 長整型 | 單精度浮點型 | 雙精度浮點型 |
---|---|---|---|---|---|---|
數據類型 | char | short | int | long | float | double |
長 度 | 1 | 2 | 4 | 4 | 4 | 8 |
4.如何在字符串中書寫或者輸出長文本
#include <stdio.h>
int main()
{
puts(
"C語言中文網,一個學習C語言和C++的網站,他們堅持用工匠的精神來打磨每一套教程。"
"堅持做好一件事情,做到極致,讓自己感動,讓用戶心動,這就是足以傳世的作品!"
"C語言中文網的網址是:http://c.biancheng.net"
);
return 0;
}
本節講到的 puts、printf,以及後面要講到的 fprintf、fputs 等與字符串輸出有關的函數,都支持這種寫法。
二、整型數據類型的長度及輸出
2.1整型數據類型的長度
對於 32 位的 Windows、Linux 和 Mac OS,short 的長度爲 2 個字節,int 爲 4 個字節,long 也爲 4 個字節。PC和服務器上的 32 位系統佔有率也在慢慢下降,嵌入式系統使用 32 位越來越多。
在 64 位環境下,不同的操作系統會有不同的結果,如下所示:
操作系統 | short | int | long |
---|---|---|---|
Win64(64位 Windows) | 2 | 4 | 4 |
類Unix系統(包括 Unix、Linux、Mac OS、BSD、Solaris 等) | 2 | 4 | 8 |
目前我們使用較多的PC系統爲 Win XP、Win 7、Win 8、Win 10、Mac OS、Linux,在這些系統中,short 和 int 的長度都是固定的,分別爲 2 和 4,大家可以放心使用,只有 long 的長度在 Win64 和類 Unix 系統下會有所不同,使用時要注意移植性。
要注意可以通過sizeof操作符來獲取某個數據類型的長度,即所佔字節大小。
#include <stdio.h>
int main()
{
short a = 10;
int b = 100;
int short_length = sizeof(a);
int int_length = sizeof(b);
int long_length = sizeof(long);
int char_length = sizeof(char);
printf("short=%d, int=%d, long=%d, char=%d\n", short_length, int_length, long_length, char_length);
return 0;
}
2.2 不同整型的輸出
使用不同的格式控制符可以輸出不同類型的整數,它們分別是:
%hd
用來輸出 short int 類型,hd 是 short decimal 的簡寫;%d
用來輸出 int 類型,d 是 decimal 的簡寫;%ld
用來輸出 long int 類型,ld 是 long decimal 的簡寫。
讀者需要注意,當格式控制符和數據類型不匹配時,編譯器會給出警告,提示程序員可能會存在風險。
2.3 不同類型的整型數據格式的取值範圍與數據溢出情況分析
我們可以計算出所有有符號數的取值範圍(括號內爲假設的長度):
char | short | int(4個字節) | long(8個字節) | |
---|---|---|---|---|
最小值 | -27 = -128 | -215 = -32,768 ≈ -3.2萬 | -231 = -2,147,483,648 ≈ -21億 | -263 ≈ -9.22×1018 |
最大值 | 27 - 1= 127 | 215 - 1 = 32,767 ≈ 3.2萬 | 231 - 1 = 2,147,483,647 ≈ 21億 | 263 - 1≈ 9.22×1018 |
若存在數據溢出的情況:
#include <stdio.h>
int main()
{
unsigned int a = 0x100000000;
int b = 0xffffffff;
printf("a=%u, b=%d\n", a, b);
return 0;
}
運行結果:a=0, b=-1
變量 a 爲 unsigned int 類型,長度爲 4 個字節,能表示的最大值爲 0xFFFFFFFF,而 0x100000000 = 0xFFFFFFFF + 1,佔用33位,已超出 a 所能表示的最大值,所以發生了溢出,導致最高位的 1 被截去,剩下的 32 位都是0。也就是說,a 被存儲到內存後就變成了 0,printf 從內存中讀取到的也是 0。
變量 b 是 int 類型的有符號數,在內存中以補碼的形式存儲。0xffffffff 的數值位的原碼爲 1111 1111 …… 1111 1111,共 32 位,而 int 類型的數值位只有 31 位,所以最高位的 1 會覆蓋符號位,數值位只留下 31 個 1,所以 b 的原碼爲:
1111 1111 …… 1111 1111
這也是 b 在內存中的存儲形式。
當 printf 讀取到 b 時,由於最高位是 1,所以會被判定爲負數,要從補碼轉換爲原碼:
[1111 1111 …… 1111 1111]補
= [1111 1111 …… 1111 1110]反
= [1000 0000 …… 0000 0001]原
= -1
最終 b 的輸出結果爲 -1。
三、二進制數、八進制數和十六進制數的表示
3.1 二進制數
二進制由 0 和 1 兩個數字組成,使用時必須以0b
或0B
(不區分大小寫)開頭,例如:
//合法的二進制
int a = 0b101; //換算成十進制爲 5
int b = -0b110010; //換算成十進制爲 -50
int c = 0B100001; //換算成十進制爲 33
//非法的二進制
int m = 101010; //無前綴 0B,相當於十進制
int n = 0B410; //4不是有效的二進制數字
讀者請注意,標準的C語言並不支持上面的二進制寫法,只是有些編譯器自己進行了擴展,才支持二進制數字。換句話說,並不是所有的編譯器都支持二進制數字,只有一部分編譯器支持,並且跟編譯器的版本有關係。
下面是實際測試的結果:
- Visual C++ 6.0 不支持。
- Visual Studio 2015 支持,但是 Visual Studio 2010 不支持;可以認爲,高版本的 Visual Studio 支持二進制數字,低版本的 Visual Studio 不支持。
- GCC 4.8.2 支持,但是 GCC 3.4.5 不支持;可以認爲,高版本的 GCC 支持二進制數字,低版本的 GCC 不支持。
- LLVM/Clang 支持(內嵌於 Mac OS 下的 Xcode 中)。
3.2 八進制數
八進制由 0~7 八個數字組成,使用時必須以0
開頭(注意是數字 0,不是字母 o),例如:
/合法的八進制數
int a = 015; //換算成十進制爲 13
int b = -0101; //換算成十進制爲 -65
int c = 0177777; //換算成十進制爲 65535
3.3 十六進制
十六進制由數字 0~9、字母 A~F 或 a~f(不區分大小寫)組成,使用時必須以0x
或0X
(不區分大小寫)開頭,例如:
//合法的十六進制
int a = 0X2A; //換算成十進制爲 42
int b = -0XA0; //換算成十進制爲 -160
int c = 0xffff; //換算成十進制爲 65535
3.4 這幾種進制的輸出格式
short | int | long | unsigned short | unsigned int | unsigned long | |
---|---|---|---|---|---|---|
八進制 | %ho | %o | %lo | %ho | %o | %lo |
十進制 | %hd | %d | %ld | %hu | %u | %lu |
十六進制 | %hx 或者 %hX | %x 或者 %X | %lx 或者 %lX | %hx 或者 %hX | %x 或者 %X | %lx 或者 %lX |
十六進制數字的表示用到了英文字母,有大小寫之分,要在格式控制符中體現出來:
- %hx、%x 和 %lx 中的
x
小寫,表明以小寫字母的形式輸出十六進制數; - %hX、%X 和 %lX 中的
X
大寫,表明以大寫字母的形式輸出十六進制數。
八進制數字和十進制數字不區分大小寫,所以格式控制符都用小寫形式。
區分不同進制數字的一個簡單辦法就是,在輸出時帶上特定的前綴。在格式控制符中加上#
即可輸出前綴,例如 %#x、%#o、%#lX、%#ho 等,請看下面的代碼:
#include <stdio.h>
int main()
{
short a = 0b1010110; //二進制數字
int b = 02713; //八進制數字
long c = 0X1DAB83; //十六進制數字
printf("a=%#ho, b=%#o, c=%#lo\n", a, b, c); //以八進制形似輸出
printf("a=%hd, b=%d, c=%ld\n", a, b, c); //以十進制形式輸出
printf("a=%#hx, b=%#x, c=%#lx\n", a, b, c); //以十六進制形式輸出(字母小寫)
printf("a=%#hX, b=%#X, c=%#lX\n", a, b, c); //以十六進制形式輸出(字母大寫)
return 0;
}
運行結果:
a=0126, b=02713, c=07325603
a=86, b=1483, c=1944451
a=0x56, b=0x5cb, c=0x1dab83
a=0X56, b=0X5CB, c=0X1DAB83
- 注意,整數和小數的有符號數在內存中都是以補碼形式存儲的,這樣方便加減運算。
- 所以在將無符號數輸出爲有符號數的時候,需要考慮將無符號數看做是有符號數的補碼,並進行從補碼到原碼的變換。
四、小數的輸出
小數也可以使用 printf 函數輸出,包括十進制形式和指數形式,它們對應的格式控制符分別是:
- %f 以十進制形式輸出 float 類型;
- %lf 以十進制形式輸出 double 類型;
- %e 以指數形式輸出 float 類型,輸出結果中的 e 小寫;
- %E 以指數形式輸出 float 類型,輸出結果中的 E 大寫;
- %le 以指數形式輸出 double 類型,輸出結果中的 e 小寫;
- %lE 以指數形式輸出 double 類型,輸出結果中的 E 大寫。
下面的代碼演示了小數的表示以及輸出:
#include <stdio.h>
#include <stdlib.h>
int main()
{
float a = 0.302;
float b = 128.101;
double c = 123;
float d = 112.64E3;
double e = 0.7623e-2;
float f = 1.23002398;
printf("a=%e \nb=%f \nc=%lf \nd=%lE \ne=%lf \nf=%f\n", a, b, c, d, e, f);
return 0;
}