2017-02-17 6 views
1

내가 헤더 파일에이 라인이 있습니다육각 컴파일러`형식 정의 구조체 MYSTRUCT * mystruct`

typedef struct mystruct *mystruct; 

그리고 .c 파일에서 해당 구조체 정의를. 꽤 표준적인 관행.

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

이 육각 3.0 SDK에서 육각 Tools 컴파일러 (7.2.12)을 사용하고 있습니다 :

나는이 컴파일 오류를 얻고있다. 공식적으로 QuIC LLVM Hexagon Clang 버전 7.2.12입니다. 금어초 비행을위한 건물. 이것은 내가 아는 한 작동해야합니다. 그것은 x86_64-pc-linux-gnu에 대한 우분투 clang 버전 3.5.0-4ubuntu2 ~ trusty2 (LLVM 3.5.0 기반)와 함께 작동합니다.

무엇이 잘못 되었나요? 이 유형의 typedef은 컴파일러에서 구현되지 않은 C의 새로운 기능입니까, 아니면 이러한 일반적인 컴파일러 차이점입니까?

편집 : 실제로 struct는 .cpp 파일이 아니라 .c 파일에 정의되어 있습니다. 문제가있는 typedef 구문을 사용하여 헤더 파일의 맨 위뿐만 아니라 우분투 clang으로 컴파일을 보여주는 Makefilemake 출력을 추가했습니다. 테스트가 끝나고 105 개의 테스트가 모두 통과합니다.

편집 2 :이 작동하는 경우 작동하지 않는 경우 조나단 룰러의 대답을 참조하십시오.

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 [email protected] 

ringbuf-gcov.o: ringbuf.c ringbuf.h 
    gcc --coverage -c $< -o [email protected] 

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 [email protected] 

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 [email protected] 
    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 : 이것은 실제로 단지 육각 그 소리 컴파일러와 함께 잘 작동합니다. 문제가되는 것은이 모듈이 존재하는 더 큰 프로그램의 컴파일 과정입니다. 나는이 코드를 C++로 컴파일하려고 시도하고 있다고 생각한다.

+0

'mystruct'라는 이름을 다시 사용하고 있습니다. 왜 이것이 효과가 있다고 생각하니? –

+2

이 코드는 C++에서는 유효하지 않습니다. 질문에 ".cpp 파일"이라고 말합니다. 하지만 C와 C++는 다른 언어입니다. 어떤 언어를 사용하고 있는지 결정하십시오. –

+2

또한 struct 태그에 동일한 이름을 사용하고 해당 유형에 대한 포인터를 사용하는 것은 C 언어의 표준 사례조차하지 않습니다. 사람들이 포인터 타입 정의 (일반적으로 권장하지 않음)를 사용할 때, 그들은 pointer typedef에 대해 일종의 헝가리어 접두사 (예 :'pmystruct')를 사용하는 경향이 있습니다. –

답변

2

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에서 컴파일 ++, 심지어 엄격한 경고에서 . 이에 해당하는 C main()을 사용하면 <stdio.h>을 사용할 수 있습니다.

+0

.cpp가 아닌 .cpp에서 작동합니다. – errolflynn

+1

Answer, typedef에 포인터가 없으므로 코드는 C와 C++에서 잘 작동합니다. 포인터를'typedef'에 포함 시키려고하면 C++에서는 작동하지 않지만 (struct, union, enum) 태그 네임 스페이스가 사용되기 때문에 C에서 혼동 스럽긴하지만 작동 할 것입니다. 'struct mystruct'는 typedef 이름 (및 변수 이름)에 사용되는 '일반 식별자'네임 스페이스와 별개입니다. –

+0

그것은 나를 위해 우분투 clang으로 컴파일됩니다. 나는'Makefile'과 make 출력을 게시했다. – errolflynn