Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 错误:字段的类型不完整_C_Struct - Fatal编程技术网

C 错误:字段的类型不完整

C 错误:字段的类型不完整,c,struct,C,Struct,我正在尝试将库移植到Mac OS X。编译器报告了一个不完整的类型错误。特别是:字段的类型“header\u t[]不完整。然而,当我查看源代码时,header\u t正好在packet\u state\u t之前定义,其中packet\u state\u t引用header\u t。因此,不应该存在任何前向引用错误,因为在数据包状态中引用报头时,报头被明确定义。发生错误的行在下面用错误标记。如何解决 typedef struct header_t { uint8_t hdr_id;

我正在尝试将库移植到Mac OS X。编译器报告了一个不完整的类型错误。特别是:字段的类型“header\u t[]不完整。然而,当我查看源代码时,header\u t正好在packet\u state\u t之前定义,其中packet\u state\u t引用header\u t。因此,不应该存在任何前向引用错误,因为在数据包状态中引用报头时,报头被明确定义。发生错误的行在下面用错误标记。如何解决

 typedef struct header_t {
    uint8_t  hdr_id;         // header ID

    uint8_t  hdr_prefix;     // length of the prefix (preamble) before the header
    uint8_t  hdr_gap;        // length of the gap between header and payload
    uint16_t  hdr_flags;      // flags for this header
    uint16_t hdr_postfix;    // length of the postfix (trailer) after the payload
    uint32_t hdr_offset;     // offset into the packet_t->data buffer
    uint32_t hdr_length;     // length of the header in packet_t->data buffer
    uint32_t hdr_payload;    // length of the payload

    uint8_t   hdr_subcount;  // number of sub-headers
    header_t  *hdr_subheader;   // Index of the first subheader in packet_t

    jobject  hdr_analysis;   // Java JAnalysis based object if not null
} header_t;

typedef struct packet_state_t {
    flow_key_t pkt_flow_key; // Flow key calculated for this packet, must be first
    uint8_t pkt_flags;       // flags for this packet
    jobject pkt_analysis;    // Java JAnalysis based object if not null
    uint64_t pkt_frame_num;  // Packet's frame number assigned by scanner
    uint64_t pkt_header_map; // bit map of presence of headers

    uint32_t pkt_wirelen;    // Original packet size
    uint32_t pkt_buflen;     // Captured length

    int8_t pkt_header_count; // total number of main headers found
    header_t pkt_headers[];  // One per header + 1 more for payload ERROR HERE!!!

    int8_t pkt_subheader_count;  // total number of sub headers found
    header_t pkt_subheaders[];  // One per header + 1 more for payload
} packet_state_t;

在结构头的定义中

改变

header_t  *hdr_subheader;   // Index of the first subheader in packet_t


类型
header\u t
很好,但编译器实际上是在抱怨类型
header\u t[]
,即“长度不确定的
header\u t
数组”,它的类型不完整,因为编译器不知道它有多大(不可能)

C99(但不是C89)在结构中支持所谓的灵活数组成员,这正是结构中的灵活数组成员,但仅在结构的末尾:

struct X {
  // any member declarations
  ...
  AnyType lastMemberArray[];  // This must be the LAST member
};
这是允许的,但它使您声明的结构也成为不完整的类型,因为编译器也不知道它有多大。使用它的唯一方法是动态分配所需大小的内存或强制转换已分配的内存块。例如:

// Allocate an X instance with space for 3 members in lastMemberArray:
X *x = malloc(sizeof(X) + 3 * sizeof(AnyType));
// Can now use x->lastMemberArray[0] through x->lastMemberArray[2]
...

// Alternatively:
char buffer[sizeof(X) + 3 * sizeof(AnyType)];
X *x = (X *)buffer;
// Same as above
为什么灵活数组成员必须在结构中排在最后?想象一下,如果其他成员也来了。编译器如何生成代码来访问这些成员

// If this were allowed:
struct X {
  AnyType flexibleArray[];
  int memberAfter;
};

void doSomething(X *x) {
  // How does the compiler generate code for this?  It doesn't know what offset
  // memberAfter is from the start of the object, because the array doesn't
  // have a known size
  printf("memberAfter = %d\n", x->memberAfter);
}
因此,一个结构不能有多个灵活的数组成员,因为显然其中一个不会是最后一个结构成员,因此不允许定义

无论您编写的是什么库代码,它都不可能一开始就使用两个灵活的数组成员,也不可能在任何平台上编译。我建议您调查原始代码以了解它的功能;如果它使用标准ISO C特性,而不依赖于任何特定于平台或特定于实现的行为或扩展,那么移植它应该不会有问题

在看不到原始代码的情况下,我建议您从使用内联灵活数组成员切换到使用指针的动态分配数组,至少对于第一个数组(为了一致性,可能还有第二个):


编辑

我下载了jnetpcap代码,并在Linux上编译它,以查看发生了什么。令我惊讶的是,它被编译了。调用的编译器命令为:

gcc -c -fPIC -DLIBPCAP_VERSION=0x1532 -I/tmp/jnetpcap/build/include -I/tmp/jnetpcap/src/c -I/usr/lib/jvm/default-java/include -I/usr/lib/jvm/default-java/include/linux /tmp/jnetpcap/src/c/jnetpcap.cpp /tmp/jnetpcap/src/c/packet_flow.cpp /tmp/jnetpcap/src/c/packet_jheader.cpp /tmp/jnetpcap/src/c/jnetpcap_pcap_header.cpp /tmp/jnetpcap/src/c/nio_jbuffer.cpp /tmp/jnetpcap/src/c/winpcap_stat_ex.cpp /tmp/jnetpcap/src/c/winpcap_send_queue.cpp /tmp/jnetpcap/src/c/winpcap_ext.cpp /tmp/jnetpcap/src/c/util_debug.cpp /tmp/jnetpcap/src/c/util_crc16.c /tmp/jnetpcap/src/c/jnetpcap_ids.cpp /tmp/jnetpcap/src/c/jnetpcap_dumper.cpp /tmp/jnetpcap/src/c/jnetpcap_utils.cpp /tmp/jnetpcap/src/c/util_in_cksum.cpp /tmp/jnetpcap/src/c/jnetpcap_beta.cpp /tmp/jnetpcap/src/c/nio_jmemory.cpp /tmp/jnetpcap/src/c/util_crc32.c /tmp/jnetpcap/src/c/packet_jsmall_scanner.cpp /tmp/jnetpcap/src/c/mac_addr_sys.c /tmp/jnetpcap/src/c/packet_protocol.cpp /tmp/jnetpcap/src/c/nio_jnumber.cpp /tmp/jnetpcap/src/c/packet_jheader_scanner.cpp /tmp/jnetpcap/src/c/library.cpp /tmp/jnetpcap/src/c/packet_jscan.cpp /tmp/jnetpcap/src/c/jnetpcap_pcap100.cpp /tmp/jnetpcap/src/c/mac_addr_dlpi.c /tmp/jnetpcap/src/c/util_checksum.cpp /tmp/jnetpcap/src/c/packet_jpacket.cpp /tmp/jnetpcap/src/c/winpcap_ids.cpp /tmp/jnetpcap/src/c/jnetpcap_bpf.cpp
<> P>这是这里的第一件事,这是C++,而不是C.C++不支持灵活的数组成员,尽管有些编译器支持它们作为扩展。C++03§9.2/8规定:

[…]当阵列用作非静态构件类型时,应规定所有尺寸

C++11§9.2/9规定:

9非静态(9.4)数据成员的类型不得不完整。[……]

当我在g++4.8.2中以更高的警告级别(
-Wall-Wextra pedantic
)编译此代码时,它会发出如下警告:

In file included from /tmp/jnetpcap/src/c/packet_jscan.cpp:28:0:
/tmp/jnetpcap/src/c/packet_jscanner.h:287:23: warning: ISO C++ forbids zero-size array ‘pkt_headers’ [-Wpedantic]
  header_t pkt_headers[];  // One per header + 1 more for payload
                       ^
/tmp/jnetpcap/src/c/packet_jscanner.h:290:26: warning: ISO C++ forbids zero-size array ‘pkt_subheaders’ [-Wpedantic]
  header_t pkt_subheaders[];  // One per header + 1 more for payload
所以,G++正在做的事情(与C++标准相反)是将未指定大小的数组转换为0的数组。第一个(
pkt_headers
)的工作原理与C99中的灵活数组成员完全相同,因为如果您分配了适当的内存量,则可以访问该数组的成员,通常可以访问到最大大小。但如果在此之后访问任何成员(特别是
pkt_子标题
pkt_子标题
),编译器将生成代码,就像
pkt_标题
大小为0一样,即如果结构与此等效:

typedef struct packet_state_t {
    flow_key_t pkt_flow_key; // Flow key calculated for this packet, must be first
    uint8_t pkt_flags;       // flags for this packet
    jobject pkt_analysis;    // Java JAnalysis based object if not null
    uint64_t pkt_frame_num;  // Packet's frame number assigned by scanner
    uint64_t pkt_header_map; // bit map of presence of headers

    uint32_t pkt_wirelen;    // Original packet size
    uint32_t pkt_buflen;     // Captured length

    int8_t pkt_header_count; // total number of main headers found
    // NOTHING HERE (array of size 0)

    int8_t pkt_subheader_count;  // total number of sub headers found
    header_t pkt_subheaders[];  // One per header + 1 more for payload
} packet_state_t;
这将导致访问
pkt\u子标题\u count
(也可能访问
pkt\u子标题
)访问与
pkt\u标题[0]
完全相同的内存

为什么这件事能顺利进行因为此项目中的代码从未访问过
pkt\u子标题\u计数
pkt\u子标题
任何地方。
如果访问了,则除非非常幸运,否则由于上述原因,代码将无法工作。它不是有效的C++,它恰好被编译器接受。
解决方案?只需从结构声明中删除
pkt_子标题
pkt_子标题
。它们不在代码中任何地方使用,并且移除它们允许<代码> pktHyth[]]/C>作为结构的最后成员,所以它是一个有效的灵活数组成员,它是有效的C99或C++中的非标准编译器扩展。

