使用带有结构/数组的头文件的指针问题,导致多重定义错误(C)

Posted

技术标签:

【中文标题】使用带有结构/数组的头文件的指针问题,导致多重定义错误(C)【英文标题】:Pointer problem using header file with struct/array, resulting in multiple defenitions error (C) 【发布时间】:2021-05-27 17:16:37 【问题描述】:

我有一个程序(背包,经过优化以返回具有最小重量的最高价值解决方案),我想将外部文件用于 typedef 和 struct 数据。

但我无法让它工作,我在某个地方弄乱了指针。我收到一个“多重定义”错误,或者当我更改它时,我收到一个“xxx 未声明”错误...

/tmp/ccMy5Yw0.o:(.data+0x0): `item1'的多重定义

非常感谢您指出我的思维错误的任何帮助。 (我在线编译@https://www.onlinegdb.com/)

当我将所有内容都放在一个文件中时,它确实有效,但是在将其拆分为不同的文件后,我无法让它工作......

main.c

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#include "defs.h"
#include "data.c"

item_t *items[ITEMS_SIZE] =  &item1, &item2, &item3, &item4, &item5, &item6, &item7, &item8,   &item9, &item10 ;

int *knapsack (item_t * items, int n, int w)

  int h, h_i, h_j, i, j, a, b, *mm, **m, *s;
  mm = calloc ((n + 1) * (w + 1), sizeof (int));
  m = malloc ((n + 1) * sizeof (int *));
  m[0] = mm;
  h = m[0][0];
  h_i = 0;
  h_j = 0;
  for (i = 1; i <= n; i++)
    
      m[i] = &mm[i * (w + 1)];
      for (j = 0; j <= w; j++)
    
      if (items[i - 1].weight > j)
        
          m[i][j] = m[i - 1][j];
        
      else
        
          a = m[i - 1][j];
          b = m[i - 1][j - items[i - 1].weight] + items[i - 1].value;
          m[i][j] = a > b ? a : b;
          if (m[i][j] > h)
        
          h = m[i][j];
          h_i = i;
          h_j = j;
        
        
      printf ("%d\t%d\t%d\n", h, h_i, h_j);
    
    
  s = calloc (n, sizeof (int));
  for (i = h_i, j = h_j; i > 0; i--)
    
      if (m[i][j] > m[i - 1][j])
    
      s[i - 1] = 1;
      j -= items[i - 1].weight;
    
    
  free (mm);
  free (m);
  return s;


int main ()

  int i, n, tw = 0, tv = 0, *s;
  for (i = 0; i < 10; i++)
    
      if (items[i]->SwitchOn)
    
      items[i]->value = items[i]->value;
    
      else
    
      items[i]->value = 0;
    
    
  n = sizeof (items) / sizeof (item_t);
  s = knapsack (items, n, 690);
  for (i = 0; i < n; i++)
    
      if (s[i])
    
      printf ("%-22s %5d %5d\n", items[i]->name, items[i]->weight,
          items[i]->value);
      tw += items[i]->weight;
      tv += items[i]->value;
    
    
  printf ("%-22s %5d %5d\n", "totals:", tw, tv);
  return 0;

defs.h

    #ifndef SYSTEMDEFS_H_INCLUDED
    #define SYSTEMDEFS_H_INCLUDED
    
    #define ITEMS_SIZE 10
    
    typedef struct Item
    
      char name[40];
      int weight;
      int value;
      bool SwitchOn;
     item_t;
    
    extern item_t item1;
    extern item_t item2;
    extern item_t item3;
    extern item_t item4;
    extern item_t item5;
    extern item_t item6;
    extern item_t item7;
    extern item_t item8;
    extern item_t item9;
    extern item_t item10;
    
    #endif

数据.c

#include <stdbool.h>
#include "defs.h"

item_t item1 =

    .name = "part1",
    .weight = 25,
    .value = 8,
    .SwitchOn = false,
;

item_t item2 =

    .name = "part2",
    .weight = 40,
    .value = 2,
    .SwitchOn = true,
;

item_t item3 =

    .name = "part3",
    .weight = 60,
    .value = 7,
    .SwitchOn = false,
;

item_t item4 =

    .name = "part4",
    .weight = 100,
    .value = 6,
    .SwitchOn = false,
;

item_t item5 =

    .name = "part5",
    .weight = 150,
    .value = 2,
    .SwitchOn = true,
;

item_t item6 =

    .name = "part6",
    .weight = 380,
    .value = 10,
    .SwitchOn = true,
;

item_t item7 =

    .name = "part7",
    .weight = 850,
    .value = 2,
    .SwitchOn = false,
;

item_t item8 =

    .name = "part8",
    .weight = 75,
    .value = 15,
    .SwitchOn = true,
;

item_t item9 =

    .name = "part9",
    .weight = 800,
    .value = 1,
    .SwitchOn = false,
;

item_t item10 =

    .name = "part10",
    .weight = 75,
    .value = 8,
    .SwitchOn = true,
;

【问题讨论】:

从 main.c 中删除 #include "data.c"。 【参考方案1】:

正如您在main.c 中包含data.c

#include "defs.h"
#include "data.c"

那么现在data.c 中的代码在两个翻译单元中重复:一个带有main.c,另一个带有data.c

删除这一行

#include "data.c"

来自main.c

还要注意,如果您声明了 item_t *[ITEM_SIZE] 类型的数组

item_t *items[ITEMS_SIZE] =  /*...*/ ;

因此,如果您将其作为参数表达式传递给函数,它会隐式转换为指向其第一个 item_t ** 类型元素的指针。但是您将数组传递给函数knapsack

s = knapsack (items, n, 690);

第一个参数的类型为item_t *

int *knapsack (item_t * items, int n, int w)

所以编译器应该发出一个指针类型不兼容的消息。这就是该函数是否被错误地声明和定义,或者您调用它时提供了不正确的参数。

【讨论】:

亲爱的弗拉德,现在这部分工作正常,但是背包函数不会从数组项中读取值...我得到的都是 0...

以上是关于使用带有结构/数组的头文件的指针问题,导致多重定义错误(C)的主要内容,如果未能解决你的问题,请参考以下文章

gcc:在 C++ 应用程序中链接 C 库会导致“多重定义”错误

c_cpp 带有类定义和结构定义的头文件。

带有指针数组的 HDF5 结构

C语言 文件操作的头文件

c语言中2个结构体的头指针相等,会不会把其中一个覆盖了

怎么用 C/C++ 把结构体数组转成 JSON串