【问题标题】:Code containing array definitions working great in main function, but not when I include it from a separate file, why?包含数组定义的代码在 main 函数中运行良好,但当我从单独的文件中包含它时却不行,为什么?
【发布时间】:2015-02-23 02:52:47
【问题描述】:

所以我有这段代码,它构建了一个字符串数组(23 个不同大小的字符串)。 为此,我分别定义了每个字符串,如下所示:

char text1[] = "The content of string 1\n";
char text2[] = "The content of string 2 which is longer\n";

剩下的 21 个字符串也是如此。然后我为每个字符串定义了 23 个指向 char 的指针,如下所示:

char *ptext1 = text1; 
char *ptext2 = text2;

剩下的 21 个字符串也是如此。然后我定义了一个指向 char 的指针数组,并用我刚刚创建的 23 个指针对其进行了初始化:

char *parray[23];
parray[0] = ptext1;
parray[1] = ptext2; // ...etc.

现在,为了按索引访问字符串,我使用 for 循环遍历元素:

for (i = 0; i < 23; i++)
{
        printf("%s", parray[i]);
}

这段代码在 main 函数中就像一个魅力,然而,当我将所有的字符串、指针和数组定义移动到一个头文件时(因为我认为将定义排除在外是一个好习惯,对吧?)并将其包含在 main.c 文件中,在那里我只有 for 循环,但它不起作用。编译器会显示各种警告和错误,例如:

warning: Data definition has to type or storage class (Then it shows this line:) parray[0] = text1;
error: Conflicting types for 'parray'
note: Previous declaration of 'parray' was here: char *parray[23];
error: Invalid Initialized parray[0] = text1;

它继续显示所有 23 个元素的类似警告和错误。

那么为什么这段代码在主函数中像我想要的那样工作,但在我包含它时却没有?

注意:

我正在为 windows 使用 mingw gcc 编译器,当我编译时,我使用这个命令:gcc main.c 而且头文件当然在同一个目录下。

这是一个副本/过去或错误输出:

In file included from x.c:2:0:
x.h:15:2: warning: data definition has no type or storage class [enabled by default]
  parray[0] = ptext11;
  ^
x.h:15:2: error: conflicting types for 'parray'
x.h:13:8: note: previous declaration of 'parray' was here
  char *parray[2];
        ^
x.h:15:2: error: invalid initializer
  parray[0] = ptext11;
  ^
x.h:16:2: warning: data definition has no type or storage class [enabled by default]
  parray[1] = ptext12;
  ^
x.h:16:2: error: conflicting types for 'parray'
x.h:13:8: note: previous declaration of 'parray' was here
  char *parray[2];
        ^
x.h:16:2: error: invalid initializer
  parray[1] = ptext12;
  ^

这是 main.c 文件:

#include <stdio.h>
#include "main.h"


void main(void)
{

    int i;
    for (i = 0; i < 2; i++)
    {
        printf("%s", parray[i]);
    }
}

还有main.h文件:

char text11[] = "Content of string 1";

char text12[] = "Content of string 2, which is longer";


char *ptext11 = text11, *ptext12 = text12;

char *parray[2];

parray[0] = ptext11;
parray[1] = ptext12;

【问题讨论】:

  • 请创建一个MCVE 来说明您的问题。
  • 您的错误消息中有印刷错误,您可以剪切并粘贴它,而不是尝试手动转录。
  • text1text2chars,只能容纳一个字符。
  • @CoolGuy,不,text1 和 text2 是字符串,我测试了这段代码,工作如我所愿
  • 查看您发布的内容。 char text1="..."char text2=".."。这些不是字符数组。

标签: c arrays string include


【解决方案1】:

在您的代码中,text1 是单个 charchars 数组中你想要的。

更改您的代码

char text1 = "The content of string 1\n";

char *parray[23];
parray[0] = ptext1;
parray[1] = ptext2; // ...etc.

