不定參數講座
在第一個例子裡,不定參數的型態和第一個已確定的int型態相同,
在第二個例子裡,不定參數的型態和第一個已確定的char*t型態不同。code:
#include <stdarg.h> int average(int first, ...) { int count = 0, sum = 0, i = first; va_list marker; va_start(marker, first); /* Initialize variable arguments. */ do{ sum += i; count++; } while ((i = va_arg(marker, int)) != -1); va_end(marker); /* Reset variable arguments. */ return (sum ? (sum / count) : 0); } void main() { clrscr(); printf("average=%d\n", average(10,20,39,-1)); }
在第三個例子裡,不定參數的型態有兩種:code:
#include <stdarg.h> int average(char *first, ...) { int count = 0, sum = 0, i; va_list marker; va_start(marker, first); /* Initialize variable arguments. */ while ((i = va_arg(marker, int)) != -1) { sum += i; count++; } va_end(marker); /* Reset variable arguments. */ return (sum ? (sum / count) : 0); } void main() { clrscr(); printf("average=%d\n", average("avg",10,20,39,-1)); }
在第四個例子裡,有兩種寫法:code:
#include <stdarg.h> int average(char *first, ...) { int count = 0, sum = 0, i; char *buffer; va_list marker; va_start(marker, first); /* Initialize variable arguments. */ for(i=0; i<2; i++) /* 將指標連續往下移動兩個變數所在的位址 */ { buffer = va_arg(marker, char *); printf("[%s]\n",buffer); } while ((i = va_arg(marker, int)) != -1) { sum += i; count++; } va_end(marker); /* Reset variable arguments. */ return (sum ? (sum / count) : 0); } void main() { clrscr(); printf("average=%d\n", average("avg","DDD","aaa",10,20,39,-1)); }
code:
int average(char *first, char *second, long ii, double mm, ...) { int count = 0, sum = 0, i; char *buffer; va_list marker; va_start(marker, first); printf("[%s]\n",va_arg(marker, char *)); printf("[%ld]\n",va_arg(marker, long)); printf("[%.lf]\n",va_arg(marker, double)); while (strcmp(buffer = va_arg(marker, char *), NULL)) printf("[%s]\n", buffer); va_end(marker); /* Reset variable arguments. */ return (sum ? (sum / count) : 0); } void main() { clrscr(); printf("average=%d\n", average("avg", "DDD", 123L, 23.0, "10", "20", "39", NULL)); }
當我們了解上述的寫法用意之後,回歸正式的精簡寫法:
code:
int average(char *first, char *second, long ii, double mm, ...) { int count = 0, sum = 0, i; char *buffer; va_list marker; va_start(marker, mm); while (strcmp(buffer = va_arg(marker, char *), NULL)) printf("[%s]\n", buffer); va_end(marker); /* Reset variable arguments. */ return (sum ? (sum / count) : 0); } void main() { clrscr(); printf("average=%d\n", average("avg", "DDD", 123L, 23.0, "10", "20", "39", NULL)); }
在以上程式中,有一行程式:
while (strcmp(buffer = va_arg(marker, char *), NULL))
這一行程式要特別說明。 strcmp(str1,str2)會存取str1及str2內容 在Real mode時,存取記憶體,沒有做任何的保護或檢查,就算存取到系統或不合法的 記憶體位址,系統不會產生任何的所謂「Access Exception」 而在Protect mode時,存取記憶時,會針對記憶體做保護及檢查的工作 確保被存取的記憶體是合法,若此記憶體未經授權或不合法時 系統會產生Access Exception來告知使用者。
strcmp(str1,NULL) strcmp會存取str1及NULL pointer的內容,一般定義NULL為0 存取記憶體位址0,是不合法的行為,在Read mode中,並不會檢查出來 而在Protect mode中,會產生Access Exception來告知使用者。 若你試著將例子中包含以上程式碼,放在Visual C++或及它在Win上跑的編譯器 你會得到Access Exception。比較正確的寫法應該是:
while (buffer = va_arg(marker, char *)
在此提供補充說明。
Written By James On 2004/09/06