【问题标题】:Concatenating 2 arrays in C [duplicate]在C中连接2个数组[重复]
【发布时间】:2017-02-27 04:59:07
【问题描述】:

我正在尝试创建一个连接 2 个数组然后返回 sum 数组的函数。 我一直在使用以下代码:

    #include "stdio.h";

struct array {
    int length;
    int *array;
};

struct array add(struct array a, struct array b) {
    int length = a.length + b.length;
    int sum[length];
    for (int i = 0; i < length; ++i) {
        if (i < a.length) {
            sum[i] = a.array[i];
        } else {
            sum[i] = b.array[i - a.length];
        }
    }

    struct array c;
    c.length = length;
    c.array = sum;
    return c;
}

int main() {
    int a[] = {1, 2, 3};
    struct array s1;
    s1.array = a;
    s1.length = sizeof(a) / sizeof(a[0]);

    int b[] = {4, 5, 6};
    struct array s2;
    s2.array = b;
    s2.length = sizeof(b) / sizeof(b[0]);

    struct array sum = add(s1, s2);
    for (int i = 0; i < sum.length; ++i) {
        printf("%d\n", sum.array[i]);
    }
    return 0;
}

输出是: 1、 17, 6356568, 1959414740, 1、 1959661600

我做错了什么?

【问题讨论】:

  • 将指针返回到本地数组根本无法正常工作。您必须使用malloc() 或其他方式分配空间。

标签: c arrays


【解决方案1】:

这三行很有问题:

int sum[length];
...
c.array = sum;
return c;

首先声明local 变量sum。在第二个中,您使 c.array 指向局部变量。在第三行中,当局部变量超出范围时返回指针。

由于局部变量超出范围,它不再存在,指向它的指针也不再有效。使用指针会导致未定义的行为

要解决这个问题,您需要动态分配内存,例如malloc.

【讨论】:

    【解决方案2】:

    sumadd 函数的局部变量。当你设置c.array = sum;,那么指针c.array就指向这个局部变量。

    函数返回后,局部变量被销毁。所以这个指针现在是一个悬空指针。但是在main 中,你会阅读这个指针。

    要解决此问题,您需要对程序的设计进行根本性更改。例如,在所有情况下对struct array 使用动态分配。

    【讨论】:

      【解决方案3】:

      C 中的数组只是一个连续的内存区域,带有指向它们的 start* 的指针。所以合并它们涉及:

      1. 求数组 A 和 B 的长度(您可能需要知道元素的数量和每个元素的 sizeof
      2. 分配 (malloc) 一个大小为 A + B 的新数组 C。
      3. 将内存从 A 复制 (memcpy) 到 C,
      4. 将内存从 B 复制到 C + A 的长度(参见 1)。

      您可能还想取消分配 (free) A 和 B 的内存。

      示例代码sn-p:

      #include <stdlib.h>
      #include <stdio.h>
      #include <string.h>
      
      #define ARRAY_CONCAT(TYPE, A, An, B, Bn) \
      (TYPE *)array_concat((const void *)(A), (An), (const void *)(B), (Bn), sizeof(TYPE));
      
      void *array_concat(const void *a, size_t an,const void *b, size_t bn, size_t s)
      {
          char *p = malloc(s * (an + bn));
          memcpy(p, a, an*s);
          memcpy(p + an*s, b, bn*s);
          return p;
      }
      
      // testing
      const int a[] = { 1, 1, 1, 1 };
      const int b[] = { 2, 2, 2, 2 };
      
      int main(void)
      {
          unsigned int i;
      
          int *total = ARRAY_CONCAT(int, a, 4, b, 4);
      
          for(i = 0; i < 8; i++)
              printf("%d\n", total[i]);
      
          free(total);
          return EXIT_SUCCCESS;
      }
      

      【讨论】:

        【解决方案4】:

        试试这个 - 更正 add 函数:

        #include <stdlib.h>
        
        struct array add(struct array a, struct array b) {
            int length = a.length + b.length;
            int * sum = (int*)calloc(length, sizeof(int));
            for (int i = 0; i < length; ++i) {
                if (i < a.length) {
                    sum[i] = a.array[i];
                }
                else {
                    sum[i] = b.array[i - a.length];
                }
            }
        
            struct array c;
            c.length = length;
            c.array = sum;
            return c;
        }
        

        stdlib 需要使用calloc 功能。

        该函数为 int 类型的 length 值分配内存。为确保内存分配成功,建议分配后检查指针sum的值,例如:

         int * sum = (int*)calloc(length, sizeof(int));
         if( sum != NULL )
         {
             // use memory and return result
         }
         else
         {
             // do not use pointer (report about error and stop operation)
         }
        

        【讨论】:

        • 为什么是calloc?你覆盖循环中的每个元素,所以malloc应该这样做,我猜。不需要演员表,顺便说一句。主题:我更喜欢两个 for 循环并避免使用 if 语句。
        • 你即将写入每个分配的字节;无需使用calloc(),它也会写入每个分配的字节。
        • @4386427:比我快 2 秒……如果我没有分心的话……
        • 没问题,可以用malloc代替calloc,而且可以去掉演员表,当然还有两个for——大家可以随便写,我刚刚做了使代码能够工作的最小更改
        【解决方案5】:

        正如 Joachim 所提到的,您正在返回一个局部变量 int sum[length]; 这是一个坏主意。变量sum在函数退出后返回栈,可以被其他栈变量覆盖。

        解决这个问题的方法之一是首先不在sum 函数中声明数组。 sum_str 在 main 中声明。您可以将指向此结构的指针传递给sum 函数。

        更新后的代码如下。

        #include <stdio.h>
        
        struct array {
            int length;
            int *array;
        };
        
        void add(struct array a, struct array b, struct array *sum_str) {
            sum_str->length = a.length + b.length;
            for (int i = 0; i < sum_str->length; ++i) {
                if (i < a.length) {
                    sum_str->array[i] = a.array[i];
                } else {
                    sum_str->array[i] = b.array[i - a.length];
                }
            }
        }
        
        int main() {
            int a[] = {1, 2, 3};
            struct array s1;
            s1.array = a;
            s1.length = sizeof(a) / sizeof(a[0]);
        
            int b[] = {4, 5, 6};
            struct array s2;
            s2.array = b;
            s2.length = sizeof(b) / sizeof(b[0]);
        
            struct array sum_str;
            int sum_a[6];
            sum_str.array = sum_a;
        
            add(s1, s2, &sum_str);
            for (int i = 0; i < sum_str.length; ++i) {
                printf("%d\n", sum_str.array[i]);
            }
            return 0;
        }
        

        另一种方法是使用其他答案所述的动态内存分配。

        【讨论】:

          猜你喜欢
          • 2019-08-04
          • 2021-08-30
          • 2021-05-19
          • 2020-11-19
          • 2013-10-04
          • 1970-01-01
          • 2023-03-21
          • 2017-01-23
          • 2011-02-08
          相关资源
          最近更新 更多