2015-04-01 67 views
1

我寫了一個小程序來檢查頁面對齊。 當程序本身硬編碼地址變量的值時,該程序工作正常,但是當我嘗試使用argc和argv值從命令行中取出它們時,輸出變得雜亂無章,uint64_t的值無法使用atoi函數從命令行恢復..?使用atoi函數從命令行輸入

正常的代碼,可以看到硬編碼到程序本身的地址的值。

1 #include<stdio.h> 
    2 #include<stdlib.h> 
    3 
    4 int aligned(uint64_t addr, uint64_t pgsize){ 
    5  return ((uint64_t)addr % pgsize == 0); 
    6 } 
    7 
    8 int main(int argc, char*argv[]){ 
    9  uint32_t i; 
10  uint64_t addr, size; 
11  addr=0x1900000000; 
12  size=0x100000000 ; 
13 
14  for(i=0;i<7;i++) 
15   if(aligned(addr,size>>i)){ 
16     printf("Aligned to %#lx\n",size>>i); 
17   } 
18   else 
19    printf("Not Aligned to %#lx\n",size>>i); 
20  return 0; 
21 } 

輸出

[souravhimanshu] ./aligned 
Aligned to 0 
Aligned to 0x80000000 
Aligned to 0x40000000 
Aligned to 0x20000000 
Aligned to 0x10000000 
Aligned to 0x8000000 
Aligned to 0x4000000 

時的atoi後印有命令行輸入

1 #include<stdio.h> 
    2 #include<stdlib.h> 
    3 
    4 int aligned(uint64_t addr, uint64_t pgsize){ 
    5  return ((uint64_t)addr % pgsize == 0); 
    6 } 
    7 
    8 int main(int argc, char*argv[]){ 
    9  uint32_t i; 
10  uint64_t addr, size; 
11  if(argc<2){ 
12   printf("usage ./chkalign <address>\n"); 
13   exit(-1); 
14  } 
15  addr=atoi(argv[1]); 
16  printf("%#lx",addr); 
17  //addr=0x1900000000; 
18  size=0x100000000 ; 
19 
20  for(i=0;i<7;i++) 
21   if(aligned(addr,size>>i)){ 
22     printf("Aligned to %#lx\n",size>>i); 
23   } 
24   else 
25    printf("Not Aligned to %#lx\n",size>>i); 
26  return 0; 
27 } 

輸出(不正確的)

[[email protected]] ./chkalign 0x924000000 
0Aligned to 0 
Aligned to 0x80000000 
Aligned to 0x40000000 
Aligned to 0x20000000 
Aligned to 0x10000000 
Aligned to 0x8000000 
Aligned to 0x4000000 

我們可以看到addr的值代碼功能顯示爲0.

請告知...

+1

你嘗試'與strtol()'呢? – 2015-04-01 06:42:29

+2

請勿包含行號,否則我們無法輕鬆地將您的代碼複製/粘貼到文本編輯器中並進行編譯。 – Lundin 2015-04-01 06:53:57

+1

當你問到這裏的時候,真的把你的代碼編寫成一個簡單的例子。你的問題與解釋地址等無關。正如你在標題中正確的,你有一個'atoi'的問題,所以解決這個問題,並省略所有無趣的東西。 – 2015-04-01 07:21:01

回答

1

沒有指定平臺,要知道,內存地址不必須與int一樣大小。 atoi返回一個int,因此問題。

即使long可能不足以容納內存地址(如在Windows IIRC中)。所以你應該使用strtoull返回一個unsigned long long保證至少有64位。還使用0作爲轉換基礎,允許在命令行上輸入地址爲0x80000000。對於您的類型,也可以更一致和便攜:long不一定是64位,因此它不應該被打印爲"%lx"printf

也適用於您的風格。一致性有助於避免錯誤。

這裏是一個修正版本:

#include <stdint.h> 
#include <stdio.h> 
#include <stdlib.h> 

int aligned(uint64_t addr, uint64_t pgsize) { 
    return (addr % pgsize) == 0; 
} 

int main(int argc, char *argv[]) { 
    int i; 
    uint64_t addr, size; 

    if (argc < 2) { 
     printf("usage: ./chkalign <address>\n"); 
     exit(-1); 
    } 
    addr = strtoull(argv[1], NULL, 0); 
    printf("Address %#llx:\n", (unsigned long long)addr); 
    //addr = 0x1900000000; 
    size = 0x100000000; 

    for (i = 0; i < 7; i++) { 
     if (aligned(addr, size >> i)) { 
      printf("Aligned to %#llx\n", (unsigned long long)size >> i); 
     } else { 
      printf("Not Aligned to %#llx\n", (unsigned long long)size >> i); 
      break; 
     } 
    } 
    return 0; 
} 
+0

謝謝@chqrlie,我在IA64 hpux盒子上... – 2015-04-01 09:55:43

1

數量0x924000000是十六進制,所以你應該使用strtol()並將其存儲在long

addr=strtol(argv[1], NULL, 16); 
+1

'strtoul'在這種情況下更有意義。 – Lundin 2015-04-01 06:55:40

+0

而使用'0'而不是'16'將允許以更通用的格式(十進制,八進制或十六進制)讀取數字。 – 2015-04-01 07:22:15

+0

使用strtoull ** addr = strtoull(argv [1],NULL,0); **在打印地址時,它打印錯誤 **/chkalign 0x924000000 ** ** addr:0x24000000 **而不是_0x924000000_ – 2015-04-01 08:31:02