# 練習7:更多變量和一些算術
> 原文:[Exercise 7: More Variables, Some Math](http://c.learncodethehardway.org/book/ex7.html)
> 譯者:[飛龍](https://github.com/wizardforcel)
你可以通過聲明`int`,`float`,`char`和`double`類型的變量,來對它們做更多的事情,讓我們來熟悉它們吧。接下來我們會在各種數學表達式中使用它們,所以我會向你介紹C的基本算術操作。
```c
int main(int argc, char *argv[])
{
int bugs = 100;
double bug_rate = 1.2;
printf("You have %d bugs at the imaginary rate of %f.\n",
bugs, bug_rate);
long universe_of_defects = 1L * 1024L * 1024L * 1024L;
printf("The entire universe has %ld bugs.\n",
universe_of_defects);
double expected_bugs = bugs * bug_rate;
printf("You are expected to have %f bugs.\n",
expected_bugs);
double part_of_universe = expected_bugs / universe_of_defects;
printf("That is only a %e portion of the universe.\n",
part_of_universe);
// this makes no sense, just a demo of something weird
char nul_byte = '\0';
int care_percentage = bugs * nul_byte;
printf("Which means you should care %d%%.\n",
care_percentage);
return 0;
}
```
下面是這一小段無意義代碼背后發生的事情:
ex7.c:1-4
C程序的通常開始。
ex7.c:5-6
為一些偽造的bug數據聲明了一個`int`和一個`double`變量。
ex7.c:8-9
打印這兩個變量,沒有什么新東西。
ex7.c:11
使用了一個新的類型`long`來聲明一個大的數值,它可以儲存比較大的數。
ex7.c:12-13
使用`%ld`打印出這個變量,我們添加了個修飾符到`%d`上面。添加的"l"表示將它當作長整形打印。
ex7.c:15-17
只是更多的算術運算和打印。
ex7.c:19-21
編撰了一段你的bug率的描述,這里的計算非常不精確。結果非常小,所以我們要使用`%e`以科學記數法的形式打印它。
ex7.c:24
以特殊的語法`'\0'`聲明了一個字符。這樣創建了一個“空字節”字符,實際上是數字0。
ex7.c:25
使用這個字符乘上bug的數量,它產生了0,作為“有多少是你需要關心的”的結果。這條語句展示了你有時會碰到的丑陋做法。
ex7.c:26-27
將它打印出來,注意我使用了`%%`(兩個百分號)來打印一個`%`字符。
ex7.c:28-30
`main`函數的結尾。
這一段代碼只是個練習,它演示了許多算術運算。在最后,它也展示了許多你能在C中看到,但是其它語言中沒有的技巧。對于C來說,一個“字符”同時也是一個整數,雖然它很小,但的確如此。這意味著你可以對它做算術運算,無論是好是壞,許多軟件中也是這樣做的。
在最后一部分中,你第一次見到C語言是如何直接訪問機器的。我們會在后面的章節中深入。
## 你會看到什么
通常,你應該看到如下輸出:
```shell
$ make ex7
cc -Wall -g ex7.c -o ex7
$ ./ex7
You have 100 bugs at the imaginary rate of 1.200000.
The entire universe has 1073741824 bugs.
You are expected to have 120.000000 bugs.
That is only a 1.117587e-07 portion of the universe.
Which means you should care 0%.
$
```
## 如何使它崩潰
像之前一樣,向`printf`傳入錯誤的參數來使它崩潰。對比`%c`,看看當你使用`%s`來打印`nul_byte`變量時會發生什么。做完這些之后,在`Valgrind`下運行它看看關于你的這次嘗試會輸出什么。
## 附加題
+ 把為`universe_of_defects`賦值的數改為不同的大小,觀察編譯器的警告。
+ 這些巨大的數字實際上打印成了什么?
+ 將`long`改為`unsigned long`,并試著找到對它來說太大的數字。
+ 上網搜索`unsigned`做了什么。
+ 試著自己解釋(在下個練習之前)為什么`char`可以和`int`相乘。
- 笨辦法學C 中文版
- 前言
- 導言:C的笛卡爾之夢
- 練習0:準備
- 練習1:啟用編譯器
- 練習2:用Make來代替Python
- 練習3:格式化輸出
- 練習4:Valgrind 介紹
- 練習5:一個C程序的結構
- 練習6:變量類型
- 練習7:更多變量和一些算術
- 練習8:大小和數組
- 練習9:數組和字符串
- 練習10:字符串數組和循環
- 練習11:While循環和布爾表達式
- 練習12:If,Else If,Else
- 練習13:Switch語句
- 練習14:編寫并使用函數
- 練習15:指針,可怕的指針
- 練習16:結構體和指向它們的指針
- 練習17:堆和棧的內存分配
- 練習18:函數指針
- 練習19:一個簡單的對象系統
- 練習20:Zed的強大的調試宏
- 練習21:高級數據類型和控制結構
- 練習22:棧、作用域和全局
- 練習23:認識達夫設備
- 練習24:輸入輸出和文件
- 練習25:變參函數
- 練習26:編寫第一個真正的程序
- 練習27:創造性和防御性編程
- 練習28:Makefile 進階
- 練習29:庫和鏈接
- 練習30:自動化測試
- 練習31:代碼調試
- 練習32:雙向鏈表
- 練習33:鏈表算法
- 練習34:動態數組
- 練習35:排序和搜索
- 練習36:更安全的字符串
- 練習37:哈希表
- 練習38:哈希算法
- 練習39:字符串算法
- 練習40:二叉搜索樹
- 練習41:將 Cachegrind 和 Callgrind 用于性能調優
- 練習42:棧和隊列
- 練習43:一個簡單的統計引擎
- 練習44:環形緩沖區
- 練習45:一個簡單的TCP/IP客戶端
- 練習46:三叉搜索樹
- 練習47:一個快速的URL路由
- 后記:“解構 K&R C” 已死