char陣列和十六進位制格式化sprintf
char ch[2]; sprintf(ch, "%x", 100); printf("字串%%s輸出:%s\n", ch); printf("字元%%c輸出ch:%c\n", ch); printf("字元%%c輸出ch[0]:%c\n", ch[0]); printf("字元%%c輸出ch[1]:%c\n", ch[1]); printf("十六進位制%%x輸出ch:%x\n", ch); printf("十六進位制%%x輸出ch[0]:%x\n", ch[0]); printf("十六進位制%%x輸出ch[1]:%x\n", ch[1]); printf("十進位制%%d輸出ch:%d\n", ch); printf("十進位制%%d輸出ch[0]:%d\n", ch[0]); printf("十進位制%%d輸出ch[1]:%d\n", ch[1]);
輸出:
字串%s輸出:64
字元%c輸出ch:>
字元%c輸出ch[0]:6
字元%c輸出ch[1]:4
十六進位制%x輸出ch:22ff3e
十六進位制%x輸出ch[0]:36
十六進位制%x輸出ch[1]:34
十進位制%d輸出ch:2293566
十進位制%d輸出ch[0]:54
十進位制%d輸出ch[1]:52
說明:
int sprintf( char *buffer, const char *format, [ argument] … );
sprintf指的是字串格式化命令,主要功能是把格式化的資料寫入某個字串中。
100十六進位制為64,ch中存入'6''4',以%c字元輸出時ch[0]='6',ch[1]='4'
以%d十進位制數輸出時,對應這兩個字元的ACSII碼為 54 52
同理,%x十六進位制輸出時,對應54 52的十六進位制36 34
printf("字元%%c輸出ch:%c\n", ch);
printf("十六進位制%%x輸出ch:%x\n", ch);
printf("十進位制%%d輸出ch:%d\n", ch);
這兩個輸出的結果是不好理解的,剛開始以為是由高位54低位52組成的一個十六位數,測試了多次結果都不對,後來在VS裡面測試發現這個結果每次都是變化的,才想到這是指標,也就是ch的地址。
char[]是“特殊的”陣列,是由char組成的字串,陣列名代表地址,也是指向存放該陣列的地址的指標。對於陣列名,當以%s輸出時,就將各個字元以整體字串的形式輸出,以數字的形式(包括%c %d %x)時,輸出地址,而%c是1個位元組,地址是4個位元組,所以地址被擷取為1個位元組後輸出,將4個位元組的int型別擷取為1個位元組char型別,測試後%d會輸出63,對應ASCII為'?'
PS:發現Linux和Windows的編譯器區別,GCC中同一程式多次執行時變數地址保持不變,而在VS中每次都會變化。
sprintf 是個變參函式。
可變引數函式顧名思義,就是函式引數個數是未知的是可變的。sprintf中[ argument]的引數和format中的格式化符號一一對應。
sprintf 對於寫入buffer的字元數是沒有限制的,這就存在了buffer溢位的可能性。
例如:
char buffer[2];
sprintf(buffer, "%x", 1000);
printf("格式化後buffer:%s\n長度:%d\n", buffer, strlen(buffer));
輸出:
格式化後buffer:3e8
長度:3
說明:
首先定義一個長度為2的char陣列buffer,然後使用sprintf將1000以十六進位制存入buffer,1000十六進位制為3e8,所有buffer長度變為3,發生溢位。
4位元組“暴力”擷取1位元組
union A
{
int i;
char c;
};
union A a;
a.i=2293567;
printf("擷取後:十進位制%d,字元%c\n", a.c, a.c);
輸出:
擷取後:十進位制63,字元?