C連載20-轉換說明中的異常

1、對字符串使用格式化輸出

#include<stdio.h>
#define BLURB "Authentic imitation!"

int D20_1_stringf(void) {
	printf("[%2s]\n", BLURB);
	printf("[%24s]\n", BLURB);
	printf("[%24.5s]\n", BLURB);
	printf("[%-24.5s]\n", BLURB);

	return 0;
}

20.1

  • 釋義:小數點接數字,表明會輸出幾個字符,小數點前面的表示佔位有幾個,負號表明文本左對齊輸出。
  • 下面演示幾個轉換說明不匹配的程序
#include<stdio.h>
#define PAGES 336
#define WORDS	65618
int D20_2_intconv(void) {
	short num = PAGES;
	short mnum = -PAGES;

	printf("num as short and unsigned short:%hd %hu\n", num, num);
	printf("-num as short and unsigned short:%hd %hu\n", mnum, mnum);
	printf("num as int and char:%d %c\n", num, num);
	printf("WORDS as int,short, and char: %d %hd %c\n", WORDS, WORDS, WORDS);

	return 0;
}

20.2

  • 釋義:第一行表示short十進制數字,和short無符號的十進制數,顯然數字大小範圍在short內;第二行都是第一個在short範圍內,第二個short int是兩個本身,負數在內存中是以補碼的形式存儲,可是%hu能夠爲它是個正數,因此把負數的補碼按照正常二進制給都出來了;第三行和第四行都是超出了相應的範圍,對數字進行相應的截斷。

2、混淆整形和浮點型,結果會更奇怪

#include<stdio.h>
int D20_3_floatcnv(void) {
	float n1 = 3.0;
	double n2 = 3.0;
	long n3 = 2000000000;
	long n4 = 1234567890;

	printf("%.1e %.1e %.1e %.1e\n", n1, n2, n3, n4);
	printf("%ld %ld\n", n3, n4);
	printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);

	return 0;
}

20.3

  • 釋義:%e轉換說明沒有把整數轉換爲浮點數,首先打印的時候,會轉換爲八位浮點數,原來的long類型是四位,因此係統還會把相鄰的四位內存拿過來,致使意外的數字;第三行沒有問題;第四行使人疑惑,即便用對了轉換說明也會生成虛假的結果。用%ld轉換說明打印浮點數會失敗,可是在這裏,用%ld打印long類型的數居然也失敗了,問題在於C如何把信息傳遞給函數,具體狀況因編譯器實現而異,」參數傳遞"框中針對一個有表明性的系統進行了討論

參數傳遞:以上面程序的第三行爲例進行分析,程序把傳入的值放入一個稱爲棧的內存區域,計算機根據變量類型(不是根據轉換說明)把這些值放入棧中。所以,n1被存儲在棧中,佔8個字節(float類型被轉換爲了double類型),一樣n2也在棧中佔有8個字節,而n3和n4分別佔用4個字節。而後控制轉到printf()函數,該函數根據轉換說明(不是根據變量類型)從棧中讀取數據,%ld轉換說明表示讀取4個字節,因此printf()讀取棧中前4個字節做爲第一個值。這是n1的前半部分,將被解釋位一個long類型的整數,根據下一個%ld轉換說明,printf()會接着讀取4個字節,這是n1的後半部分,將被解釋位第二個long類型的整數,相似的,後面兩個變量在進行讀取的時候,就會出現錯誤的狀況。git

2、源碼:

相關文章
相關標籤/搜索