#including <alsa/asoundlib.h> 和 <sys/time.h> 导致多重定义冲突
#including <alsa/asoundlib.h> and <sys/time.h> results in multiple definition conflict
这是要重现的最小 C 程序:
#include <alsa/asoundlib.h>
#include <sys/time.h>
int main( void )
{
}
这将使用 gcc -c -o timealsa.o timealsa.c
进行编译,但如果包含 -std=c99
开关,则会出现重定义错误:
In file included from /usr/include/sys/time.h:28:0,
from timealsa.c:3:
/usr/include/bits/time.h:30:8: error: redefinition of ‘struct timeval’
struct timeval
^
In file included from /usr/include/alsa/asoundlib.h:49:0,
from timealsa.c:2:
/usr/include/alsa/global.h:138:8: note: originally defined here
struct timeval {
^
如何在仍然使用 -std=c99
的情况下解决此冲突?
由于您的问题表明您正在使用 GLIBC 的 time.h
,因此有一种方法可以通过告诉它不要定义 timeval
来避免这种情况。首先包括 asoundlib.h
,然后定义 _STRUCT_TIMEVAL
。 asoundlib.h
中定义的那个将被使用。
#include <alsa/asoundlib.h>
#ifndef _STRUCT_TIMEVAL
# define _STRUCT_TIMEVAL
#endif
#include <sys/time.h>
int main( void )
{
}
对于 C99 及更高版本,您不能对同一结构进行重复定义。问题是 alsa/asoundlib.h
包含 alsa/global.h
其中包含此代码:
/* for timeval and timespec */
#include <time.h>
...
#ifdef __GLIBC__
#if !defined(_POSIX_C_SOURCE) && !defined(_POSIX_SOURCE)
struct timeval {
time_t tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#endif
#endif
所以 Michael Petch 的解决方案将不起作用 - 当您包含 alsa/asoundlib.h
时已经太晚了。正确的解决方案是定义 _POSIX_C_SOURCE
(_POSIX_SOURCE
已过时)。有关这些宏的更多信息 here and here.
例如,您可以尝试 -D_POSIX_C_SOURCE=200809L
。但是,如果你这样做,你会得到这样的错误:
/usr/include/arm-linux-gnueabihf/sys/time.h:110:20: error: field ‘it_interval’ has incomplete type
struct timeval it_interval;
^
/usr/include/arm-linux-gnueabihf/sys/time.h:112:20: error: field ‘it_value’ has incomplete type
struct timeval it_value;
^
/usr/include/arm-linux-gnueabihf/sys/time.h:138:61: error: array type has incomplete element type
extern int utimes (const char *__file, const struct timeval __tvp[2])
^
这完全是一堆旧 C 代码和疯狂的宏。我让它工作的唯一方法是放弃并使用 -std=gnu11
.
这是要重现的最小 C 程序:
#include <alsa/asoundlib.h>
#include <sys/time.h>
int main( void )
{
}
这将使用 gcc -c -o timealsa.o timealsa.c
进行编译,但如果包含 -std=c99
开关,则会出现重定义错误:
In file included from /usr/include/sys/time.h:28:0,
from timealsa.c:3:
/usr/include/bits/time.h:30:8: error: redefinition of ‘struct timeval’
struct timeval
^
In file included from /usr/include/alsa/asoundlib.h:49:0,
from timealsa.c:2:
/usr/include/alsa/global.h:138:8: note: originally defined here
struct timeval {
^
如何在仍然使用 -std=c99
的情况下解决此冲突?
由于您的问题表明您正在使用 GLIBC 的 time.h
,因此有一种方法可以通过告诉它不要定义 timeval
来避免这种情况。首先包括 asoundlib.h
,然后定义 _STRUCT_TIMEVAL
。 asoundlib.h
中定义的那个将被使用。
#include <alsa/asoundlib.h>
#ifndef _STRUCT_TIMEVAL
# define _STRUCT_TIMEVAL
#endif
#include <sys/time.h>
int main( void )
{
}
对于 C99 及更高版本,您不能对同一结构进行重复定义。问题是 alsa/asoundlib.h
包含 alsa/global.h
其中包含此代码:
/* for timeval and timespec */
#include <time.h>
...
#ifdef __GLIBC__
#if !defined(_POSIX_C_SOURCE) && !defined(_POSIX_SOURCE)
struct timeval {
time_t tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#endif
#endif
所以 Michael Petch 的解决方案将不起作用 - 当您包含 alsa/asoundlib.h
时已经太晚了。正确的解决方案是定义 _POSIX_C_SOURCE
(_POSIX_SOURCE
已过时)。有关这些宏的更多信息 here and here.
例如,您可以尝试 -D_POSIX_C_SOURCE=200809L
。但是,如果你这样做,你会得到这样的错误:
/usr/include/arm-linux-gnueabihf/sys/time.h:110:20: error: field ‘it_interval’ has incomplete type
struct timeval it_interval;
^
/usr/include/arm-linux-gnueabihf/sys/time.h:112:20: error: field ‘it_value’ has incomplete type
struct timeval it_value;
^
/usr/include/arm-linux-gnueabihf/sys/time.h:138:61: error: array type has incomplete element type
extern int utimes (const char *__file, const struct timeval __tvp[2])
^
这完全是一堆旧 C 代码和疯狂的宏。我让它工作的唯一方法是放弃并使用 -std=gnu11
.