【问题标题】:Pointer address is not incrementing [closed]指针地址不递增[关闭]
【发布时间】:2012-10-23 20:07:47
【问题描述】:

我之前在Code Review 中已经实施了一些建议。我还通过使用指针改进了我的代码。但是,squeezed_str++ 下面的地址递增部分有什么问题?似乎地址没有增加。请指教。

PS。 substring() 函数正在工作。 :)

char *squeeze (char *str, int start_index, int end_index, char *ref_str) {
     char *substr;
     substr = malloc (sizeof (*substr));
     if (substr == NULL) {
          printf ("Unable to allocate memory.\n");
          exit (EXIT_FAILURE);
     }

     char *squeezed_str;
     squeezed_str = malloc (sizeof (*squeezed_str));
     if (squeezed_str == NULL) {
          printf ("Unable to allocate memory!\n");
          exit (EXIT_FAILURE);
     }

     substr = substring (str, start_index, end_index);
     int substr_len = strlen (substr);
     int refstr_len = strlen (ref_str);

     char chr1, chr2; chr1 = chr2 = '\0';

     for (int i = 0; i < substr_len; i++) {
          chr1 = *(substr+i);
          for (int j = 0; j < refstr_len; j++) {
               chr2 = *(ref_str + j);
               if (chr1 == chr2) {
                    break;
               }
          }
          if (chr1 != chr2) {
               *squeezed_str = *(substr+i);
               squeezed_str++;
          }     
     }

     return squeezed_str;
 } /* end of squeeze() */

【问题讨论】:

  • 这两个malloc真的很奇怪。 sizeof(*subtr) == sizeof(char).
  • sizeof(char*) 通常给出 4 或 8 个字节; strlen(char*) 给出字符串的长度
  • 另外,substr = malloc(); 然后没有转换 substr = substring()... 你泄漏了一个字节的内存。
  • ...在 1 字节 malloc 之后,我们立即通过将 ptr 设置为其他东西来泄漏它...
  • @chrismsawi ,您阅读的建议是 int *ptr = malloc( sizeof(*ptr) );这为一个整数分配空间,您想为 char * 的内容分配空间,然后 malloc(strlen(str)+1) 就可以了

标签: c optimization pointers


【解决方案1】:

内联建议的一些改进,未经测试:

char *squeeze (char *str, int start_index, int end_index, char *ref_str) {
     char *substr = substring (str, start_index, end_index);
         //do not malloc here!, you are doing an assignment later on, so memory leak
         //infact might as well move assignment right here

     char *squeezed_str;
     squeezed_str = malloc (strlen(str)+1); //+ 1 one for null terminator
     if (squeezed_str == NULL) {
          printf ("Unable to allocate memory!\n");
          exit (EXIT_FAILURE);
     }

     int substr_len = strlen (substr);
     int refstr_len = strlen (ref_str);
     int squeezeStrIdx = 0;

     for (int i = 0; i < substr_len; i++) {
          char chr1 = substr[i]; //using index accessing is nicer
                                 //moved the scope of the variable in
          char chr2 = '\0'; //reduced variable scope, benefit is now resets each loop
          for (int j = 0; j < refstr_len; j++) {
               chr2 = ref_str[j];
               if (chr1 == chr2) {
                    break;
               }
          }
          if (chr1 != chr2) {
               squeezed_str[squeezeStrIdx] = chr1;
               squeezeStrIdx++; //if you modify squeezed_str,
                                //how do you expect to return it at end of method?
          }     
     }

     //this is to null terminate the squeezed_str
     squeezed_str[squeezeStrIdx] = '\0';

     return squeezed_str;
 } /* end of squeeze() */

【讨论】:

  • 这确实成功了。有用!谢谢。但是,也许是最后一个问题。我还是不明白你为什么要引入另一个变量,squeezeStrIdx 作为数组索引。为什么会这样?请多多指教。
  • 他引入了另一个变量以不丢失返回的指针malloc。看我的回答,我做了同样的事情,但使用了另一个指针。
  • 在函数结束时返回指针squeezed_str。您的代码正在递增此指针,因此您返回的将是 squeezed_str 末尾的指针。因此,额外的变量是跟踪我们正在写入的位置,而无需更改squeezed_str 指针。它只是像 0,1,2,3,4 一样上升,并用作 squeezed_str 数组的偏移量。
  • 我刚刚添加了一个改进,一旦我们完成填充squeezed_str,我们应该空终止它。 squeezeStrIdx 偏移在正确的位置执行此操作。
【解决方案2】:

完全有缺陷的一件事是修改squeezed_str。这是malloc 返回的地址。如果您修改它,您以后将无法free 该内存区域。您造成了内存泄漏,或者更糟糕的是,您在最后调用 free 时造成了崩溃。

编辑:

 char *squeeze (const char *str, size_t start_index, size_t end_index, const char *ref_str) 
 /* You don't modify `str` and `ref_str` so it is a good idea to make it visible in the signature of the function, whence the const qualifiers */
 {
 char *substr;   
 /* Snip the memory leak */

 char *squeezed_str = malloc (sizeof (*squeezed_str));
 if (!squeezed_str) {
      fprintf (stderr, "Unable to allocate memory!\n");  /* Error are to be written on stderr */
      exit (EXIT_FAILURE);     /* Exitting the app in a function is not good style */
 }

 substr = substring (str, start_index, end_index);
 size_t substr_len = strlen (substr);       /* strlen returns size_t not int */
 size_t refstr_len = strlen (ref_str);

 char chr1 = 0, chr2 = 0;
 char *squeezed_copy = squeezed_str;       /* We use a second pointer to not lose the malloc'ed area */
 for (size_t i = 0; i < substr_len; i++) {
      chr1 = substr[i];                     /* This syntax is simpler (you'll see when you have nested structures */
      for (size_t j = 0; j < refstr_len; j++) {
           chr2 = ref_str[j];
           if (chr1 == chr2) {
                break;
           }
      }
      if (chr1 != chr2)
           *squeezed_copy++ = substr[i];
 }
 /* Add the NUL sentinel */
 *squeezed_copy++ = 0;

 return squeezed_str;
} /* end of squeeze() */

这就是说,我没有检查算法是否符合您的预期。我预感会说使用strstr 会更好。

【讨论】:

  • 这也成功了!谢谢! :)
  • 我想提出一个问题。你说“以功能退出应用程序不是很好的风格”,为什么会这样,我应该如何改进我的?当我阅读您的代码时,我得到了许多非常有用的、一致的实现。非常感谢。
  • 在 1 个小程序中,退出一个函数并没有那么糟糕,但是如果你的函数是一个实用函数(最终将成为库的一部分),那么当你的程序,调用该函数,突然停止,没有给调用者清理的机会(关闭文件、套接字、信号,等等)。
  • 一个函数可以使用return error_code。当然,调用者必须根据返回的错误采取措施。对于更大的程序,这是更好的方法,调用者可以忽略或正确处理错误。
  • 非常感谢。我会尝试实施您的建议。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-29
  • 1970-01-01
  • 1970-01-01
  • 2021-12-27
  • 2012-01-02
  • 1970-01-01
  • 2021-12-11
相关资源
最近更新 更多