char text1[] = "The content of string 1\n";
char *ptext1 = text1; 

char **parray= NULL;
parray = malloc(23 * sizeof (*parray));
parray[0] = ptext1;
parray[1] = ptext2; // ...etc.

最后,free(parray)

注意:使用char *ptext1 和family 是多余的。使用更正的版本。可以直接写parray[0] = text1之类的。


编辑:

根据您的最新编辑,您似乎正在尝试在头文件中初始化数组中的每个元素一个接一个。这是不允许的。将数组放在头文件中会使数组的范围成为全局的。您只能在声明/定义时使用char *parray[23] = {&lt;set of initializers&gt;} 初始化全局数组,之后不能。你不能这样做

parray[0] = ptext1;
parray[1] = ptext2;

在头文件[全局范围]中。否则,您必须在函数内部执行此操作。

【讨论】:

  • 但是为什么我的代码在 main 中有效,但在单独包含时无效?如果它措辞一次,它应该再次起作用,不是吗?
  • @the-sizixe 您的代码与您在此处发布的不同。查看错误消息parray[0] = text1;,但您发布的是parray[0] = ptext1;。正确检查您的代码。
  • 除了在您发布答案后应用了 OP 的更改之外,我看不出从静态分配的数组切换到动态的数组如何解决 OP 的问题。
  • @alk 先生,主要问题是 text1text1[]char *ptext1 = text1。可以将动态分配视为建议。
  • @alk 先生,OP 的帖子似乎存在一个重大的概念问题。请检查我的更新答案。
【解决方案2】:

在 C 语句中,例如:

parray[0] = ptext11;
parray[1] = ptext12;

不能出现在上下文之外,也就是只能出现在函数内部。

要根据定义初始化parray

char *parray[2] = {ptext11, ptext12};

更新:

假设这个

char text11[] = "Content of string 1";
char text12[] = "Content of string 2, which is longer";
char *ptext11 = text11, *ptext12 = text12;

代码甚至可以缩短为:

char *parray[2] = 
{
  "Content of string 1",
  "Content of string 2, which is longer"
};

或更方便的版本:

char *parray[] = 
{
  "Content of string 1",
  "Content of string 2, which is longer",
  NULL
};

NULL 表示数组的结尾,可用于确定运行时元素的数量。这允许您在较新版本的代码中向数组添加更多字符串,而无需调整任何定义数组大小的变量。

确定元素数量的函数示例如下:

ssize_t number_of_array_elements(char ** parray)
{
  ssize_t result = 0;

  if (NULL == *parray)
  {
    result = -1;
    errno = EINVAL;
  }
  else
  {
    while (NULL != *parray)
    {
      ++result;
      ++parray;
    }
  }

  return result;
}

像这样使用它:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>


char * parray[] = {
  "Content of string 1",
  "Content of string 2, which is longer",
  NULL
};

int main(void)
{
  size_t size = 0;

  {
    ssize_t result = number_of_array_elements(parray);
    if (-1 == result)
    {
      perror("array_elements() failed");
      exit(EXIT_FAILURE);
    }

    size = result;
  }

  printf("parray holds %zu elements.\n", size);

  exit(EXIT_SUCCESS);
}

【讨论】:

  • 是的,谢谢@alk 先生,但我想知道哪些文档有这些信息?直到现在我才知道这一点。 (请注意,我是 C 新手)
  • @the-sizixe:它可能在您首选的简历入门的第一章中有所描述?如果不是切换到另一本书。
  • 我明白了,你能推荐我一本书吗?那教C,而不是编程。我想通过这样的知识提高我的 C 技能。
猜你喜欢
  • 1970-01-01
  • 2018-07-31
  • 2018-01-22
  • 2019-11-17
  • 2017-07-21
  • 1970-01-01
  • 2017-10-23
  • 1970-01-01
  • 2012-04-25
相关资源
最近更新 更多