C程式設計語言(第二版 ) 讀書筆記

來源:互聯網
上載者:User

終於把這本被稱為C語言聖經的書看完了。書的封面如下:

摘抄筆記如下:

page 16
EOF值為-1,所以char類型是無法存放該值的,需要用int類型。聯想到我們常寫的
while(scanf("%d",&a)!=EOF)其實scanf是一個int類型的函數,在類型匹配的時候傳回值為1,在類型不符的時候傳回值為0,在沒有資料讀入的時候傳回值為-1,這和EOF是一致的。

page53
x=f()+g(),該語句在編譯的時候其實不一定是從左至右執行的,具體情況視環境而定
printf("%d %d",++n,power(n,2))這樣的寫法就不是很正確

page84
局部變數問題,就算在if裡面也算是局部變數,例如下面就是正確的

int x;int y;f(double x){  double y;}

page90
宏替換,如果在替換文本中參數名以#作為首碼,那麼它們將被由實際變元替換的參數擴充成帶引號的字串。
#define dprint(expr) printf(#expr"=%g\n",expr)
使用時dprint(x/y)
宏被替換為printf("x/y" "=%g\n",x/y) 也就是printf("x/y=%g\n",x/y)
##是一種串連實際變元的手段,替換文本參數用此串連,##與前後的空白符被刪除
#define paste(front,back) front## back
paste(name,1)  建立name1

page115
main(int argc,char *agrv[])
main中的這兩個參數在使用命令列的情況下使用,第一個參數的值為程式執行時命令列中變元的數目,第二個變元為一個指向字串數組的指標,其中每個字串對應一個變元。
例echo hello,world 將列印出hello,world

#include<stdio.h>main(int argc,char *argv[]){while(--agrc>0)printf("%s%s",argv[i],(i<argc-1)?" ":"");printf("\n");    return 0;}

page138
千萬不要以為一個結構的大小等於它各成員大小的和,因為對不同對象有不同對齊需求,所以結構中會出現洞。例如

struct {char c;int i;}

需要八個位元組而不是五個位元組,sizeof[注意sizeof是運算子不是函數]運算子返回結構大小的正確值

page147
union中所有的元素都位於同一地區,保證地區大小能夠容納擁有最大位元組類型的元素,從某種意義上來說,聯合也是一個結構,只不過是其所有成員相對於基地址的位移量為0。

補充:聯合的作用

C中的union和struct的區別,為什麼要發明union? 
union和struct的區別在於: 

1、對於一個union類型的變數,所有成員變數共用一塊記憶體,該記憶體的大小有這些成員變數中長度最大的一個來決定 

2、union分配的記憶體是連續的,這一點非常重要。 

更具體的看這裡,還有測試代碼呢(附件1): 

那為什麼要發明union呢?這是由於union的特性決定的,特別是上述的第二點,因為struct中成員變數雖然記憶體都是獨立的,但是struct不能保證分配的記憶體是連續的。 

舉個例子:CPU的ax寄存器分為ah和al兩部分,我們現在要給其賦值,就可以採用union: 

union _ax_register { int i; // 4Bytes, union將按此分配一個4位元組的連續記憶體 unsigned short ah; // 2 Bytes unsigned short al; // 2 Bytes } ax_register; 

現在,給ax_register.i賦值,其高16bit就會賦給ah,低16bit就會賦給al,是不是很方便呢? 

再舉個例子,IP地址,我們使用union,就可以直接給他賦一個int值,就能給IP的四個段同時賦值,如果用struct,就麻煩多嘍,如下: 

union _ip_address { int i; // spaceholder unsigned char ip_first_num; unsigned char ip_second_num; unsigned char ip_third_num; unsigned char ip_fourth_num; } ip_address; 

這樣,給ip_address.i 賦值,就自動將其8bit 的賦給了四個IP欄位。是不是很方便?更方便的是,現在要比較兩個IP地址的大小,只要比較這個int值就OK了。原因就在於它們共用同一片記憶體。union的壞處是原先的資料很容易被後寫入的資料抹去,所以不宜用來進行資料處理。一般用來儲存資料就行了。

page147
位欄位,個人感覺是用來儲存某個資料的資訊的,這裡把某個資料的是否是關鍵字,是否是靜態變數,是否是全域變數進列欄位壓縮儲存。即程式中每個標識符都有與其關聯的特定資訊,類似於電腦網路中的掩碼。

struct {unsigned int is_keyword:1;unsigned int is_extern :1;unsigned int is_static:1;}flags;

這裡定義一個變數flags,只包含三個一位欄位。flags.is_exteern=1;可以直接這樣進行賦值

第七章輸入輸出 覺得沒有太大用,粗略瀏覽

總結:大一學過C語言,大二學過C++,所以這本書對我來說可能沒有別人說的那麼神奇,但是我還是學到了一點東西。第七章大致看了一點,第八章和後面的附錄沒看,習題也沒做幾道,希望以後有時間再讀。

最後說一個問題,今天在實驗室討論的很激烈:

#include <stdio.h>int main(){const int a=4;int *b=(int *)(&a);printf("%d\n",&a);printf("%d\n",b);*b=10;printf("%d\n",a);printf("%d\n",*b);return 0;}

說明如下:a是const類型,b是指向a地址的指標,首先輸出地址,然後把b的值給改變了,再輸入a和*b的值。如果按照常理推斷,*b和a表示的是同一個記憶體,所以改變*b也會改變a,但是結果呢?

輸出如下:

可以看到a的值並沒有改變,這與const類型有關,去掉const後輸出是按照常理推斷的10和10。

究竟為什麼呢?

按照反組譯碼後,發現編譯器發現a是const後直接把4傳給了printf根本沒有從記憶體位址中去取值,所以導致輸出不一樣。看來又學到點東西了,討論是一種協助人進步的方式。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.