[英]fscanf only gets first 4 bytes of a hex number
我正在用C語言編寫一個緩存模擬器,並且幾乎完成了所有工作……除非我嘗試掃描地址,fscanf跳過了十六進制數字中的一些數字:它只會得到4個字節! 如果我無法獲得正確的地址,則標記位不正確,並且模擬將始終無法進行。 任務似乎很簡單,但是我一定錯過了一些東西。 也許與fscanf格式的字符串特質有關?
源文件如下所示:
S 00600aa0,1
I 004005b6,5
S 7ff000398,8
M 7ff000390,8
// and so on ...
我嘗試使用fgets和sscanf代替,但是得到的結果相同。
char buffer[200];
char *pattern = " %c %x,%s\n";
int status; long address; char op;
while ((status = fscanf(source, pattern, &op, &address, buffer)) != EOF) {
if (op != 'I') {
fprintf(stderr,"address: %x\n",address); // DEBUG stmnt
simulate the cache..........................
調試語句為第3行打印出錯誤的地址,而不是“ address:7ff000398”,而是寫入“ address:ff000398”。 它正確地適合第1行。為什么只讀取前4個字節? “地址”已經很長了,我找不到像%x這樣的任何文檔。
address
vairable的類型很long
,只能存儲4個字節,而0x7ff000398
是8個字節。 因此它僅存儲最后4個有效字節,而忽略最高有效字節。 這就是第1行和第2行按預期工作,而第3行則不行的原因。
要解決此問題,您可以將地址類型更改為long long
您將需要一個64位整數來存儲結果。
在32位系統上, long
類型可能只有32位長。
可以肯定的是,您可以將long long
類型用於address
。
更好的方法是使用uint64_t
類型(在c99的stdint.h
定義)
address
類型更改為long long
(如果需要) %x
更改為%lx
(對於long
)或%llx
(對於long long
)(兩個地方) 啟用警告后,您將收到以下消息:
warning: format ‘%x’ expects argument of type ‘unsigned int’,
but argument 3 has type ‘long int’ [-Wformat=]
fprintf(stderr,"address: %x\n",address); // DEBUG stmnt
~^ ~~~~~~~
%lx
這為您解決問題提供了一個很好的線索。
因此,您的代碼應如下所示:
#include <stdio.h>
int main(void)
{
char buffer[10];
char *pattern = " %c %lx,%s\n";
int status;
unsigned long address; char op;
while ((status = scanf(pattern, &op, &address, buffer)) != EOF) {
fprintf(stderr,"address: %lx\n",address);
}
return 0;
}
通過您的輸入,我得到的結果是:
address: 600aa0
address: 4005b6
address: 7ff000398
address: 7ff000390
從C99開始,您可以使用uintptr_t
,這是一種能夠存儲指針的無符號整數類型(如果這些地址是同一目標計算機上的指針)。
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(void)
{
char *str = "7ff000398";
uintptr_t address;
sscanf(str, "%" SCNxPTR, &address); // x for base 16
printf("%" PRIxPTR "\n", address); // x for base 16
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.