【问题标题】:Why are the values of these 2 char* variables didn't change after exit the function?为什么这 2 个 char* 变量的值在退出函数后没有改变?
【发布时间】:2014-05-29 08:57:28
【问题描述】:

我正在填充一个 C 程序来将 2 个输入向量相乘。代码如下:

/**
 * Function name: parseArguments
 * Description:
 *    Determine what options or arguments user used
 *    Command-line options:
 *   [-h]    : Show help information
 *   [-n] num: Determine number of threads
 *   file1   : Choose first file
 *   file2   : Choose second file
 * Return value:
 *    0: If parsing successful
 *    exit: If error
 **/
static int parseArguments(int argc, char **argv, int* nthreads, char* file1, char* file2)
{
  int opt;
  int help=0;
  extern int optind;
  extern char * optarg;    // (global variable) command-line options

  while ((opt = getopt(argc, argv, "hn:")) != EOF)
  {
    switch (opt) {
      //Parse option -h, -n
      case 'n':
        *nthreads = atoi(optarg);
        break;
    case 'h':
        Usage();
        exit(1);
        break;
      default:
        fprintf(stderr, "Try 'mulvector -h' for more information\n");
        exit(1);
    }


    // parse file1 & file2 arguments
// THIS IS WHAT I'M ASKING
        if (optind < argc)
    {
        file1 = &argv[optind];
        optind++;
    }
    if (optind < argc)
        file2 = &argv[optind];
  }

  return 0;
}

问题是,在我调用这个函数(在 main() 函数中)然后退出这个函数(继续 main() 函数)之后,2 个变量 file1 和 file2 在执行 parseArguments 之前仍然保持它们的旧值功能。我正在尝试解决这个问题,但我没有得到任何结果......

希望大家帮忙,非常感谢!

注意: file1 和 file2 的类型是 char file1[1024] 所以我不能使用 char** 作为 parseArguments 函数的参数!

【问题讨论】:

    标签: c pointers command-line


    【解决方案1】:

    C 按值传递参数。因此,您对file1file2 所做的修改只是对函数内部存在的指针的本地副本的修改。调用者看不到这些变化。

    您可能想要:

    1. 将文本复制到file1file2 引用的缓冲区,或者
    2. file1file2的地址传递给函数并修改调用者看到的值。

    选项 1 如下所示:

    static int parseArguments(..., char* file1, char* file2)
    {
        ....
        strcpy(file1, argv[optind]);
        ....
        strcpy(file2, argv[optind]);
        ....
    }
    

    当然,这是要求缓冲区溢出。因此,您还可以明智地传递缓冲区的长度以允许代码避免溢出,例如使用strncpystrncat。这里对这个问题进行了很好的讨论:Why should you use strncpy instead of strcpy?

    选项 2 如下所示:

    static int parseArguments(..., char** file1, char** file2)
    {
        ....
        *file1 = &argv[optind];
        ....
        *file2 = &argv[optind];
        ....
    }
    

    【讨论】:

    • 谢谢!你能告诉我如何解决这个错误吗?我希望 file1 和 file2 具有新的解析值!
    • 谢谢,但我忘了注意:file1 和 file2 的类型在 main() 函数中被强制为 char file1[1024],所以我不能使用 char** 作为 parseArguments 的参数函数!
    • 在这种情况下,您需要选项 1。
    【解决方案2】:
    file1 = &argv[optind];
    

    如果要修改指针对象,则必须向函数传递指向指针的指针,而不仅仅是指针对象的值。

    即:

    char **file1, char **file2
    

    而不是

    char* file1, char* file2
    

    【讨论】:

    • 谢谢,但我忘了注意:file1 和 file2 的类型在 main() 函数中被强制为 char file1[1024],所以我不能使用 char** 作为 parseArguments 的参数函数!
    • @rainman_TS7 在这种情况下你不想修改指针!请记住,您不能分配给数组。如果要复制字符串,请使用字符串复制函数,例如 strncpy
    【解决方案3】:

    因为你改变的是指针的地址,而不是值。

    你有办法:

    1. 通过链接获取变量(char*& file1、char*& file2)。
    2. 通过指针获取它们(char** file1,char** file2),但你应该调用你的函数 parseArguments(..., &amp;charPointer1, &amp;charPointer2)

    【讨论】:

      【解决方案4】:

      如果file1file2 指向有效内存,则将argc 的元素指向的内存内容复制到file1 和file2points to, but assigningargc 的元素地址的位置。

      为此替换分配

      file1 = &argv[optind];
      

      通过复制操作

      strcpy(file1, argv[optind]);
      

      但是这样做是有风险的,因为在 parseArgument() 内部它不知道有多少内存 hab 分配给 filefile2

      要绕过这个传递到parseArguments 也是这样的尺寸:

      static int parseArguments(int argc, char **argv, int* nthreads, 
        char* file1, size_t size1, 
        char* file2, size_t size2)
      {
        ...
        memset(file1, 0, size1);
        strncpy(file1, argv[optind], size1 - 1);
      

      【讨论】:

        【解决方案5】:

        C 是按值传递的,即使对于指针也是如此。如果你想改变一个指针,你需要传入一个指向它的指针,然后取消引用指针以获取它后面的变量。

        这意味着一个指向你的函数的双指针:

        static int parseArguments (int      argc,
                                   char   **argv,
                                   int     *nthreads,
                                   char   **pFile1,
                                   char   **pFile2)
        

        并使用这些指针的地址调用它:

        char *somePtr, *otherPtr;
        int rc = parseArguments (..., &somePtr, &otherPtr);
        

        也表示在函数本身内部解引用,如:

        *pFile1 = &argv[optind];
        

        实际上,ISO 很容易解决人们在 C 中必须模拟传递引用的问题。

        他们可以简单地为函数原型中的变量添加一个特殊标记,以表明它们是按引用传递的,因此在函数中对它们的访问将是间接的。

        这是否真的发生过,很难说。


        至于你的评论:

        注意:file1 和 file2 的类型是 char file1[1024] 所以我不能使用 char** 作为 parseArguments 函数的参数!

        如果你想传入一个不能修改的缓冲区地址,那么你必须将内存转移到那个缓冲区中(并且忽略我上面的cmets),比如用:

        strcpy (file1, argv[optind]);
        

        尽管您可能希望事先检查长度以防止缓冲区溢出,或者使用更安全的边界检查内存复制功能。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-06-02
          • 1970-01-01
          • 1970-01-01
          • 2011-09-15
          • 2023-01-30
          • 1970-01-01
          • 2017-02-07
          • 2022-12-06
          相关资源
          最近更新 更多