2015-04-01 51 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