讀書筆記之:你必須知道的495個C語言問題

來源:互聯網
上載者:User

《你必須知道的495個C語言問題》這本書中列出了495個C語言中的問題,這些問題都比較都代表性,這是真實的有人提出的問題,然後作者給出瞭解答。這個有對應的網站:http://c-faq-chn.sourceforge.net/

2.12 怎樣向資料檔案讀寫結構體
  使用fwrite()編寫結構相對簡單
  fwrite(&some_struct,sizeof somestruct,1,fp);
  對應的fread函數可以再把它讀出來,此處fwrite受到一個結構的指標並把這個結構的記憶體映像作為位元組流寫入檔案。sizeof操作符計算出結構佔用的位元組數。
  但是這樣用記憶體映像寫出的資料檔案卻是不能夠移植的,尤其是當結構中包含浮點成員或指標的時候。結構的記憶體布局跟機器和編譯器都有關。不同的編譯器可能使用不同數量的填充位,不同機器上基本類型的大小和位元組順序也不盡相同。因此,作為記憶體映像寫出的結構在別的機器上(甚至是被別的編譯器編譯之後)不一定能被讀回來。
  同時注意如果結構包含任何指標(char*字串或指向其他資料結構的指標),則只有指標值會被寫入檔案。當它們再次被讀回來的時候可能已經失效。最後為了廣泛的可移植性,你必需用"b"標誌開啟檔案。
2.15 如何確定域在結構中的位元組位移量
ANSI C在<stddef.h>中定義了offsetof()宏,利用offsetof(structs,f)可以計算出域f在結構s中的位移量。
其實現方式為:
#define offsetof(type,f) (int)&(((type*)0)->f)
看下面的解說:
struct AAA
{
    int i;
    int j;
};
struct AAA *pAAA;
pAAA=new AAA;
這時,pAAA實際上是一個Pointer, 指向某一確定的記憶體位址,比如0x1234;
而 pAAA->i 整體是一個int型變數,其地址是&(pAAA->i) ,'&'為取址運算子;
那麼&(pAAA->i)一定等於0x1234,因為i是結構體AAA的第一個元素。
而&(pAAA->j)一定是0x1234 + 0x4 = 0x1238; 因為sizeof(int) = 4;
這個做法的巧妙之處就是:它把"0"作為上例中的pAAA,那麼 &(pAAA->j)就是j的offset

6.6 動態分配多維陣列
方案一:分配一個指標數組,然後把每個指標初始化為動態分配的行:
   int **array1=malloc(nrows*sizeof(int*));
   for(i=0;i<nrows;i++)
       array1[i]=malloc(ncolumns*sizeof(int));
   ...
   for(i=0;i<nrows;i++)
       free(array1[i]);
    free(array1);

方案二:數組內容連續,但是後來重新分配行的時候會比較困難:
   int **array2=malloc(nrows*sizeof(int*));
   array2[0]=malloc(nrows*ncolumns*sizeof(int));
   for(i=1;i<nrows;i++)
       array2[i]=array2[0]+i*ncolumns;
    free(array2[0]);
    free(array2);

11.28 malloc(0)有什麼用?返回一個null 指標還是指向0位元組的指標
ANSI/ISO標準聲稱它可能返回任意一種,其行為由實現定義。

13.15 怎樣產生一個隨機數
標準C庫有一個隨機數產生器rand。
下面是Park和MIller提供的"最小標準"的可移植隨機數產生器的C語言實現:
#define a 16807
#define m 2147483647
#define q (m/a)
#define r (m%a)
static long int seed=1;
long int PMrand()
{
    long int hi=seed/q;
    long int lo=seed%q;
    long int test=a*lo-r*hi;
    if(test>0)
        seed=test;
    else
        seed=test+m;

    return seed;
}
如果要返回(0,1)範圍內的浮點數,需要修改:
double PMrand()
....
return (double)seed/m;

13.16 怎樣獲得某一範圍內的隨機整數?
直接使用這種方法:rand()%N(試圖返回從0到N-1的整數)不好,因為許多隨機數產生器的低位並不隨機。
一種較好的方法是:
(int)((double)rand()/((double)RAND_MAX+1)*N)
如果不希望使用浮點數,另一種方法是:
rand()/(RAND_MAX/N+1)
這兩種方法都是需要知道RAND_MAX,並且假設N要遠遠小於RAND_MAX.如果N值接近RAND_MAX而隨機數產生器的範圍又不是N的整數倍,那麼這些方法都會失效,某些輸出會比其他的頻率更高。
[M,N]範圍內的隨機整數:
M+rand()/(RAND_MAX/(N-M+1)+1)

13.17 每次執行程式,rand都返回相同的數字序列,為什嗎?
這是多數偽隨機數產生器的一個特徵,它們產生的隨機數總是從同一個數字開始,然後是同一個序列。如果不需要這種可預測性,可以調用srand用真正隨機的值來初始化類比隨機數產生器的種子。
srand((unsigned int)time((tim_t*)NULL));
這個代碼可能存在的問題是:time()返回的time_t可能是浮點值,轉換到不帶正負號的整數時有可能上溢,導致不可移植。

13.18 我需要隨機的真/假值,所以,我就直接用rand()%,可是我得到交替的0,1,0,1....?
低劣的偽隨機數產生器在低位中並不隨機,很不幸,某些系統就提供這樣的偽隨機數產生器。實際上,周期為2^e的純線性同餘隨機數產生器的低n位會以2^n為周期重複,而很多e位機的隨機數就是這樣寫出來的。因此,最好使用高位。

13.20 產生高斯分布的隨機數


14.6 如何取整
簡單的方法是(int)(x+0.5)

改進方法:(int)(x<0?x-0.5:x+0.5)

14.7












 20.8 實現位元組或集合


20.9 判斷及其的位元組順序是大端還是小端
方法一:使用指標
int x=1;
if(*(char*)&x==1)
    printf("little-endian\n");
else
    printf("big-endian\n");
方法二:使用聯合
union{
    int i;
    char c;
}x;
x.i=1;
if(x.c==1)
    printf("little-endian\n");
else
    printf("big-endian\n");

20.10 調換位元組

 

20.13 計算出整數中為1的位的個數
使用查表的方式,並且採用每4位為一個單位
 static int bitcounts[]={0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
 int bitcount(unsigned int u)
 {
     int n=0;
     for(;u!=0;u>>=4)
         n++bitcounts[u&0xf];
     return n;
 }
  20.18 交換兩個變數的值


20.24 實現異或的宏
#define XOR(a,b) ((a)&&!(b)||!(a)&&(b))
#define XOR(a,b) (!!(a)^!!(b)) //兩次取反,嚴格0/1正常化
#define XOR(a,b) (!!(a)!=!!(b))
#define XOR(a,b) (!(a)^!(b))
#define XOR(a,b) (!(a)!=!(b))
#define XOR(a,b) ((a)?!(b)::!!(b))
20.25 C語言中沒有迴圈移位操作符
部分原因是C語言的類型大小沒有精確定義,但是,對大小已知的機器字進行迴圈移位很有意義。
用兩個常規移位和一個按位或操作就可以實現迴圈移位
如:
(x<<13)|(x>>3)
對一個16位的機器字進行迴圈左移13位

20.26 C語言的詞法分析
規則是:在一個簡單的從左至右掃描中的任何時刻,最長的記號被劃分,不管最終的結果是否有意義。




 

 

 

 

 
 


 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.