分享

_GNU_SOURCE和__USE_GNU的差别

 点点阅 2017-09-13

本文转载至:http:///2015/03/_gnu_source-vs-__use_gnu/#more-371

c-cpp.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <signal.h> //放这里就编译不过
/* get REG_RIP from ucontext.h */
#ifndef __USE_GNU
# define __USE_GNU
#endif
#include <ucontext.h>
int main(int argc, char* argv[])
{
printf("%dn", REG_R8);
return 0;
}

用gcc编译不过,用g++可以:
$ g++ c-cpp.c
$ gcc c-cpp.c
c-cpp.c: In function ‘main’:
c-cpp.c:12:17: error: ‘REG_R8’ undeclared (first use in this function)
c-cpp.c:12:17: note: each undeclared identifier is reported only once for each function it appears in

其预处理上有差别:
$ gcc siginfo.c -E >gcc.c
$ g++ siginfo.c -E >g++.c

在/usr/include/x86_64-linux-gnu/sys/ucontext.h 文件里,定义了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* Container for all general registers.  */
typedef greg_t gregset_t[NGREG];
#ifdef __USE_GNU
/* Number of each register in the `gregset_t' array.  */
enum
{
  REG_R8 = 0,
# define REG_R8 REG_R8
  REG_R9,
# define REG_R9 REG_R9
  ...
#endif
struct _libc_fpxreg

经过预处理,gcc.c显示为:

1
2
3
typedef greg_t gregset_t[23];
# 94 "/usr/include/x86_64-linux-gnu/sys/ucontext.h" 3 4
struct _libc_fpxreg

g++.c显示为:

1
2
3
4
5
6
7
8
typedef greg_t gregset_t[23];
enum
{
  REG_R8 = 0,
  REG_R9,
  ...
};
struct _libc_fpxreg

很明显,gcc版本的,没有enum,所有gcc编译不过。

换一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
/* get REG_RIP from ucontext.h */
#ifndef __USE_GNU
# define __USE_GNU
#endif
#include <signal.h> //放这里就可以
#include <ucontext.h>
int main(int argc, char* argv[])
{
printf("%dn", REG_R8);
return 0;
}

看下在gcc下,两者的预处理差别:
/usr/include/features.h 里面,首先会:

1
#undef __USE_GNU

然后根据_GNU_SOURCE来定义:

1
2
3
#ifdef _GNU_SOURCE
# define __USE_GNU 1
#endif

__USE_GNU 不是开放给用户用的,features.h里面会修改,但 _GNU_SOURCE 不会,它才是给用户用的
看features.h里的注释:
These are defined by the user (or the compiler) to specify the desired environment:
_GNU_SOURCE All of the above, plus GNU extensions.

These are defined by this file and are used by the header files to decide what to declare or define:
__USE_GNU Define GNU extensions.

修改方法,在代码最开始,添加:

1
2
3
#ifdef _GNU_SOURCE
# define _GNU_SOURCE
#endif

或者,直接在编译选项里定义。
而gcc和g++的默认定义也有区别,因为g++默认定义了_GNU_SOURCE,所以g++可以编译过而gcc编译不过。

在这里 http:///questions/5679267/how-to-resolve-reg-eip-undeclared-first-use-in-this-function-error-on-linux-3 也搜索到答案,但是之前没有太留意。
I believe you should either have #define _GNU_SOURCE as the first line of your source file, or better put -D_GNU_SOURCE in your CFLAGS (on the command line). Then make sure you include and .


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多