【问题标题】:Initializing pointer from argv to compare addresses从 argv 初始化指针以比较地址
【发布时间】:2018-04-22 02:16:51
【问题描述】:

我刚从 C 开始,阅读了很多关于指针和数组的内容,但似乎无法理解为什么我的代码不能正常运行。

我正在尝试使用 argv 第一个元素的地址来调节 while 循环,但没有成功。我确信我以错误的方式使用 argv。

代码如下:

int main(int k, const char* argv[]) 
{   const char** first = NULL ;
    first = &argv[0] ;
    argv += k ;
    while (argv > first) puts(*argv), argv-- ; 
    return 0 ; } 

返回分段错误。

这就是我的想法:

先创建一个指针,赋值为NULL(因为argv类型使用了两个*)

将此指针分配给 argv 第一个元素的地址 argv[0] 以使其显而易见。

将 argv 移动 argc (k)

while 循环将 argv 地址与第一个地址进行比较,只要 argv 没有到达第一个地址,就打印 *argv,然后递减 argv。

上面的代码确实应该返回命令行上的所有元素,从最后一个开始并忽略第一个(程序的名称)。

感谢您的帮助!

【问题讨论】:

    标签: c arrays pointers argv


    【解决方案1】:

    问题在于argv[k](在您的代码中对argv 进行修改之前)被定义为空指针。通过执行argv += k,您使argv 指向该空指针,然后您将其传递给puts,当puts 尝试使用该空指针时导致未定义的行为

    解决它的一种可能方法是执行例如argv += (k - 1) 代替。

    【讨论】:

    • 我使用了printf 而不是puts 并得到了要打印的第一个字符串(null)
    【解决方案2】:

    在您的情况下,argv 的大小为 1,这意味着只有 argv[0] 有效 在生成 argv+=k 时,您超出了数组边界

    【讨论】:

      【解决方案3】:

      与其更改argv 本身的值,不如简单地操作指向argv(或其中的元素)的指针。当您增加或减少 argv 本身时,您将失去对原始指针的引用。是的,您可以存储一个副本...,但是您很麻烦地声明了指向argv 的指针,只需将您的k(或argc)偏移量应用于指针,例如

      #include <stdio.h>
      
      int main (int argc, char **argv) {
      
          char **p = argv;                 /* pointer to argv */
          p += argc - 1;                   /* advance to last */
      
          printf ("\nin order:");          /* output original order */
          for (int i = 1; i < argc; i++)
              printf (" %s", argv[i]);
      
          printf ("\nreverse :");          /* decrement p outputting in reverse */
          while (p > argv)
              printf (" %s", *p--);
      
          putchar ('\n');
      
          return 0;
      }
      

      使用/输出示例

      $ ./bin/argvptr my dog has fleas
      
      in order: my dog has fleas
      reverse : fleas has dog my
      

      【讨论】:

      • 注意 HS:我仍然不明白为什么人们继续在函数的开头声明变量,而不是在他们需要的地方。
      • 通常是因为他们在 Win7 上有 cl.exe 并且需要 C89 兼容声明才能在编译器之间移植? :)
      • 他们的生活一定很糟糕!但我认为除非 OP 标记特定的编译器或 C 版本,否则答案应该反映最佳可用功能。 OP正在学习编程。 (MSVC 还不支持这个基本功能?!)
      • 哦,比这更糟糕......只需尝试使用任何有意义的函数,如 clock_gettime 或任何需要 unistd.hsys/select.h 的函数。将QueryPerformanceCounterWindows.h 拼凑到C 程序中只是为了让一个体面的计时器工作,这确实显示了该编译器的时代。但是,有些人仍然坚持使用旧的windoze :) 我将它虚拟化在带有 virtualbox 的服务器上,并通过 rdesktop 在窗口中无头运行它只是为了测试目的......
      【解决方案4】:

      我不知道我是否在这里遗漏了什么。如果您只想以相反的顺序打印参数,为什么不简单地使用这样的东西:

      #include <stdio.h>
      
      int main(int argc, char *argv[])
      {
          int i;
      
          for (i = argc - 1; i > 0; i--) {
              puts(argv[i]);
          }
          return 0;
      }
      

      【讨论】:

      • 我想OP想训练指针技能。请注意,您的回答并不能真正回答问题。
      • 谢谢八月,但我之所以使用该特定解决方案是因为练习是这样制定的,试图训练 Stargateur 指出的指针技能。不过,感谢您提供替代解决方案。
      猜你喜欢
      • 1970-01-01
      • 2017-01-30
      • 2011-10-31
      • 1970-01-01
      • 2020-11-01
      • 2015-04-25
      • 1970-01-01
      • 1970-01-01
      • 2022-12-09
      相关资源
      最近更新 更多