公告版位
從小害怕寫作文, 文筆不佳到現在, 還請各位讀者大大:
1. 發現有錯誤, 請留言告知. (或者你 '覺得' 不對也行)
2. 用字措辭不當, 請留言告知.
3. 有看沒有懂? 幫到忙也好, 幫倒忙也罷, 總之留個言吧.

目前分類:C Language (15)

瀏覽方式: 標題列表 簡短摘要

今天在網上爬文, 無意間學到了 named initializer 這個到 C99 才出現的語法.

enum 的應用例子


先來看一個 enum 的應用例子:

文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

C 語言的編譯器有一個內建的巨集 sizeof() 可以用來取得配置給變數的記憶體大小. 例如:

    uint32_t varX = 1234;
    int      size;

    size = sizeof(varX);

這樣變數 size 所存儲的數值就會是變數 varX 到底在電腦裡佔用了多大的記憶體. uint32_t 型態的變數 (沒有意外的話) 應該都會佔用 4 bytes.

文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

寫 C 程式時偶而會遇到函數的原型宣告多設了一些暫時沒有用到的參數, 一般狀況下只要修改一下標頭檔中的宣告以及實際 C 函數的定義就好了. 不過偶而也會遇到不能改的情形, 例如:

  • 套用某些框架系統時, 函數的原型宣告是框架系統提供的. (一改大概框架系統就不用升版了)
  • 使用函數庫中某個函數的 call back, 而函數庫改不動, 或者沒原始程式, 沒得改.
  • 在開發 embedded system 時, 我們需要實作或者改寫一些函數以取代 C 編譯器的一些預設行為, 例如: Keil ARM/MDK 中要把 printf() 改輸出到 SoC 的 UART.

下面一些方法可以在無法修改函數的原型宣告時, 把 C 編譯器對未使用的函數參數之告警消除.

  • 方法一: 大部份的 C 編譯器應該都可以適用.
  • #define UNUSED(x) ( (void)(x) )
    
    void f(int x, int y) {
        UNUSED(x);
        ...
    }
    
文章標籤

MagicJackTing 發表在 痞客邦 留言(4) 人氣()

C 語言的變數有所謂的 storage class, 初學時對當中的差異並不是很容易弄清楚, 後來我把各種條件稍作整理, 於是有了下面的表格:

C 語言變數
條件/狀況 外部變數
文章標籤

MagicJackTing 發表在 痞客邦 留言(2) 人氣()

運算子優先權 (C 語言)
Percedence Table

運算子
Operator
說 明
文章標籤

MagicJackTing 發表在 痞客邦 留言(1) 人氣()

以前以為 typedef 的功能可以用 #define 來完成, 用起來感覺功能也差不多, 例如:

typedef unsigned char bool;  // 用這一行或者是下一行 二選一
//#define bool unsigned char

bool      flag1, flag2;
文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

C 語言中 typedef 可以用來擴充 C 原有的資料型態. 通常我們會將某個資料型態或者將常用的資料型態組合給予一個比較直觀而易懂的別名. 定義別名之後我們就可以像使用原有的資料型態來宣告或定義變數一樣, 直接拿它來宣告或定義(註一, 註二)變數.

註一: 宣告定義有所不同. 定義變數會實際佔據記憶體空間, 而宣告變數則只產生參考的連結, 稍後連結程式時再連結到在其他模組定義的變數. 我們一般把宣告變數擺放在 header file (.h 檔) 中, 有需要的模組或程式只要 include 即可. 而定義變數則視情況放在主程式或者相關的模組中, 當然它通常也會 include 該 header file.

註二: ANSI C 標準文件說: 會實際佔據記憶體空間的宣告稱為定義. 所以 ANSI C 說的宣告包含了定義純宣告. 而註一及以下本文中所指的宣告則是指沒有佔據記憶體空間的純宣告, 而不是 ANSI C 原先所指的宣告, 特此說明. 請參考維基網站 Declaration (computer programming) 段落二 'Declaration vs. definition' 及段落三 'Declarations and Definitions')

文章標籤

MagicJackTing 發表在 痞客邦 留言(1) 人氣()

程式在移植或者整合時, 有時會遇到使用結構來的定義程式所用到的資料的情形, 有時原作者是用一指向結構的指標來處理, 但是有時也會有直接用結構變數的情形.

