【问题标题】:Hexagon compiler having trouble with `typedef struct mystruct *mystruct` [duplicate]Hexagon 编译器在使用 `typedef struct mystruct *mystruct` 时遇到问题 [重复]
【发布时间】:2017-07-06 10:12:21
【问题描述】:

我在头文件中有这一行:

typedef struct mystruct *mystruct;

以及 .c 文件中的相应结构定义。相当标准的做法。

我收到此编译错误:

fatal error: typedef redefinition with different types ('struct mystruct *' vs mystruct')

这是使用来自 Hexagon 3.0 SDK 的 Hexagon Tools Compiler (7.2.12)。它的正式版本是 QuIC LLVM Hexagon Clang 版本 7.2.12。为 Snapdragon Flight 建造。据我所知,这应该有效。它适用于 x86_64-pc-linux-gnu 的 Ubuntu clang 版本 3.5.0-4ubuntu2~trusty2(基于 LLVM 3.5.0)。

这里有什么问题?这种类型的typedef 是 C 的一个新特性,没有在编译器中实现,还是像这样的编译器差异很常见?

编辑:实际上 struct 是在 .c 而不是 .cpp 文件中定义的。添加了 Makefilemake 输出显示使用 Ubuntu clang 进行编译,以及带有麻烦的 typedef 语句的头文件顶部。最后运行一个测试,所有 105 个测试都通过了。

Edit2:请参阅 Jonathan Leffler 的回答,了解适用与不适用的情况。

ringbuf.h:

#include <stddef.h>
#include <sys/types.h>

#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))

typedef struct ringbuf_t *ringbuf_t;

生成文件:

CC=clang
CFLAGS=-O0 -g -Wall -Wpointer-arith -ftrapv -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error

# or, for gcc...
#CC=gcc
#CFLAGS=-O0 -g -Wall

LD=$(CC)
LDFLAGS=-g

test:   ringbuf-test
    ./ringbuf-test

coverage: ringbuf-test-gcov
      ./ringbuf-test-gcov
      gcov -o ringbuf-gcov.o ringbuf.c

valgrind: ringbuf-test
      valgrind ./ringbuf-test

help:
    @echo "Targets:"
    @echo
    @echo "test  - build and run ringbuf unit tests."
    @echo "coverage - use gcov to check test coverage of ringbuf.c."
    @echo "valgrind - use valgrind to check for memory leaks."
    @echo "clean - remove all targets."
    @echo "help  - this message."

ringbuf-test-gcov: ringbuf-test-gcov.o ringbuf-gcov.o
    gcc -o ringbuf-test-gcov --coverage $^

ringbuf-test-gcov.o: ringbuf-test.c ringbuf.h
    gcc -c $< -o $@

ringbuf-gcov.o: ringbuf.c ringbuf.h
    gcc --coverage -c $< -o $@

ringbuf-test: ringbuf-test.o libringbuf.so
    $(LD) -o ringbuf-test $(LDFLAGS) $^ -L$(MY_LIBS_PATH) -lringbuf

ringbuf-test.o: ringbuf-test.c ringbuf.h
    $(CC) $(CFLAGS) -c $< -o $@ 

libringbuf.so: ringbuf.o
    $(CC) -shared -o libringbuf.so ringbuf.o
    cp ./libringbuf.so $(MY_LIBS_PATH)/

ringbuf.o: ringbuf.c ringbuf.h
    $(CC) $(CFLAGS) -fPIC -c $< -o $@
    cp ./ringbuf.h $(MY_INCLUDES_PATH)/

clean:
    rm -f ringbuf-test ringbuf-test-gcov *.o *.so *.gcov *.gcda *.gcno

.PHONY: clean

make 输出:

clang -O0 -g -Wall -Wpointer-arith -ftrapv -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -c ringbuf-test.c -o ringbuf-test.o 
clang -O0 -g -Wall -Wpointer-arith -ftrapv -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -fPIC -c ringbuf.c -o ringbuf.o
cp ./ringbuf.h /home/eric/Includes/
clang -shared -o libringbuf.so ringbuf.o
cp ./libringbuf.so /home/eric/Libs/
clang -o ringbuf-test -g ringbuf-test.o libringbuf.so -L/home/eric/Libs -lringbuf
./ringbuf-test

Edit3:这实际上只适用于 Hexagon-clang 编译器。存在问题的是该模块存在于较大程序的编译过程。我认为它正在尝试将此代码编译为 C++。

【问题讨论】:

  • 您正在重用名称mystruct。您为什么希望这会起作用?
  • 此代码在 C++ 中是非法的。您在问题中说“.cpp 文件”。但是您将问题标记为 C。C 和 C++ 是不同的语言。请确定您使用的语言...
  • 此外,在 C 中,为结构标记和指向该类型的指针使用相同的名称甚至不是标准做法。当人们确实使用指针类型定义(通常不鼓励)时,他们倾向于对指针类型定义使用某种匈牙利语前缀(例如pmystruct)。
  • 我的错误,已更正为 .c 文件。我没有编写此代码以供参考。从https://github.com/dhess/c-ringbuf 得到它。如有必要,更改 struct typedef 不会太难。但是,这绝对适用于另一个编译器。
  • 查看 Jonathan Leffler 的评论,认为这适用于 C 中 (struct, union, enum) 标记周围的命名空间。尽管不适用于 Hexagon clang 编译器

标签: c llvm-clang qualcomm hexagon-dsp


【解决方案1】:

如果你不尝试Use typedef for a pointer type,你的代码在 C 和 C++ 中会很好。

标头(例如hdr.h)可以/应该包含:

typedef struct mystruct mystruct;

来源(例如hdr.cpp)可能包含:

#include "hdr.h"

struct mystruct
{
    const char *a;
    int   b;
    int   c;
};

#include <iostream>

int main()
{
    mystruct *ap = new mystruct;
    ap->a = "collywobbles";
    ap->b = 1;
    ap->c = 2;
    std::cout << "a: " << ap->a << ", b = " << ap->b << ", c = " << ap->c << "\n";
    return 0;
}

这将在 C++ 中编译,即使在严格的警告下也是如此。使用 &lt;stdio.h&gt; 的等效 C main() 将在 C 中工作。

【讨论】:

  • 为什么这在 .c 中有效,但在 .cpp 中无效
  • 如答案所示,typedef 中没有指针,代码在 C 和 C++ 中运行良好。如果您尝试将指针包含在typedef 中,它在 C++ 中将不起作用,但是(想想看)它会在 C 中起作用,尽管令人困惑,因为使用了 (struct, union, enum) 标记命名空间对于 struct mystruct 与用于 typedef 名称(和变量名称)的“普通标识符”命名空间是分开的。
  • 如果您的意思是,您能否使用 typedef 将 C 库与指向程序的指针链接起来,否则使用 C++,答案是“是”,因为 C 函数将被声明为 extern "C",以便它们可以从 C++ 调用,并且省略了类型安全的链接信息,否则会搞砸。
  • 我无法测试,无法访问 clang 的六边形(或五边形,或……)版本。我会仔细检查一下 Mac clang 做了什么。
  • 为什么不更新答案而不仅仅是更新 cmets?这个答案具有误导性:这样做是否是一个好主意不是问题的主题(就此而言,这也意味着这绝对不是重复,尽管它可能是“印刷或其他“接近的候选人”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-08
  • 2011-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多