简体   繁体   English

C嵌套结构上的g ++编译错误

[英]g++ compile error on C nested struct

I need the community's help with a compile error regarding C nested structs compiled with g++ . 关于g++g++编译的C嵌套结构的编译错误,我需要社区的帮助。

I have the following three files: 我有以下三个文件:

main.cpp (for completeness; this file is not required to reproduce the compile error): main.cpp (出于完整性考虑;不需要此文件来重现编译错误):

#include <iostream>
#include "ns.h"

int main( int argc, char* argv[] )
{
  someFunc();
  return 0;
}

ns.h : ns.h

#ifndef NS_H
#define NS_H

#ifdef __cplusplus
extern "C" {
#endif

void someFunc();

#ifdef __cplusplus
}
#endif

#endif // NS_H

ns.c : ns.c

#include "ns.h"

#ifdef __cplusplus
extern "C" {
#endif

#define MY_MAX (42)

typedef struct _outer
{
  int count;
  struct Inner
  {
    int count;
    void* cb;
    void* ctx [ MY_MAX ];
  } inner_[ MY_MAX ];
} Outer;

Outer g_outer[ 10 ];

#include "staticFuncs.h"

void someFunc()
{
  staticFunc();
}

#ifdef __cplusplus
}
#endif

staticFuncs.h : staticFuncs.h

#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

static void anotherStaticFunc()
{
  printf( "%s", __FUNCTION__ );

  struct Inner* ptr = NULL;
  ptr = &(g_outer[ 0 ].inner_[ 0 ]);
  (void)ptr;
}

static void staticFunc()
{
  printf( "%s", __FUNCTION__ );
  anotherStaticFunc();
}

#ifdef __cplusplus
}
#endif

The relevant compilation is as follows: 相关汇编如下:

>g++ --version
g++ (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


>g++ -g -c ns.c -o ns.o
In file included from ns.c:22:0:
staticFuncs.h: In function 'void anotherStaticFunc()':
staticFuncs.h:12:7: error: cannot convert '_outer::Inner*' to 'anotherStaticFunc()::Inner*' in assignment
   ptr = &(g_outer[ 0 ].inner_[ 0 ]);
       ^

What gives? 是什么赋予了?

I'm aware that in C , nested structs are not referred to by any scoping syntax, but are referred to as though they were not nested. 我知道在C ,任何范围分析语法都不会引用嵌套结构,而是将其称为未嵌套结构。 Ie, I'm pretty confident in that I can do struct Inner* ptr = NULL; 即,我对我可以执行struct Inner* ptr = NULL;充满信心struct Inner* ptr = NULL; as I did in staticFuncs.h . 就像我在staticFuncs.h所做的staticFuncs.h More important than my confidence, if I compile with cc instead of g++ , compilation goes through. 比我的信心更重要的是,如果我使用cc而不是g++编译,则编译将继续进行。

I've tried my damnedest to tell g++ that I'm compiling C , not C++ , code by throwing in extern "C" s everywhere, but it's still tripping over the scoping of Inner . 我已经尽我最大的努力告诉g++ ,我到处都是C而不是C++代码,方法是在各处都抛出extern "C" ,但是仍然超出了Inner的范围。

Can anyone please help identify why this compiler error arises and how I can work around it? 任何人都可以帮助确定为什么会出现此编译器错误以及如何解决该错误? I must use g++ to compile. 我必须使用g++进行编译。

The problem is unchanged if staticFuncs.h is staticFuncs.c instead. 如果将staticFuncs.c改为staticFuncs.h则问题不会改变。

The problem is unchanged if the static functions are not static. 如果静态函数不是静态的,则问题不会改变。

The problem is unchanged if the content of staticFuncs.h/c is embedded in ns.c instead of being #include ed. 如果将staticFuncs.h/c的内容嵌入ns.c而不是#include ed,则问题不会改变。

While gcc will compile code as C++ if it has certain suffixes, there is no way to compile C with g++. 如果gcc有某些后缀,它将以C ++的形式编译代码,但是无法用g ++编译C。
The only difference between gcc and g++ is that the latter always compiles C++, and that it links with the C++ libraries. gcc和g ++之间的唯一区别是,后者总是编译C ++,并且与C ++库链接。

The simplest fix is 最简单的解决方法是

struct Inner
{
    int count;
    void* cb;
    void* ctx [ MY_MAX ];
};

typedef struct _outer
{
  int count;
  struct Inner inner_[ MY_MAX ];
} Outer;

The error message from the compiler is very clear. 来自编译器的错误消息非常清楚。

The LHS of the assignment operator is declared as: 赋值运算符的LHS声明为:

struct Inner* ptr = NULL;

That line equivalent to: 该行等效于:

// Declare a struct in the function. This is different from _outer::Inner.
struct Inner;

// Declare the variable using the struct declared in the function.
struct Inner* ptr = NULL;

What you need to do is use _outer::Inner* as the type of ptr . 您需要做的是使用_outer::Inner*作为ptr的类型。

_outer::Inner* ptr = NULL;

I'm working on a project which compiles with g++ on default setup which is not ment to be changed (summarizing). 我正在一个项目,该项目可以在默认设置下使用g++进行编译,而无需更改(总结)。 And I dealed with the same problem while adding SQLite3 Amalgamation file, which is C code. 在添加SQLite3合并文件( C代码)时,我遇到了相同的问题。 In order to minimize the conflicts on Git when updating this file to merge official SQLite3 changes, you can also add the following trick, being an example of my case: 为了在更新此文件以合并官方SQLite3更改时最小化Git上的冲突,您还可以添加以下技巧,作为我的案例的示例:

#ifdef __cplusplus
#define _ht Hash::_ht
#endif // __cplusplus

Inmediately after the struct ( Hash ) which embeds the _ht struct, which is surely used in LHS later. 在嵌入_ht结构的结构( Hash )之后,此结构肯定会在稍后的LHS中使用。 Of course, you have to name intermediate embedded structs if they aren't. 当然,如果没有,则必须命名中间的嵌入式结构。 This is elegant, and especially helpful when using thirdparty code intended to support future updates with the least amount of problems, as of what was reasoned in the first paragraph. 这很优雅,并且在使用第三方代码来支持将来更新且问题最少的情况下尤其有用,就像在第一段中所阐述的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM