1. 字符型(char)簡介
字符型(char)用于儲(chǔ)存字符(character),如英文字母或標(biāo)點(diǎn)。嚴(yán)格來說,char 其實(shí)也是整數(shù)類型(integer type),因?yàn)?/span> char 類型儲(chǔ)存的實(shí)際上是整數(shù),而不是字符。計(jì)算機(jī)使用特定的整數(shù)編碼來表示特定的字符。美國普遍使用的編碼是 ASCII(American Standard Code for Information Interchange 美國信息交換標(biāo)準(zhǔn)編碼)。例如:ASCII 使用 65 來代表大寫字母 A,因此存儲(chǔ)字母 A 實(shí)際上存儲(chǔ)的是整數(shù)65。注意:許多IBM大型機(jī)使用另一種編碼——EBCDIC(Extended Binary-Coded Decimal Interchange Code 擴(kuò)充的二進(jìn)制編碼的十進(jìn)制交換碼);不同國家的計(jì)算機(jī)使用的編碼可能完全不同。
ASCII 的范圍是 0 到 127,故而 7 位(bit)就足以表示全部 ASCII。char 一般占用 8 位內(nèi)存單元,表示ASCII綽綽有余。許多系統(tǒng)都提供擴(kuò)展ASCII(Extended ASCII),并且所需空間仍然在 8 位以內(nèi)。注意,不同的系統(tǒng)提供的擴(kuò)展 ASCII 的編碼方式可能有所不同!
許多字符集超出了 8 位所能表示的范圍(例如漢字字符集),使用這種字符集作為基本字符集的系統(tǒng)中,char 可能是 16 位的,甚至可能是 32 位的。總之,C 保證 char 占用空間的大小足以儲(chǔ)存系統(tǒng)所用的基本字符集的編碼。C 語言定義一個(gè)字節(jié)(byte)的位數(shù)為 char 的位數(shù),所以一個(gè)字節(jié)可能是 16 位,也可能是 32 位,而不僅僅限于 8 位。
2. 聲明字符型變量
字符型變量的聲明方式和其它類型變量的聲明方式一樣:
char good;
char better, best;
以上代碼聲明了三個(gè)字符型變量:good、better,和 best。
3. 字符常量與初始化
我們可以使用以下語句來初始化字符型變量:
char ch = 'A';
這個(gè)語句把 ch 的值初始化為 A 的編碼值。在這個(gè)語句中,'A' 是字符常量。C 語言中,使用單引號(hào)把字符引起來就構(gòu)成字符常量。我們來看另外一個(gè)例子:
char fail; /* 聲明一個(gè)字符型變量 */
fail = 'F'; /* 正確 */
fail = "F"; /* 錯(cuò)!"F" 是字符串字面量 */
把字符用雙引號(hào)引起來構(gòu)成字符串字面量,所以第三個(gè)語句是錯(cuò)誤的。我們會(huì)在后續(xù)的教程中討論字符串,現(xiàn)在暫且把它放下。
因?yàn)樽址麑?shí)質(zhì)上是以數(shù)字的形式存儲(chǔ)的,所以我們可以直接使用數(shù)字來初始化字符變量,或者給字符變量賦值:
char ch = 65; /* 不好的風(fēng)格 */
在 ASCII 中,A 的編碼是 65,所以對(duì)于使用 ASCII 的系統(tǒng)來說,這個(gè)語句等同于 char ch = 'A';。使用非 ASCII 的系統(tǒng)中,65 代表的不一定是 A,而有可能是其它任何字符,所以使用數(shù)字來初始化字符變量,或者給字符變量賦值是一種不好的風(fēng)格,因?yàn)橐浦残蕴盍耍〉牵褂米址A浚ɡ?/span> 'A')來初始化字符變量,或者給字符變量賦值,字符變量得到的一定是我們所期待的字符的編碼值。例如:
char ch = 'A';
無論在使用任何編碼的系統(tǒng)中,ch 都能夠得到字符 A 所對(duì)應(yīng)的編碼值。這是因?yàn)榫幾g器會(huì)自動(dòng)把 'A' 轉(zhuǎn)化成 A 所對(duì)應(yīng)的編碼值。因此,我們應(yīng)該使用字符常量來初始化字符變量,或者給字符變量賦值;而不要用數(shù)字。
有趣的是,C 使用 int 類型來處理字符常量,而不是 char 類型。例如,在使用32位 int 的ASCII 系統(tǒng)中,以下代碼
char ch = 'C';
'C' 的編碼值 67 被存儲(chǔ)于 32 位的內(nèi)存單元中;不過 ch 仍然存儲(chǔ)于 8 位的內(nèi)存單元中,只是它的值變成了 67。因此,我們可以定義形如 'good' 的古怪字符常量。因?yàn)槊總€(gè)字符的編碼值占用 8 位的內(nèi)存單元,所以這個(gè)常量剛好可以存儲(chǔ)于 32 位的內(nèi)存單元。然而,用這種字符常量初始化字符變量,或者給字符變量賦值的話,導(dǎo)致的結(jié)果是,字符變量只能得到字符常量的最后 8 位。也就是說,以下代碼
char ch = 'good';
ch 得到的是 'd' 的值。
以后,在沒有特殊說明的情況下,我們討論的都是 ASCII。
ASCII 表
ASCII值 |
控制字符 |
ASCII值 |
控制字符 |
ASCII值 |
控制字符 |
ASCII值 |
控制字符 |
0 |
NUL |
32 |
(space) |
64 |
@ |
96 |
` |
1 |
SOH |
33 |
! |
65 |
A |
97 |
a |
2 |
STX |
34 |
" |
66 |
B |
98 |
b |
3 |
ETX |
35 |
# |
67 |
C |
99 |
c |
4 |
EOT |
36 |
$ |
68 |
D |
100 |
d |
5 |
ENQ |
37 |
% |
69 |
E |
101 |
e |
6 |
ACK |
38 |
& |
70 |
F |
102 |
f |
7 |
BEL |
39 |
' |
71 |
G |
103 |
g |
8 |
BS |
40 |
( |
72 |
H |
104 |
h |
9 |
HT |
41 |
) |
73 |
I |
105 |
i |
10 |
LF |
42 |
* |
74 |
J |
106 |
j |
11 |
VT |
43 |
+ |
75 |
K |
107 |
k |
12 |
FF |
44 |
, |
76 |
L |
108 |
l |
13 |
CR |
45 |
- |
77 |
M |
109 |
m |
14 |
SO |
46 |
. |
78 |
N |
110 |
n |
15 |
SI |
47 |
/ |
79 |
O |
111 |
o |
16 |
DLE |
48 |
0 |
80 |
P |
112 |
p |
17 |
DC1 |
49 |
1 |
81 |
Q |
113 |
q |
18 |
DC2 |
50 |
2 |
82 |
R |
114 |
r |
19 |
DC3 |
51 |
3 |
83 |
S |
115 |
s |
20 |
DC4 |
52 |
4 |
84 |
T |
116 |
t |
21 |
NAK |
53 |
5 |
85 |
U |
117 |
u |
22 |
SYN |
54 |
6 |
86 |
V |
118 |
v |
23 |
ETB |
55 |
7 |
87 |
W |
119 |
w |
24 |
CAN |
56 |
8 |
88 |
X |
120 |
x |
25 |
EM |
57 |
9 |
89 |
Y |
121 |
y |
26 |
SUB |
58 |
: |
90 |
Z |
122 |
z |
27 |
ESC |
59 |
; |
91 |
[ |
123 |
{ |
28 |
FS |
60 |
< |
92 |
\ |
124 |
| |
29 |
GS |
61 |
= |
93 |
] |
125 |
} |
30 |
RS |
62 |
> |
94 |
^ |
126 |
~ |
31 |
US |
63 |
? |
95 |
_ |
127 |
DEL |
NUL 空字符 |
VT 垂直制表 |
SYN 同步 |
SOH 標(biāo)題開始 |
FF 走紙控制 |
ETB 信息組傳送結(jié)束 |
STX 正文開始 |
CR 回車 |
CAN 作廢 |
ETX 正文結(jié)束 |
SO 移位輸出 |
EM 媒介結(jié)束 End of Medium |
EOT 傳輸結(jié)束 |
SI 移位輸入 |
SUB 換置 |
ENQ 詢問字符 |
DLE Data Link Escape |
ESC Escape |
ACK 確認(rèn) |
DC1 設(shè)備控制1 |
FS 文件分隔符 |
BEL 響鈴 |
DC2 設(shè)備控制2 |
GS 組分隔符 |
BS 退格 |
DC3 設(shè)備控制3 |
RS 記錄分隔符 |
HT 橫向制表 |
DC4 設(shè)備控制4 |
US 單元分隔符 |
LF 換行 |
NAK 否定 |
DEL 刪除 |
參考資料:C Primer Plus, 5th Edtion By Stephen Prata
The C Programming Language 2e By K&R
本文版權(quán)歸 螞蟻的 C/C++ 標(biāo)準(zhǔn)編程 以及 作者 antigloss 共同所有,轉(zhuǎn)載請(qǐng)注明原作者和出處。謝謝。
不可打印字符(Nonprinting Characters)
有些 ASCII 字符是不可打印的。例如退格、另起一行、警報(bào)等。C 語言提供了兩種方法來表示這種不可打印字符。
第一種方法是使用 ASCII 編碼。例如,ASCII 編碼中,7 用于表示警報(bào):
char beep = 7;
第二種方法是使用特殊符號(hào)序列,也就是所謂的轉(zhuǎn)義字符(escape sequences)。參見下表:
轉(zhuǎn)義字符 含義
\a 警報(bào)( Alert (ANSI C) )
\b 退格(Backspace)
\f 換頁(Form feed)
\n 換行(Newline)
\r 回車(Carriage return)
\t 水平制表符(Horizontal tab)
\v 垂直制表符(Vertical tab)
\\ 反斜桿( Backslash (\) )
\' 單引號(hào)( Single quote (') )
\" 雙引號(hào)( Double quote (") )
\? 問號(hào)( Question mark (?) )
\0oo 八進(jìn)制數(shù)( Octal value (o 代表一個(gè)八進(jìn)制數(shù)字) )
\xhh 十六進(jìn)制數(shù)( Hexadecimal value (h 代表一個(gè)十六進(jìn)制數(shù)字) )
給變量賦值的時(shí)候,轉(zhuǎn)義字符必須使用單引號(hào)引住。例如:
char nl = '\n';
下面我們?cè)敿?xì)學(xué)習(xí)每個(gè)轉(zhuǎn)移字符的含義。
\a(警報(bào))是 ANSI C89 添加的,用于產(chǎn)生可聽或者可視的警報(bào)。\a 產(chǎn)生的效果取決于硬件。一般來說,輸出 \a 會(huì)產(chǎn)生鳴響。但是在某些系統(tǒng),輸出 \a 不會(huì)產(chǎn)生任何效果,或者僅僅顯示一個(gè)特殊字符。標(biāo)準(zhǔn)明確指出,\a 不應(yīng)該改變當(dāng)前活躍位置(active position)。所謂活躍位置,是指顯示設(shè)備(顯示器、打字機(jī)、打印機(jī)等等)顯示下一個(gè)字符的位置。以顯示器為例,活躍位置就是指光標(biāo)所處的位置,輸出 \a 不會(huì)導(dǎo)致光標(biāo)移動(dòng)位置。
\b、\f、\n、\r、\t,以及 \v 都是輸出設(shè)備控制符。退格符(\b)使當(dāng)前行的活躍位置后退一個(gè)位置。換頁符(\f)使活躍位置跳到下一頁的開端。注:換頁符可用于控制打印機(jī)換頁,但不會(huì)導(dǎo)致 PC 機(jī)的顯示屏換頁。換行符(\n)使活躍位置跳到下一行的開端。回車符 ( \r ) 使活躍位置返回當(dāng)前行的開端。水平制表符(\t)使活躍位置移動(dòng)若干個(gè)位置(通常是8個(gè))。垂直制表符(\v)使活躍位置換若干行。注:\v可用于控制打印機(jī)換若干行,但是不會(huì)導(dǎo)致PC機(jī)的顯示屏換行。
\\、\',以及 \" 使我們可以把 \,' 和 " 用作字符常量。如果要打印以下句子:
"\ is called 'backslash'."
我們需要使用如下語句:
printf("\"\\ is called \'backslash\'.\"");
或者
printf("\"\\ is called 'backslash'.\"");
注意,在字符串字面量中,無論寫 \' 還是 ',輸出都是一樣的。但是,在給字符變量賦值時(shí),一定要寫 \'。例如:
char ch = '''; /* 錯(cuò)誤! */
char ch = '\''; /* 正確。 */
\0oo 和 \xhh 是ASCII碼的兩種特殊表示形式。如果想用八進(jìn)制ASCII碼表示字符,可以在八進(jìn)制數(shù)前面加上 \ ,然后用單引號(hào)引起來。例如:
beep = '\007'; /* \007 代表 \a */
打頭的那些0可以省略,也就是說,寫成 '\07' 或者 '\7' 都一樣。無論有沒有打頭的0 ,7 都會(huì)被當(dāng)成八進(jìn)制數(shù)處理。
從 C89 開始,C提供了用十六進(jìn)制表示字符常量的方法:在反斜桿后面寫一個(gè) x ,然后再寫 1 到 3 個(gè)十六進(jìn)制數(shù)字。例如:
nl = '\xa'; /* \xa 代表 \n */
注意:使用ASCII碼時(shí),要注意區(qū)分數(shù)字和數(shù)字字符。例如:字符4的ASCII碼是52 ,'4' 代表字符 4 ,而不是數(shù)字4。此外,盡管 '\n' 和 '\xa' ,'\a' 和 '\007' 是等價(jià)的,但是我們應(yīng)該盡可能使用 '\n' 和 '\a' ,而不要用 '\xa' 和 '\007' 。這是因?yàn)榍罢咭锥⒈阌谟洃洠乙浦残愿摺6笳咧粚?duì)使用ASCII碼的系統(tǒng)有效。
參考資料:C Primer 5th Edition
C99 標(biāo)準(zhǔn)
本文版權(quán)歸 螞蟻的 C/C++ 標(biāo)準(zhǔn)編程 以及 作者 antigloss 共同所有,轉(zhuǎn)載請(qǐng)注明原作者和出處。謝謝。
一、字符輸出
printf 函數(shù)使用 %c 表示輸出字符。因?yàn)樽址且?/span> 1 字節(jié)整數(shù)的形式存取的,所以,如果使用 %d 的話,輸出的會(huì)是整數(shù)。例如:
/* 這個(gè)程序輸出字符以及字符的整數(shù)編碼 */
#include <stdio.h>
int main(void)
{
char ch;
printf("Please enter a character.\n");
scanf("%c", &ch); /* 由用戶輸入一個(gè)字符 */
printf("The code for %c is %d.\n", ch, ch);
return 0;
}
請(qǐng)各位自行編譯執(zhí)行此程序,查看其執(zhí)行結(jié)果。輸入字符后記得要按回車鍵。
printf 函數(shù)輸出 ch 的值兩次,第一次以字符的形式輸出(因?yàn)楦袷较薅ǚ麨?/span> %c),第二次以十進(jìn)制整數(shù)的形式輸出(因?yàn)楦袷较薅ǚ?/span> %d)。注意:格式限定符只是用于指定數(shù)據(jù)的輸出形式,而不是用來指定數(shù)據(jù)怎么存儲(chǔ)。
二、字符類型的符號(hào)
某些編譯器中,char 默認(rèn)是有符號(hào)的(signed)。對(duì)于這類型的編譯器來說,char 的表示范圍通常是 -128 到 127 。而另外一些編譯器中,char 默認(rèn)是無符號(hào)的(unsigned)。對(duì)于這類型的編譯器來說,char 的表示范圍通常是 0 到 255 。一般來說,編譯器的使用說明會(huì)注明它默認(rèn)把 char 當(dāng)作有符號(hào)的還是無符號(hào)的。
從 C89 開始,我們可以使用關(guān)鍵字 signed 和 unsigned 來修飾 char 。這么一來,無論編譯器默認(rèn) char 是有符號(hào)的也好,無符號(hào)的也罷,我們都可以用 signed char 表示有符號(hào) char ,也可以用 unsigned char 表示無符號(hào) char 。
參考資料:C Primer 5th Edition
C99 標(biāo)準(zhǔn)
本文版權(quán)歸 螞蟻的 C/C++ 標(biāo)準(zhǔn)編程 以及 作者 antigloss 共同所有,轉(zhuǎn)載請(qǐng)注明原作者和出處。謝謝。
ANSI C 提供了3種字符類型,分別是char、signed char、unsigned char
char相當(dāng)于signed char或者unsigned char,但是這取決于編譯器!
這三種字符類型都是按照1個(gè)字節(jié)存儲(chǔ)的,可以保存256個(gè)不同的值。
signed char取值范圍是 -128 到 127
unsigned char 取值范圍是 0 到 255
但是char究竟相當(dāng)于signed char呢還是相當(dāng)于unsigned char呢??
這就是char和int的不同之處!
int==signed int,但是char不能簡單以為==signed char
要確定char究竟等同什么要基于不同的編譯器做測試
大多數(shù)機(jī)器使用補(bǔ)碼來存儲(chǔ)整數(shù),在這些機(jī)器中按照整數(shù)類型存儲(chǔ)的-1的所有位均是1
假設(shè)我的機(jī)器也是如此存儲(chǔ),就能據(jù)此判斷char究竟是等于signed char還是unsigned char
程序如下:
[oracle@test c]$ vi test_char.c
#include <stdio.h>
int main()
{
char a=-1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}