【问题标题】:Input from command line using atoi function使用 atoi 函数从命令行输入
【发布时间】:2015-06-05 17:19:57
【问题描述】:

我写了一个小程序来检查页面对齐。 当我在程序本身中硬编码地址变量的值时,该程序运行良好,但是当我尝试使用 argc 和 argv 值从命令行获取它们时,输出变得随意,是否无法使用 atoi 函数从命令行恢复 uint64_t 的值。 .?

普通代码,可以看到地址的值被硬编码到程序本身中。

  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

命令行输入代码

  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 }

输出(不正确)

    [sourav@himanshu] ./chkalign 0x924000000 
0Aligned to 0 
Aligned to 0x80000000 
Aligned to 0x40000000 
Aligned to 0x20000000
Aligned to 0x10000000
Aligned to 0x8000000
Aligned to 0x4000000

我们可以看到在 atoi 函数显示为 0 后打印时 addr 的值。

请多多指教……

【问题讨论】:

  • 你试过strtol()吗?
  • 不要包含行号,否则我们无法轻松地将您的代码复制/粘贴到文本编辑器中并进行编译。
  • 在这里询问时,真的要把你的代码简化为一个最小的例子。您的问题与解释地址无关。正如你在标题中所说的那样,atoi 有问题,所以解决这个问题,并省略所有无趣的东西。
  • 请不要在代码示例中使用行号,这会使 CPR(剪切粘贴并运行)和 PCV(发布更正版本)复杂化。

标签: c memory-alignment atoi


【解决方案1】:

数字0x924000000是十六进制的,所以你应该使用strtol()并将其存储在long

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

【讨论】:

  • strtoul 在这种情况下更有意义。
  • 使用0 代替16 将允许以更通用的格式读取数字,十进制、八进制或十六进制。
  • 使用 strtoull addr=strtoull(argv[1],NULL,0); 打印地址时打印不正确./chkalign 0x924000000 addr:0x24000000 而不是 0x924000000
  • 这取决于您平台上long 的大小。它在 Windows 中只有 32 位。检查我的答案。
【解决方案2】:

您没有指定平台,请注意内存地址的大小不一定与int 相同。 atoi 返回一个 int,这就是问题所在。

即使long 也可能不足以容纳内存地址(如在 Windows IIRC 中)。因此,您应该使用strtoull 返回一个unsigned long long,保证至少为64 位。还使用0 作为转换的基础,允许在命令行上将地址输入为0x80000000。还要与您的类型更加一致和可移植:long 不一定是 64 位,因此不应在 printf 中将其打印为 "%lx"

还要努力打造自己的风格。一致性有助于避免错误。

这是一个更正的版本:

#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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-20
    • 2015-07-20
    • 2012-07-04
    • 2014-02-19
    • 2017-01-03
    • 1970-01-01
    相关资源
    最近更新 更多