【问题标题】:cannot access array defined in external file, W/O the keyword "extern"无法访问外部文件中定义的数组,W/O 关键字“extern”
【发布时间】:2015-06-09 08:51:04
【问题描述】:

我发现无论如何,我都无法访问在外部文件中定义的数组。所以我在 c 和 c++ 中都做了一些简单的测试:

在 C 中:

main.c

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

int func();
char arr[100]="";

int main()
{
  for(int i=0;i<=9;++i){
    func();
    printf("%s\n",arr);
  }
return 0;
}

func.c

#include<string.h>
#include<stdio.h>

extern char* arr;
int func(){
  strcat(arr,"hello");          // try to access arr here
  return 0;
}

在 C++ 中:

main.cpp

#include<iostream>
using namespace std;

int func();
char arr[100]="";

int main()
{
  for(int i=0;i<=10;++i){
    func();
    cout<<arr<<endl;
  }
return 0;
}

func.cpp

#include<cstring>
extern char* arr;

int func(){
  strcat(arr,"hello");      // try to access arr here

  return 0;
}

如您所见,非常简单的测试。无论我使用什么方法访问外部文件中的数组,都会出现分段错误。

【问题讨论】:

  • 我不确定,但可能是因为在 main 中您将其声明为 arr[100] 而在 func 中您将其声明为 *arr
  • 是的。这显然是两种不同的类型。

标签: c++ c arrays


【解决方案1】:

变量链接不是类型安全的。

问题是您定义名称“arr”来引用数组。
假设数组位于地址 0x10,它看起来像这样:

Address     0x10  0x11  0x12  0x13
Content    |  0  |  0  |  0  |  0 | (... 100 zeroes in total)

名称“arr”是指存储此数组的位置。

在“func.cpp”(和“func.c”——它们的工作原理完全相同)中,您声称或声明,名称“arr”指的是一个指针。
这是一个谎言,因为它不是你定义的那样,而是编译器和链接器盲目地信任你。

这个谎言导致func 中的代码将存储在地址 0x10 的值解释为指针而不是数组。
使用 32 位指针,那将是

Address  0x10   0x14
Content |  0  |  0  | (...)

而当您将strcat 转到0 时,事情就不顺利了。

如果您在数组中存储比零更不同的内容(例如"\1\2\3\4")并在调试器中检查指针,则更明显的是数组的元素已“变成”指针的值。

解决办法是提出正确的主张; arr 是一个数组:

extern char arr[];

(请注意,在变量声明中,与函数参数相反,char arr[]不与char* arr 相同。)

【讨论】:

  • @walkerlala 不,它只是在“arr”的类型上撒谎。两个“arr”指的是同一个地方,但对存储在那个地方的内容有不同的解释。
【解决方案2】:

使用

extern char arr[];

而不是

extern char* arr;

虽然在 C 语言中很多情况下数组被隐式转换为指针,但数组与指针不同。你所拥有的是一个指针,而不是声明。 func.c 中的声明与 main.c 中的定义不匹配。

【讨论】:

  • 所以你的意思是,我声明了一个指针(类型为char),而不是让“arr”可访问?
  • @walkerlala 问题不在于它不可访问,而在于你声称它是一个指针,而它实际上是一个数组。
  • 据我了解,这会导致问题,因为我声明了一个新指针,而不是“extern” var。对吗?
  • @BlueMoon “指针”是数组的第一个 sizeof(char*) 元素,经过重新解释。
  • 换句话说:char arr[]="abcd";中的arr指的是数组的基地址(即char'a'的位置)而arr中的arr只是指向基地址。 molbdnilo 的回答更好地解释了这一点。
【解决方案3】:

简单的事情是你必须在两个地方都使用 extern 关键字。
在 main.c 中

extern char arr[100]="";

在 func.c 中

extern char *arr;

这将告诉编译器 arr 是一个外部变量名,以便可以在其他文件中访问它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-08
    • 2021-10-04
    • 2013-06-02
    相关资源
    最近更新 更多