<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # [X分鐘速成Y](http://learnxinyminutes.com/) ## 其中 Y=c 源代碼下載:?[learnc-cn.c](http://learnxinyminutes.com/docs/files/learnc-cn.c) C語言在今天仍然是高性能計算的主要選擇。 C大概是大多數程序員用到的最接近底層的語言了,C語言原生的速度就很高了,但是別忘了C的手動內存管理,它會讓你將性能發揮到極致。 ~~~ // 單行注釋以//開始。(僅適用于C99或更新的版本。) /* 多行注釋是這個樣子的。(C89也適用。) */ // 常數: #define 關鍵詞 #define DAYS_IN_YEAR 365 // 以枚舉的方式定義常數 enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; // MON自動被定義為2,TUE被定義為3,以此類推。 // 用#include來導入頭文件 #include <stdlib.h> #include <stdio.h> #include <string.h> // <尖括號>間的文件名是C標準庫的頭文件。 // 標準庫以外的頭文件,使用雙引號代替尖括號。 #include "my_header.h" // 函數的簽名可以事先在.h文件中定義, // 也可以直接在.c文件的頭部定義。 void function_1(char c); void function_2(void); // 如果函數出現在main()之后,那么必須在main()之前 // 先聲明一個函數原型 int add_two_ints(int x1, int x2); // 函數原型 // 你的程序的入口是一個返回值為整型的main函數 int main() { // 用printf打印到標準輸出,可以設定格式, // %d 代表整數, \n 代表換行 printf("%d\n", 0); // => 打印 0 // 所有的語句都要以分號結束 /////////////////////////////////////// // 類型 /////////////////////////////////////// // 在使用變量之前我們必須先聲明它們。 // 變量在聲明時需要指明其類型,而類型能夠告訴系統這個變量所占用的空間 // int型(整型)變量一般占用4個字節 int x_int = 0; // short型(短整型)變量一般占用2個字節 short x_short = 0; // char型(字符型)變量會占用1個字節 char x_char = 0; char y_char = 'y'; // 字符變量的字面值需要用單引號包住 // long型(長整型)一般需要4個字節到8個字節; 而long long型則至少需要8個字節(64位) long x_long = 0; long long x_long_long = 0; // float一般是用32位表示的浮點數字 float x_float = 0.0; // double一般是用64位表示的浮點數字 double x_double = 0.0; // 整數類型也可以有無符號的類型表示。這樣這些變量就無法表示負數 // 但是無符號整數所能表示的范圍就可以比原來的整數大一些 unsigned short ux_short; unsigned int ux_int; unsigned long long ux_long_long; // 單引號內的字符是機器的字符集中的整數。 '0' // => 在ASCII字符集中是48 'A' // => 在ASCII字符集中是65 // char類型一定會占用1個字節,但是其他的類型卻會因具體機器的不同而各異 // sizeof(T) 可以返回T類型在運行的機器上占用多少個字節 // 這樣你的代碼就可以在各處正確運行了 // sizeof(obj)返回表達式(變量、字面量等)的尺寸 printf("%zu\n", sizeof(int)); // => 4 (大多數的機器字長為4) // 如果`sizeof`的參數是一個表達式,那么這個參數不會被演算(VLA例外,見下) // 它產生的值是編譯期的常數 int a = 1; // size_t是一個無符號整型,表示對象的尺寸,至少2個字節 size_t size = sizeof(a++); // a++ 不會被演算 printf("sizeof(a++) = %zu where a = %d\n", size, a); // 打印 "sizeof(a++) = 4 where a = 1" (在32位架構上) // 數組必須要被初始化為具體的長度 char my_char_array[20]; // 這個數組占據 1 * 20 = 20 個字節 int my_int_array[20]; // 這個數組占據 4 * 20 = 80 個字節 // (這里我們假設字長為4) // 可以用下面的方法把數組初始化為0: char my_array[20] = {0}; // 索引數組和其他語言類似 -- 好吧,其實是其他的語言像C my_array[0]; // => 0 // 數組是可變的,其實就是內存的映射! my_array[1] = 2; printf("%d\n", my_array[1]); // => 2 // 在C99 (C11中是可選特性),變長數組(VLA)也可以聲明長度。 // 其長度不用是編譯期常量。 printf("Enter the array size: "); // 詢問用戶數組長度 char buf[0x100]; fgets(buf, sizeof buf, stdin); // stroul 將字符串解析為無符號整數 size_t size = strtoul(buf, NULL, 10); int var_length_array[size]; // 聲明VLA printf("sizeof array = %zu\n", sizeof var_length_array); // 上述程序可能的輸出為: // > Enter the array size: 10 // > sizeof array = 40 // 字符串就是以 NUL (0x00) 這個字符結尾的字符數組, // NUL可以用'\0'來表示. // (在字符串字面量中我們不必輸入這個字符,編譯器會自動添加的) char a_string[20] = "This is a string"; printf("%s\n", a_string); // %s 可以對字符串進行格式化 /* 也許你會注意到 a_string 實際上只有16個字節長. 第17個字節是一個空字符(NUL) 而第18, 19 和 20 個字符的值是未定義。 */ printf("%d\n", a_string[16]); // => 0 // byte #17值為0(18,19,20同樣為0) // 單引號間的字符是字符字面量 // 它的類型是`int`,而 *不是* `char` // (由于歷史原因) int cha = 'a'; // 合法 char chb = 'a'; // 同樣合法 (隱式類型轉換 // 多維數組 int multi_array[2][5] = { {1, 2, 3, 4, 5}, {6, 7, 8, 9, 0} } // 獲取元素 int array_int = multi_array[0][2]; // => 3 /////////////////////////////////////// // 操作符 /////////////////////////////////////// // 多個變量聲明的簡寫 int i1 = 1, i2 = 2; float f1 = 1.0, f2 = 2.0; int a, b, c; a = b = c = 0; // 算數運算直截了當 i1 + i2; // => 3 i2 - i1; // => 1 i2 * i1; // => 2 i1 / i2; // => 0 (0.5,但會被化整為 0) f1 / f2; // => 0.5, 也許會有很小的誤差 // 浮點數和浮點數運算都是近似值 // 取余運算 11 % 3; // => 2 // 你多半會覺得比較操作符很熟悉, 不過C中沒有布爾類型 // 而是用整形替代 // (C99中有_Bool或bool。) // 0為假, 其他均為真. (比較操作符的返回值總是返回0或1) 3 == 2; // => 0 (false) 3 != 2; // => 1 (true) 3 > 2; // => 1 3 < 2; // => 0 2 <= 2; // => 1 2 >= 2; // => 1 // C不是Python —— 連續比較不合法 int a = 1; // 錯誤 int between_0_and_2 = 0 < a < 2; // 正確 int between_0_and_2 = 0 < a && a < 2; // 邏輯運算符適用于整數 !3; // => 0 (非) !0; // => 1 1 && 1; // => 1 (且) 0 && 1; // => 0 0 || 1; // => 1 (或) 0 || 0; // => 0 // 條件表達式 ( ? : ) int a = 5; int b = 10; int z; z = (a > b) ? a : b; // 10 “若a > b返回a,否則返回b。” // 增、減 char *s = "iLoveC" int j = 0; s[j++]; // "i" 返回s的第j項,然后增加j的值。 j = 0; s[++j]; // => "L" 增加j的值,然后返回s的第j項。 // j-- 和 --j 同理 // 位運算 ~0x0F; // => 0xF0 (取反) 0x0F & 0xF0; // => 0x00 (和) 0x0F | 0xF0; // => 0xFF (或) 0x04 ^ 0x0F; // => 0x0B (異或) 0x01 << 1; // => 0x02 (左移1位) 0x02 >> 1; // => 0x01 (右移1位) // 對有符號整數進行移位操作要小心 —— 以下未定義: // 有符號整數位移至符號位 int a = 1 << 32 // 左移位一個負數 int a = -1 << 2 // 移位超過或等于該類型數值的長度 // int a = 1 << 32; // 假定int32位 /////////////////////////////////////// // 控制結構 /////////////////////////////////////// if (0) { printf("I am never run\n"); } else if (0) { printf("I am also never run\n"); } else { printf("I print\n"); } // While循環 int ii = 0; while (ii < 10) { // 任何非0的值均為真 printf("%d, ", ii++); // ii++ 在取值過后自增 } // => 打印 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " printf("\n"); int kk = 0; do { printf("%d, ", kk); } while (++kk < 10); // ++kk 先自增,再被取值 // => 打印 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " printf("\n"); // For 循環 int jj; for (jj=0; jj < 10; jj++) { printf("%d, ", jj); } // => 打印 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " printf("\n"); // *****注意*****: // 循環和函數必須有主體部分,如果不需要主體部分: int i; for (i = 0; i <= 5; i++) { ; // 使用分號表達主體(null語句) } // 多重分支:switch() switch (some_integral_expression) { case 0: // 標簽必須是整數常量表達式 do_stuff(); break; // 如果不使用break,控制結構會繼續執行下面的標簽 case 1: do_something_else(); break; default: // 假設 `some_integral_expression` 不匹配任何標簽 fputs("error!\n", stderr); exit(-1); break; } /////////////////////////////////////// // 類型轉換 /////////////////////////////////////// // 在C中每個變量都有類型,你可以將變量的類型進行轉換 // (有一定限制) int x_hex = 0x01; // 可以用16進制字面量賦值 // 在類型轉換時,數字本身的值會被保留下來 printf("%d\n", x_hex); // => 打印 1 printf("%d\n", (short) x_hex); // => 打印 1 printf("%d\n", (char) x_hex); // => 打印 1 // 類型轉換時可能會造成溢出,而且不會拋出警告 printf("%d\n", (char) 257); // => 1 (char的最大值為255,假定char為8位長) // 使用<limits.h>提供的CHAR_MAX、SCHAR_MAX和UCHAR_MAX宏可以確定`char`、`signed_char`和`unisigned char`的最大值。 // 整數型和浮點型可以互相轉換 printf("%f\n", (float)100); // %f 格式化單精度浮點 printf("%lf\n", (double)100); // %lf 格式化雙精度浮點 printf("%d\n", (char)100.0); /////////////////////////////////////// // 指針 /////////////////////////////////////// // 指針變量是用來儲存內存地址的變量 // 指針變量的聲明也會告訴它所指向的數據的類型 // 你可以使用得到你的變量的地址,并把它們搞亂,;-) int x = 0; printf("%p\n", &x); // 用 & 來獲取變量的地址 // (%p 格式化一個類型為 void *的指針) // => 打印某個內存地址 // 指針類型在聲明中以*開頭 int* px, not_a_pointer; // px是一個指向int型的指針 px = &x; // 把x的地址保存到px中 printf("%p\n", (void *)px); // => 輸出內存中的某個地址 printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer)); // => 在64位系統上打印“8, 4”。 // 要得到某個指針指向的內容的值,可以在指針前加一個*來取得(取消引用) // 注意: 是的,這可能讓人困惑,'*'在用來聲明一個指針的同時取消引用它。 printf("%d\n", *px); // => 輸出 0, 即x的值 // 你也可以改變指針所指向的值 // 此時你需要取消引用上添加括號,因為++比*的優先級更高 (*px)++; // 把px所指向的值增加1 printf("%d\n", *px); // => 輸出 1 printf("%d\n", x); // => 輸出 1 // 數組是分配一系列連續空間的常用方式 int x_array[20]; int xx; for (xx=0; xx<20; xx++) { x_array[xx] = 20 - xx; } // 初始化 x_array 為 20, 19, 18,... 2, 1 // 聲明一個整型的指針,并初始化為指向x_array int* x_ptr = x_array; // x_ptr現在指向了數組的第一個元素(即整數20). // 這是因為數組通常衰減為指向它們的第一個元素的指針。 // 例如,當一個數組被傳遞給一個函數或者綁定到一個指針時, //它衰減為(隱式轉化為)一個指針。 // 例外: 當數組是`&`操作符的參數: int arr[10]; int (*ptr_to_arr)[10] = &arr; // &arr的類型不是`int *`! // 它的類型是指向數組的指針(數組由10個int組成) // 或者當數組是字符串字面量(初始化字符數組) char arr[] = "foobarbazquirk"; // 或者當它是`sizeof`或`alignof`操作符的參數時: int arr[10]; int *ptr = arr; // 等價于 int *ptr = &arr[0]; printf("%zu, %zu\n", sizeof arr, sizeof ptr); // 應該會輸出"40, 4"或"40, 8" // 指針的增減多少是依據它本身的類型而定的 // (這被稱為指針算術) printf("%d\n", *(x_ptr + 1)); // => 打印 19 printf("%d\n", x_array[1]); // => 打印 19 // 你也可以通過標準庫函數malloc來實現動態分配 // 這個函數接受一個代表容量的參數,參數類型為`size_t` // 系統一般會從堆區分配指定容量字節大小的空間 // (在一些系統,例如嵌入式系統中這點不一定成立 // C標準對此未置一詞。) int *my_ptr = malloc(sizeof(*my_ptr) * 20); for (xx=0; xx<20; xx++) { *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx } // 初始化內存為 20, 19, 18, 17... 2, 1 (類型為int) // 對未分配的內存進行取消引用會產生未定義的結果 printf("%d\n", *(my_ptr + 21)); // => 誰知道會輸出什么 // malloc分配的區域需要手動釋放 // 否則沒人能夠再次使用這塊內存,直到程序結束為止 free(my_ptr); // 字符串通常是字符數組,但是經常用字符指針表示 // (它是指向數組的第一個元素的指針) // 一個優良的實踐是使用`const char *`來引用一個字符串字面量, // 因為字符串字面量不應當被修改(即"foo"[0] = 'a'犯了大忌) const char* my_str = "This is my very own string"; printf("%c\n", *my_str); // => 'T' // 如果字符串是數組,(多半是用字符串字面量初始化的) // 情況就不一樣了,字符串位于可寫的內存中 char foo[] = "foo"; foo[0] = 'a'; // 這是合法的,foo現在包含"aoo" function_1(); } // main函數結束 /////////////////////////////////////// // 函數 /////////////////////////////////////// // 函數聲明語法: // <返回值類型> <函數名稱>(<參數>) int add_two_ints(int x1, int x2){ return x1 + x2; // 用return來返回一個值 } /* 函數是按值傳遞的。當調用一個函數的時候,傳遞給函數的參數 是原有值的拷貝(數組除外)。你在函數內對參數所進行的操作 不會改變該參數原有的值。 但是你可以通過指針來傳遞引用,這樣函數就可以更改值 例子:字符串本身翻轉 */ // 類型為void的函數沒有返回值 void str_reverse(char *str_in){ char tmp; int ii = 0; size_t len = strlen(str_in); // `strlen()`` 是C標準庫函數 for(ii = 0; ii < len / 2; ii++){ tmp = str_in[ii]; str_in[ii] = str_in[len - ii - 1]; // 從倒數第ii個開始 str_in[len - ii - 1] = tmp; } } /* char c[] = "This is a test."; str_reverse(c); printf("%s\n", c); // => ".tset a si sihT" */ // 如果引用函數之外的變量,必須使用extern關鍵字 int i = 0; void testFunc() { extern int i; // 使用外部變量 i } // 使用static確保external變量為源文件私有 static int i = 0; // 其他使用 testFunc()的文件無法訪問變量i void testFunc() { extern int i; } //**你同樣可以聲明函數為static** /////////////////////////////////////// // 用戶自定義類型和結構 /////////////////////////////////////// // Typedefs可以創建類型別名 typedef int my_type; my_type my_type_var = 0; // struct是數據的集合,成員依序分配,按照 // 編寫的順序 struct rectangle { int width; int height; }; // 一般而言,以下斷言不成立: // sizeof(struct rectangle) == sizeof(int) + sizeof(int) //這是因為structure成員之間可能存在潛在的間隙(為了對齊)[1] void function_1(){ struct rectangle my_rec; // 通過 . 來訪問結構中的數據 my_rec.width = 10; my_rec.height = 20; // 你也可以聲明指向結構體的指針 struct rectangle *my_rec_ptr = &my_rec; // 通過取消引用來改變結構體的成員... (*my_rec_ptr).width = 30; // ... 或者用 -> 操作符作為簡寫提高可讀性 my_rec_ptr->height = 10; // Same as (*my_rec_ptr).height = 10; } // 你也可以用typedef來給一個結構體起一個別名 typedef struct rectangle rect; int area(rect r){ return r.width * r.height; } // 如果struct較大,你可以通過指針傳遞,避免 // 復制整個struct。 int area(const rect *r) { return r->width * r->height; } /////////////////////////////////////// // 函數指針 /////////////////////////////////////// /* 在運行時,函數本身也被存放到某塊內存區域當中 函數指針就像其他指針一樣(不過是存儲一個內存地址) 但卻可以被用來直接調用函數, 并且可以四處傳遞回調函數 但是,定義的語法初看令人有些迷惑 例子:通過指針調用str_reverse */ void str_reverse_through_pointer(char *str_in) { // 定義一個函數指針 f. void (*f)(char *); // 簽名一定要與目標函數相同 f = &str_reverse; // 將函數的地址在運行時賦給指針 (*f)(str_in); // 通過指針調用函數 // f(str_in); // 等價于這種調用方式 } /* 只要函數簽名是正確的,任何時候都能將任何函數賦給某個函數指針 為了可讀性和簡潔性,函數指針經常和typedef搭配使用: */ typedef void (*my_fnp_type)(char *); // 實際聲明函數指針會這么用: // ... // my_fnp_type f; // 特殊字符 '\a' // bell '\n' // 換行 '\t' // tab '\v' // vertical tab '\f' // formfeed '\r' // 回車 '\b' // 退格 '\0' // null,通常置于字符串的最后。 // hello\n\0\. 按照慣例,\0用于標記字符串的末尾。 '\\' // 反斜杠 '\?' // 問號 '\'' // 單引號 '\"' // 雙引號 '\xhh' // 十六進制數字. 例子: '\xb' = vertical tab '\ooo' // 八進制數字. 例子: '\013' = vertical tab // 打印格式: "%d" // 整數 "%3d" // 3位以上整數 (右對齊文本) "%s" // 字符串 "%f" // float "%ld" // long "%3.2f" // 左3位以上、右2位以上十進制浮 "%7.4s" // (字符串同樣適用) "%c" // 字母 "%p" // 指針 "%x" // 十六進制 "%o" // 八進制 "%%" // 打印 % /////////////////////////////////////// // 演算優先級 /////////////////////////////////////// //---------------------------------------------------// // 操作符 | 組合 // //---------------------------------------------------// // () [] -> . | 從左到右 // // ! ~ ++ -- + = *(type)sizeof | 從右到左 // // * / % | 從左到右 // // + - | 從左到右 // // << >> | 從左到右 // // < <= > >= | 從左到右 // // == != | 從左到右 // // & | 從左到右 // // ^ | 從左到右 // // | | 從左到右 // // && | 從左到右 // // || | 從左到右 // // ?: | 從右到左 // // = += -= *= /= %= &= ^= |= <<= >>= | 從右到左 // // , | 從左到右 // //---------------------------------------------------// ~~~ ## 更多閱讀 最好找一本?[K&R, aka “The C Programming Language”, “C程序設計語言”](https://en.wikipedia.org/wiki/The_C_Programming_Language)。它是關于C最重要的一本書,由C的創作者撰寫。不過需要留意的是它比較古老了,因此有些不準確的地方。 另一個比較好的資源是?[Learn C the hard way](http://c.learncodethehardway.org/book/) 如果你有問題,請閱讀[compl.lang.c Frequently Asked Questions](http://c-faq.com/)。 使用合適的空格、縮進,保持一致的代碼風格非常重要。可讀性強的代碼比聰明的代碼、高速的代碼更重要。可以參考下[Linux內核編碼風格](https://www.kernel.org/doc/Documentation/CodingStyle)?。 除了這些,多多Google吧 [1] http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看