退出函数后,为什么这两个char *变量的值没有改变?

时间:2014-05-29 08:57:28

标签: c pointers command-line

我填充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&amp; file2在执行parseArguments函数之前仍保留其旧值。我试图解决这个问题,但我没有结果......

希望你们能提供帮助,非常感谢先进!

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

5 个答案:

答案 0 :(得分:2)

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

你可能想要:

  1. 将文本复制到file1file2引用的缓冲区,或
  2. file1file2的地址传递给该函数,并修改调用者看到的值。
  3. 选项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];
        ....
    }
    

答案 1 :(得分:1)

file1 = &argv[optind];

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

那是:

char **file1, char **file2

而不是

char* file1, char* file2

答案 2 :(得分:0)

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函数的参数!

如果要传入无法修改的缓冲区地址,则必须将内存转移到该缓冲区(并忽略上面的注释),例如:

strcpy (file1, argv[optind]);

虽然你可能想要预先检查长度以防止缓冲区溢出,或者使用更安全的边界检查内存复制功能。

答案 3 :(得分:0)

因为您更改指针的地址,而不是值。

你有办法:

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

答案 4 :(得分:0)

如果file1file2指向有效内存,请将argc个元素所指向的内存内容复制到file1和file2的位置points to, but assigning argc`的元素&#39;地址。

为此,请更换作业

file1 = &argv[optind];

通过复制操作

strcpy(file1, argv[optind]);

但是这样做有风险,因为在parseArgument()内部,我不知道已为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);