返回信息流A.cpp:
int arr[] = {1, 2, 3};
B.cpp:
#include <iostream>
using namespace std;
extern int* arr; //写成extern int arr[];没问题
int main(int argc, char const *argv[])
{
cout << arr[0] << " " << arr[1] << " " << arr[2];
return 0;
}
编译可以通过,但是运行时会出错。为什么不能声明为指针呢?
这是一条镜像帖。来源:北邮人论坛 / cpp / #77803同步于 2014/3/25
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
请教一个关于声明的问题
abkdnh
2014/3/25镜像同步7 回复
订阅后,新回复会通过你的通知中心匿名送达。
7 条回复
1. 编译器在编译时候无法知道除本文件外其他文件中的变量类型;
2. 保证同一个变量的相同类型是程序员应该做的事情;
3. 数组和指针不同, A.cpp 中 arr 是个 int array, B.app 中 arr 是个 int pointer,类型不同;
4. 具体可以参见 《C陷阱与缺陷》 4.5 章。
【 在 Leavetaking 的大作中提到: 】
: 1. 编译器在编译时候无法知道除本文件外其他文件中的变量类型;
: 2. 保证同一个变量的相同类型是程序员应该做的事情;
: 3. 数组和指针不同, A.cpp 中 arr 是个 int array, B.app 中 arr 是个 int pointer,类型不同;
: ...................
那我在B.cpp里面使用指针arr的时候,它是指向哪里呢?
arr[]中的arr是一个符号常量,它实际上是数组的首地址;
extern int *arr中,需要分析下编译器在遇到这句时是怎么处理arr的,他通过搜索发现已经有一个非static的arr了,所以他认为arr这个变量已经存在一个实体了,不会为arr分配空间,直接把arr定为到arr[]上,而后者实际上是一个地址,所以B.cpp文件中arr为arr[]开始的前四个字节所表示的地址。可以表示为&arr(in B.cpp) = arr[0-3byte](in a.cpp)
【 在 abkdnh 的大作中提到: 】
: A.cpp:
: int arr[] = {1, 2, 3};
: B.cpp:
: ...................
【 在 gaoweiwei 的大作中提到: 】
: arr[]中的arr是一个符号常量,它实际上是数组的首地址;
: extern int *arr中,需要分析下编译器在遇到这句时是怎么处理arr的,他通过搜索发现已经有一个非static的arr了,所以他认为arr这个变量已经存在一个实体了,不会为arr分配空间,直接把arr定为到arr[]上,而后者实际上是一个地址,所以B.cpp文件中arr为arr[]开始的前四个字节所表示的地址。可以表示为&arr(in B.cpp) = arr[0-3byte](in a.cpp)
既然如此,为什么cout << arr[0] << " " << arr[1] << " " << arr[2];会出错呢?
上帖说过了。为了方便,把B.cpp里的arr叫做arrB,A.cpp里的arr叫arrA。arrB这个变量定位于arrA数组的起始,arrB所指向的地址是arrA起始四个字节所表示的值,也就是0x1,访问arrB[n]就是访问0x1 + n * 4,肯定会出错了。你可以cout << arrB,看看是不是1。
【 在 abkdnh 的大作中提到: 】
:
: 既然如此,为什么cout << arr[0] << " " << arr[1] << " " << arr[2];会出错呢?
【 在 gaoweiwei 的大作中提到: 】
: 上帖说过了。为了方便,把B.cpp里的arr叫做arrB,A.cpp里的arr叫arrA。arrB这个变量定位于arrA数组的起始,arrB所指向的地址是arrA起始四个字节所表示的值,也就是0x1,访问arrB[n]就是访问0x1 + n * 4,肯定会出错了。你可以cout << arrB,看看是不是1。
我的本意是想让arrB保存arrA的首地址,而事实上却保存了arrA[0](即1),是这个意思吧
是的,结果如你所述。
【 在 abkdnh 的大作中提到: 】
:
: 我的本意是想让arrB保存arrA的首地址,而事实上却保存了arrA[0](即1),是这个意思吧