這些程式我們在使用的時候按理應該盡量不要更動以免日後改版時造成問題, 不過要是遇到下面二種狀況那就...

  1. 原始程式是用指標來指向要處理的結構變數, 而現在我們想把規模縮小, 只會有一份結構變數, 同時也希望最佳化目的碼, 讓系統小一點, 快一點.
  2. 或者原始程式中把結構變數寫死了, 所有的函數都是針對那一個結構變數寫的, 結構變數生不出第二個 instance 來. 而我們卻是需要擴充一下, 讓它能處理多個結構變數.
文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

外部資料結構


在寫 CPU 或介面晶片的驅動程式時, 經常會使用到某些固定位址, 如: ARM Cortex-M 把系統設定及狀態對應到記憶體的特定位址, 某些周邊 IC, 例如 PCI, USB... 也是使用一小段記憶體空間. (註: 常見的周邊 IC 暫存器定址有二種: 一種是只有二個位址空間, 一個是 '指令/地址暫存器', 一個是 '資料暫存器'; 另一種則是直接使用 CPU 的記憶體空間來對應)

軟體功力較佳的 SoC 晶片製造廠所提供的驅動程式, 通常會將這一小段記憶體空間以結構 (struct) 的方式定義好, 再使用 define 將特定的位址值 (常數), 定義成一虛擬變數. 當然如果晶片功能比較簡單就不見得是用這種方法.

文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

個人覺得 C 語言最神奇的地方是有好些個對等寫法

類型 相關運算子 寫法一 寫法二 說明/宣告
1. (變數)取址 "&" p &x p 為指標, 並指向變數 x
2. (指標)取值 "*" *p x 同上
3. 陣列與指標 "[]" and "*" p[n] *(p+n) p 為陣列變數或者指標變數
4. 結構成員 "->" and "." p->x (*p).x p 為指標, 並指向一結構
x 為該結構成員
文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

C 語言預設會幫我們作一些型別轉換的動作, 一般的型別轉換不只會更換資料型別, 更會使資料內容有所變動, 例如:

    float   fVar = 1.2;
    int32_t iVar;

    iVar = fVar;    // iVar 值為整數 1

但是萬一我們不想要這個預設的換轉, 只是想要把 fVar 的數值 (以 float 格式) 存放在變數 iVar 所佔用的記憶體中, 而又不想動用 union 設定呢? (因為使用 union 程式或多或少都需要修改, 萬一 compiler 不支援 Unnamed Structure and Union Fields (或者 Anonymous unions, C11 的功能), 則需要更動的幅度就會更大.)

文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

'型別轉換': 基本上就只是在變數/函數前面加一對小括號, 中間填入要轉成什麼型別, 像這個樣子 "(型別)", 例如:
(unsigned char *)ptr
看不出哪一點難, 對吧

文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

本文來自網站 ieng9.ucsd.edu (http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html) 加以重新排版.

呃... 它搬家了, 新網址如後: cseweb.ucsd.edu (http://cseweb.ucsd.edu/~ricko/rt_lt.rule.html)

文章標籤

MagicJackTing 發表在 痞客邦 留言(4) 人氣()

在系統在整合或移值時最常用的就是以巨集來置換一些底層 function. 這類的技巧叫 wrapper (意思是包裝紙)

但是在面對像 printf() 或者 scanf() 之類參數個數可變 (或稱不具名參數) 的函數, 就出現只能更換函數名稱, 而無法增減參數個數的冏境, 例如:

// 下例 OK, 但是無法處理參數的異動
#define printf             my_printf

// 下例 OK, 但是只能處理剛好二個參數的異動 (增加, 交換)
#define printf(a, b)       my_printf(x, b, a)

// 下例 ERR, C 編譯器的 preprocessor 不認識 ...
#define printf(a, b, ...)  my_printf(x, a, b, ...)
文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

#include <stdarg.h>

int my_function(int cnt, char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    ...
    x = va_arg(ap, int);    // 取得一個整數變數
    ...
    *va_arg(ap, long *) = y;    // 把一個長整數指標變數塞回去
    ...
    va_end(ap);
    ...
    return ret_value;
}

int main(void)
{
    ...
    my_function(12, "abc", 6, 7, 8);
    ...
}

說明:

文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

您尚未登入,將以訪客身份留言。亦可以上方服務帳號登入留言

請輸入暱稱 ( 最多顯示 6 個中文字元 )

請輸入標題 ( 最多顯示 9 個中文字元 )

請輸入內容 ( 最多 140 個中文字元 )

請輸入左方認證碼:

看不懂,換張圖

請輸入驗證碼