程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> 神奇的C語言

神奇的C語言

編輯:關於C
1. 例子:     #include <stdio.h>   #define _mir(a) #a int main() {     char * s = _mir(         struct _st{             int a;             int b;             int c;         };     );     printf( "%s\n", s );     return 0; } 輸出:   1 struct _st{ int a; int b; int c; }; 說明:   A) 預編譯中#是將右邊的參數轉成一個字符串,##是將左右兩邊的參數連接成一個字符串。例子是#的用法。 B) 宏當中的參數其實是以逗號(,)分隔的,其他的字符其實都被看成同一個參數,但是換行和空白其實被處理過了,使參數在同一個行中。有興趣的自己多做些測試吧,這個用法可以用於要寫包含特殊字符的字符串,免得要寫很多的轉義字符(\),但是中間不能有逗號,呵呵~   2. 例子:     #include <stdio.h>   struct _st{     int a;     int b;     int c; };   void main() {     printf( "%d\n", &((struct _st*)0)->b ); } 輸出:   1 4  說明:   A) &((struct _st*)0)->b 的作用是輸出_st結構體中b的偏移。為什麼用0當成指針呢,其實很好理解:如果一個_st結構體的地址是0,那麼b的地址其實就是b在結構體中的偏移。 B) 其實按理,如果先做((struct _st*)0)->b運算,那麼程序肯定異常,所以編譯器還是做了優化的,具體編譯器怎麼做的,我也沒深究。   3. 例子:     #include <stdio.h>   struct _st{         int a : 1;         int b : 1;         int c : 1; }s = {         .c = 1,         .b = 0,         .a = 0 };   void main() {         printf( "%d %d %d %d\n", sizeof(s), s.a, s.b, s.c ); }  輸出:   1 4 0 0 -1  說明:   A) 在結構體的初始化時,可以指定域進行初始化,如例子中的.c = 1,順序可以顛倒,這樣做的好處就是可讀性較強,對於大結構的初始化,在閱讀時很方便。缺點就是低版本的編譯器可能不支持。 B) 在結構體的聲明中,可以指定域的大小,如例子中的int a : 1; 說明a只暫用一個bit,充分展示了C對二進制處理反面的親和力。 C) 為什麼s.c輸出是-1,而不是1,其實很簡單,因為0xFFFFFFFF表示的是-1,那麼一個1bit大小的變量,所有位上面都是1,那麼它也表示-1。所以編碼的過程中,有符號和無符號混用其實是很危險的一件事情。 4. 例子:     #include <stdio.h> void main() {     int i;     char a[10]="hello";           0[a] = 'x';     printf( "%s\n", a );       for( i=0; i<10; i++ )         printf( "%c", (rand()%10)["0123456789"] );     printf( "\n" );      } 輸出:   1 2 xello 1740948824 說明:   A) 0[a] = 'x';是什麼玩意兒?如果寫成a[0]='x';其實你就明白是什麼意思了,但是說白了,a[0]和0[a]在編譯器看來是一樣的。因為數組在做[]運行時,其實是做指針的加法運行:a[0]等價於*(a+0)。所以0[a]也就等價於*(0+a)是完全正確的。 B) 循環中功能是輸出一個10位的隨機數。其實也等價於"0123456789"[rand()%10]。這裡"0123456789"的類型是char*,所以指針也支持[]運算,因為[]運算其實就是加法運算。   5. 例子:   #include <stdio.h>       void func( char a[10] ) {     printf( "%d %d\n", &a, &a[0] ); }   void main() {     char a[10];     printf( "%d %d\n", &a, &a[0] );     func( a ); }  輸出:   1 2 1638208 1638208 1638192 1638208 說明:   A) 為什麼兩行的結果會不一樣?在一般情況下,按我的理解,一個數組a,&a和&a[0]的值是一樣的。但是當a在形參當中時就不一樣了。例子中,func函數中的a,其實a變量是在func函數的棧當中,在func內部,a其實已經被轉化成char *a,所以&a是表示指針變量a在棧中的地址,而&a[0]表示的是指針指向的內存空間的第一個元素的地址,其實也就是調用者傳入的數組的第一個元素的地址。不知道我說明白了沒有!! B) 這個可能比較難理解,關鍵是明白一點,在數組作為形參時,是被轉換成指針看待的。
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved