2015年6月30日 星期二
2015年6月7日 星期日
[C] %s 的使用
當使用 %s 於 printf 和 scanf 時, 對應的argument 必須是 char * , 如下列例子:
char *str_constant = "I point to a string literal";
char str_buf[] = "I am an array of char initialized with a string literal";
printf("string literal = %s\n", "I am a string literal");
printf("str_constant = %s\n", str_constant);
printf("str_buf = %s\n", str_buf);
scanf("%55s", str_buf);
值得注意的是, 看以下小程序,
#define max 5
----------------------
#define max 5
----------------------
char *name[max];
int i;
for (i = 0; i < max; i++){
name[i] = malloc(3);
scanf("%3s", name[i]);
printf("%s\n", name[i]);
free(name[i]);
}
// 使用scanf前必須用使用 malloc 為每個char * pointer 動態分配位置記存字符
// %3s , 即指只讀取讀入字串的前3個字符
int i;
for (i = 0; i < max; i++){
name[i] = malloc(3);
scanf("%3s", name[i]);
printf("%s\n", name[i]);
free(name[i]);
}
// 使用scanf前必須用使用 malloc 為每個char * pointer 動態分配位置記存字符
// %3s , 即指只讀取讀入字串的前3個字符
2015年6月1日 星期一
[C] auto 與 register
C語言變數儲存等級(storage class),一共有四種:auto、extern、register、static,我們最常用的是auto,然而卻很少人用它來宣告變數,怎麼說起來很奇怪?因為編譯器自動把我們宣告的變數自動設成auto,只是我們都忽略有這回事。看個例子:
1
2
| int i;auto int i; |
以上兩者的意義相同,auto變數在程式執行的時候,OS配置記憶體空間給這個變數。
現在我們來討論register變數,跟auto變數一樣,register變數在程式執行的時候,OS會配置記憶體空間給此變數,但跟auto變數不一樣的是,register變數會被配置到CPU中的暫存器(register),而auto變數會被配置到RAM中,它們的差異在於存取速度,前者(register)快於後者(RAM),那到底快多少呢?我看到網路上都說「快」,但到底有多快?我們實際來測試看看吧~
1
| for(register int i=0;i<1000000000;i++); |
我舉我們最常使用的for迴圈,讓它空轉10的9次方次,我的電腦執行時間為:
2.98905059209784340000
請按任意鍵繼續 . . .
而去掉register宣告,結果則為:
3.03692563877645630000
請按任意鍵繼續 . . .
雖然看起來只有差0.05秒左右,但你若宣告long long的話,差異就更明顯了。不過當今電腦速度這麼快,誰會在乎這麼一點時間呢?
結論就是驗證了儲存裝置的層級:register存取速度優於RAM。前者量少而貴但相對較快,後者則相反。
文章出處 : https://cg2010studio.wordpress.com/2011/04/08/register-variable/
[C] static 與 extern
static變數,當變數有宣告時加上static限定時,一但變數生成,它就會一直存在記憶體之中,即使函式執行完畢,變數也不會消失,例如:
#include <stdio.h>
void count(void);
int main(void) {
int i;
for(i = 0; i < 10; i++) {
count();
}
return 0;
}
void count(void) {
static int c = 1;
printf("%d\\n", c);
c++;
}
執行結果:
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
雖然變數c是在count()函式中宣告的,但是函式結束後,變數仍然存在,它會直到程式執行結束時才消失,雖然變數一直存在,但由於它是被宣告在函式之 中,所以函式之外仍無法存取static變數。
您可以宣告全域static變數,其在程式執行期間一直存在,但在一個原始程式文件中宣告全域static變數,還表示其可以存取的範圍僅限於該原始程式文件之中,您也可以將函式宣告為static:
static void some() {
...
}
...
}
一個static函式表示,其可以呼叫的範圍限於該原始碼文件之中,如果您有一些函式僅想在該原始程式文件之中使用,則可以宣告為static,這也可以避免與其他人寫的函式名稱衝突的問題。
extern可以聲明變數會在其它的位置被定義,這個位置可能是在同一份文件之中,或是在其它文件之中,例如:
- some.c
double someVar = 1000;
// 其它定義 ...
- main.c
#include <stdio.h>
int main(void) {
extern double someVar;
printf("%f\\n", someVar);
return 0;
}
在main.c中實際上並沒有宣告someVar,extern指出someVar是在其它位置被定義,編譯器會試圖在其它位置或文件中找出 someVar的定義,結果在some.c中找到,因而會顯示結果為1000,要注意的是,extern聲明someVar在其它位置被定義,如果您 在使用extern時同時指定其值,則視為在該位置定義變數,結果就引發重覆定義錯誤,例如:
#include <stdio.h>
int main(void) {
int main(void) {
extern double someVar = 100;
// error, `someVar' has both `extern' and initializer
...
return 0;
}
return 0;
}
您必須先聲明extern找到變數,再重新指定其值,這麼使用才是正確的:
#include <stdio.h>
int main(void) {
extern double someVar;
someVar = 100;
...
return 0;
}
int main(void) {
extern double someVar;
someVar = 100;
...
return 0;
}
文章出處 :http://openhome.cc/Gossip/CGossip/Scope.html
[C] 可視範圍(scope)
在C中,談到可視範圍(scope)可分為許多層次,也可以談到很複雜,在這邊先談談
-「全域變數」(Global variable)
-「區域變數」(Local variable)
-「區塊變數」(Block variable)。
全域變數是指直接宣告在(主)函式之外的變數,這個變數在整個程式之中都「看」得它的存在,而可以呼叫使用,例如:
const double PI = 3.14159;
doule area(double r) {
return r * r * PI;
}
int main(void) {
// .....
return 0;
}
doule area(double r) {
return r * r * PI;
}
int main(void) {
// .....
return 0;
}
在這個例子中,PI這個變數可以被主函式main()與副函式area()來使用,通常全域變數是用來定義一些常數,初學者不應為了方便而將所有的變數都 設定為全域變數,否則將來一定會發生變數名稱管理上的問題,全域變數的生命週期始於程式開始之時,終止於程式結束之時。
區域變數是指宣告在函式之內的變數,或是宣告在參數列之前的變數,它的可視範圍只在宣告它的函式區塊之中,其它的函式不可以使用該變數,例如在上例的主函 式中,您不可以直接對area()函式中的變數r作出存取的動作,區域變數的生命週期開始於函式被呼叫之後,終止於函式執行完畢之時。
區塊變數是指宣告在某個陳述區塊之中的變數,例如while迴圈區塊中,或是for迴圈區塊,例如下面的變數i在迴圈結束之後,就會自動消失:
while(...) {
int i = 0; // ....
}
int i = 0; // ....
}
當一可視範圍大的變數與可視範圍小的變數發生同名狀況時,可視範圍小的變數會暫時覆蓋可視範圍大的變數,稱之為「變數覆蓋」,例如:
int num = 10;
int i;for(i = 0; i < 100; i++) {
int num = 20; // ...
}
printf("%d", num);
int i;for(i = 0; i < 100; i++) {
int num = 20; // ...
}
printf("%d", num);
這個程式最後顯示的 num 值仍是10,當執行迴圈時,迴圈內的 num 變數作用將覆蓋迴圈外的 num 變數;同樣的作用發生於全域變數與區域變數發生同名的時候。
文章來源:http://openhome.cc/Gossip/CGossip/Scope.html
[C] 列舉(enum)
- 列舉型態(enumeration)是一種特殊的常數定義方式。
- 列舉型態可使我們定義自己的資料型態,及設定其值。
- 程式的可讀性提高。
- 列舉型態的定義及宣告方式格式如下:
定義1:
- enum color
- {
- red,
- blue,
- green,
- };
- enum color coat, hat;
定義2:
- enum color /*宣告列舉型態color */
- {
- red,
- blue,
- green,
- } coat , hat;
定義3:
使用typedef
- typedef enum{
- All,
- January,
- February,
- March,
- April,
- May
- }month;
- month Month;
============================================================
Example 1 :
===================================================================
Remark:
enum 是英文 enumerate(列舉,枚舉) 的縮寫
效果是列舉出多個'常數',並設定數值。
例子:
enum{
stop,
stand,
run
};
stop,
stand,
run
};
大括號中每一個元素稱為列舉元,每個列舉元其實儲存著一個整數。
如果沒設定數值,預設是從0開始遞增。(stop=0 ; stand=1 ; run=2)
如果要設定數值,可以這樣打
enum{
stop=5,
stand,
run
};
stop=5,
stand,
run
};
這樣就會變成 (stop=5 ; stand=6 ; run=7)
也可以這樣用
enum{
stop=5,
stand, run=2
};
stop=5,
stand, run=2
};
這樣會變成 (stop=5 ; stand=6 ; run=2)
參考網址: http://bodscar.pixnet.net/blog/post/61204511-%E8%AA%AA%E6%98%8E-typedef-enum
[C] Typedef
typedef 用來對一個資料類型取一個新名字。目的是為了讓程式碼更好讀更好理解
舉個例子:
我們來為int取個可愛的名字 這樣看起來比較順眼
我們來為int取個可愛的名字 這樣看起來比較順眼
未使用 typedef 的樣貌
int color; //宣告color 為一變數
int leaf; // 宣告leaf 為一變數
...
...
...
使用 typedef 後的樣貌 ->
typedef int Apple; // int 的名子為Apple(蘋果)
typedef int Orange; // int 的名字Orange(橘子)
Apple color; //宣告color 為一變數
Orange leaf; // 宣告leaf 為一變數
...
...
...
另一個更常見的例子是用在幫結構(struct)取名子
未使用 typedef 的樣貌
未使用 typedef 的樣貌
struct var {
int math;
int english;
char data3;
};struct var yo;
這個結構以往在C當中要使用就要用這樣的方式
struct var yo;
struct var yo;
但是只要使用 typedef 就能改名了 如下
typedef struct var results;
typedef struct var results;
這樣之後要使用時就能改成這樣
results yo;
results yo;
完整用法
struct var {
int math;
int english;
char data3;
};typedef struct var results;
results yo;
進階用法
typedef struct {
int math;
int english;
char data3;
} result;
result yo; // 直接用取
文章出處 : http://bodscar.pixnet.net/blog/post/61204511-%E8%AA%AA%E6%98%8E-typedef-enum
訂閱:
文章 (Atom)