我认为不存在合法的空数组字段(<代码>头文件pktl头[]/COD>)这不是结构的结尾。感谢您的输入,但不是错误所在。错误出现在typedef结构数据包_state_t{…header_t pkt_headers[];}中。。无论如何,我试过你的建议,没什么区别。这不重要。typedef和struct标记位于不同的作用域中。。谢谢你的贡献。然而,这段代码显然在Linux上编译得很好。它不能在Mac OS X上编译。难道没有编译器开关或其他东西可以让它工作吗?如果我修改了你提议的代码,它会影响程序的其他部分吗。如果可能的话,我想尽量避免重写大部分代码。切换到指针似乎已经消除了这个错误。@jamie:它应该根本无法在Linux上编译。您能提供一个例子,以及确切的编译器版本和使用的编译器选项吗?我正在尝试编译Jnetpcap的1.4主干。这个问题也发生在Jnetpcap的1.3.1上。Linux和Windows都是受支持的操作系统,而不是Mac OS X。这很有趣,因为根本没有编译的方法。您知道用于编译的编译器、编译器版本和编译器选项是什么吗?那代码是编译的吗?C99在§6.7.2.1/2中对此非常清楚。
In file included from /tmp/jnetpcap/src/c/packet_jscan.cpp:28:0:
/tmp/jnetpcap/src/c/packet_jscanner.h:287:23: warning: ISO C++ forbids zero-size array ‘pkt_headers’ [-Wpedantic]
  header_t pkt_headers[];  // One per header + 1 more for payload
                       ^
/tmp/jnetpcap/src/c/packet_jscanner.h:290:26: warning: ISO C++ forbids zero-size array ‘pkt_subheaders’ [-Wpedantic]
  header_t pkt_subheaders[];  // One per header + 1 more for payload
typedef struct packet_state_t {
    flow_key_t pkt_flow_key; // Flow key calculated for this packet, must be first
    uint8_t pkt_flags;       // flags for this packet
    jobject pkt_analysis;    // Java JAnalysis based object if not null
    uint64_t pkt_frame_num;  // Packet's frame number assigned by scanner
    uint64_t pkt_header_map; // bit map of presence of headers

    uint32_t pkt_wirelen;    // Original packet size
    uint32_t pkt_buflen;     // Captured length

    int8_t pkt_header_count; // total number of main headers found
    // NOTHING HERE (array of size 0)

    int8_t pkt_subheader_count;  // total number of sub headers found
    header_t pkt_subheaders[];  // One per header + 1 more for payload
} packet_state_t;