簡體   English   中英

fscanf僅獲取十六進制數字的前4個字節

[英]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位系統

在32位系統上, long類型可能只有32位長。

可以肯定的是,您可以將long long類型用於address

更好的方法是使用uint64_t類型(在c99的stdint.h定義)

變化

  1. address類型更改為long long (如果需要)
  2. %x更改為%lx (對於long )或%llx (對於long long )(兩個地方)
  3. 在打開警告的情況下進行編譯。

警告

啟用警告后,您將收到以下消息:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM