首页
社区
课程
招聘
[旧帖] C++中结构体变量互相引用的问题 0.00雪花
发表于: 2015-11-30 23:48 5104

[旧帖] C++中结构体变量互相引用的问题 0.00雪花

bxc 活跃值
6
2015-11-30 23:48
5104
见如下代码:
struct AA_T
{
  struct BB_T     * lpBB;
  int               NumberOfBB;
};

struct BB_T
{
  struct AA_T     * lpAA;
  int               NumberOfAA;
};

AA_T aa0[] =
{
  { bb0, sizeof(bb0) / sizeof(BB_T) }
  ,
  { bb1, sizeof(bb1) / sizeof(BB_T) }
};

AA_T aa1[] =
{
  { bb0, sizeof(bb0) / sizeof(BB_T) }
  ,
  { bb1, sizeof(bb1) / sizeof(BB_T) }
};

BB_T bb0[] =
{
  { aa0, sizeof(aa0) / sizeof(AA_T) }
  ,
  { aa1, sizeof(aa1) / sizeof(AA_T) }
};

BB_T bb1[] =
{
  { aa0, sizeof(aa0) / sizeof(AA_T) }
  ,
  { aa1, sizeof(aa1) / sizeof(AA_T) }
};


如果这样写的话,MSVC会提示
error C2065: “bb0”: 未声明的标识符
error C2065: “bb1”: 未声明的标识符


将以上代码改写成
struct AA_T
{
  struct BB_T     * lpBB;
  int               NumberOfBB;
};

struct BB_T
{
  struct AA_T     * lpAA;
  int               NumberOfAA;
};


[COLOR="Red"]extern BB_T bb0[], bb1[];


AA_T aa0[] =
{
  { bb0, sizeof(bb0) / sizeof(BB_T) }
  ,
  { bb1, sizeof(bb1) / sizeof(BB_T) }
};

AA_T aa1[] =
{
  { bb0, sizeof(bb0) / sizeof(BB_T) }
  ,
  { bb1, sizeof(bb1) / sizeof(BB_T) }
};

BB_T bb0[] =
{
  { aa0, sizeof(aa0) / sizeof(AA_T) }
  ,
  { aa1, sizeof(aa1) / sizeof(AA_T) }
};

BB_T bb1[] =
{
  { aa0, sizeof(aa0) / sizeof(AA_T) }
  ,
  { aa1, sizeof(aa1) / sizeof(AA_T) }
};


还是会提示
error C2070: “BB_T []”: 非法的 sizeof 操作数


为了方便修改结构体数组,所以不打算显示的声明数组个数,但是这样用extern声明的话,又无法正常的sizeof。请问这种情况该怎么写代码。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
struct BB_T
2015-12-1 10:01
0
雪    币: 236
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3



#define __countof(arr) (sizeof(arr)/ sizeof(arr[0]))

typedef struct AA_T {
struct BB_T * lpBB;
int NumberOfBB;
} AA_T;

typedef struct BB_T {
struct AA_T * lpAA;
int NumberOfAA;
} BB_T;


size_t len_aa0 = 0;
size_t len_bb0 = 0;

extern struct BB_T bb0[];

AA_T aa0[] = {
{ bb0, 0} ,
};

BB_T bb0[] = {
{ aa0, 0} ,
};

class AutoInit
{
private:
AutoInit()
{
// 初始化
// TODO
aa0[0].NumberOfBB = __countof(bb0);
bb0[0].NumberOfAA = __countof(aa0);
}
public:
static AutoInit& Instance()
{
static AutoInit sc;
return sc;
}
};
// 调用 一次
AutoInit& at = AutoInit::Instance();




int _tmain(int argc, _TCHAR* argv[])
{
printf("%d\r\n", aa0[0].NumberOfBB);
printf("%d\r\n", bb0[0].NumberOfAA);

return 0;
}
2015-12-1 10:49
0
雪    币: 7048
活跃值: (3527)
能力值: ( LV12,RANK:340 )
在线值:
发帖
回帖
粉丝
4
这样弄,还不如弄个宏显示声明数组个数呢.
2015-12-1 11:28
0
雪    币: 250
活跃值: (81)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
你这样省事吗?
一是不方便阅读,二不方便维护
2015-12-2 14:50
0
雪    币: 35
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
问题就出在标红的这句话上,编译器只知道 bb0 和 bb1 是两个数组,但是不知道多大。这时对它们用 sizeof ,编译器是不可能知道的。

把标红的这句话中方括号里面加上元素个数,编译就可以通过了,但是这样非常难维护。

直接用宏来定义数组元素的个数,在这里也不好,也是难维护:如果增删数组元素,必须同时改宏定义。

个人想到一个比较笨的方法,简单粗暴地解决楼主的问题:用一个 const 表示数组的大小,常量定义在数组定义的后面,可以使用 sizeof ,因为这时编译器的知道数组的具体大小的,然后只需要在红色那句话下面再放两个数组大小常量的声明即可。

上代码:

extern BB_T bb0[], bb1[];
extern const int bb0_size, bb1_size;

AA_T aa0[] =
{
  { bb0, bb0_size }
  ,
  { bb1, bb1_size }
};
const int aa0_size = sizeof(aa0) / sizeof(AA_T);

AA_T aa1[] =
{
  { bb0, bb0_size }
  ,
  { bb1, bb1_size }
};
const int aa1_size = sizeof(aa1) / sizeof(AA_T);

BB_T bb0[] =
{
  { aa0, aa0_size }
  ,
  { aa1, aa1_size }
};
const int bb0_size = sizeof(bb0) / sizeof(BB_T);

BB_T bb1[] =
{
  { aa0, aa0_size }
  ,
  { aa1, aa1_size }
};
const int bb1_size = sizeof(bb1) / sizeof(BB_T);

这样写,同时兼顾了所谓的可维护性和楼主的需求。只是按照楼主目前的需求进行小改。但是说实话,个人觉得楼主这样写,代码并不易于维护。
2016-1-26 00:46
0
雪    币: 7048
活跃值: (3527)
能力值: ( LV12,RANK:340 )
在线值:
发帖
回帖
粉丝
7
感谢~方法不错.
2016-1-26 15:08
0
雪    币: 219
活跃值: (34)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
你的方法不错,但是你说的加上元素个数的方法是行不通的,我在VS2012环境中测试的。是不是我的理解有误?
2016-1-26 19:50
0
雪    币: 878
活跃值: (496)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
通过initializer-list规避大小声明本身是个很好的trick, 但用在LZ的想法上压根行不通, 至少现在的编译器条件下行不通, 就拿6L的代码说事, 你aa0实例化时bb0_size和bb1_size还是未知值, 即是说你之后还是需要显式赋值的.
2016-1-26 20:11
0
雪    币: 312
活跃值: (123)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
10
C++程序,从代码到机器码经过的是预编译(头文件的展开,处理大部分带有#的代码),编译,链接,生成可执行程序,由于在编译的过程中,涉及到语法解释,语义解释,而对其的解释是按照从上到下的顺序依次进行,当它扫描到你的AA_T aa0[] =
{
  { bb0, sizeof(bb0) / sizeof(BB_T) }
  ,
  { bb1, sizeof(bb1) / sizeof(BB_T) }
}; 时,bb0和bb1都没有出现过,同时也没有相关类型和变量的声明,所以会报错,而楼上的大牛们都是通过extends去将变量提前声明,导致其编译通过。
2016-2-1 14:26
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
如果仅仅是想要维护方便的话可以先设置一个大小,以后再用new分配呗
2016-2-4 12:10
0
游客
登录 | 注册 方可回帖
返回
//