【嵌入式开发基础】gcc -D参数的坑!!

前言

在C/C++开发中,我们常常会在头文件中通过#define 进行宏的定义, 在代码的预编译阶段编译器会将宏进行替换.
然而在有些场景下需要在Makefile中实现类似在头文件通过#define进行宏定义的效果, 那么该怎么写呢?

好在gcc/g++ 等编译器提供了-D这一参数进行同等的操作.

首先可以不通过在Linux下的终端执行 man gcc or man g++命令,查看对于-D参数的说明,

test man gcc
GCC(1)                                                                                            GNU                                                                                           GCC(1)

NAME
       gcc - GNU project C and C++ compiler

SYNOPSIS
       gcc [-c|-S|-E] [-std=standard]
           [-g] [-pg] [-Olevel]
           [-Wwarn...] [-Wpedantic]
           [-Idir...] [-Ldir...]
           [-Dmacro[=defn]...] [-Umacro]
           [-foption...] [-mmachine-option...]
           [-o outfile] [@file] infile...

       Only the most useful options are listed here; see below for the remainder.  g++ accepts mostly the same options as gcc.
...

对于-D参数的描述如下(gcc为例子):

-D name
           Predefine name as a macro, with definition 1.

-D name=definition
           The contents of definition are tokenized and processed as if they appeared during translation phase three in a #define directive.  In particular, the definition is truncated by embedded
           newline characters.

           If you are invoking the preprocessor from a shell or shell-like program you may need to use the shell's quoting syntax to protect characters such as spaces that have a meaning in the
           shell syntax.

           If you wish to define a function-like macro on the command line, write its argument list with surrounding parentheses before the equals sign (if any).  Parentheses are meaningful to most
           shells, so you should quote the option.  With sh and csh, -D'name(args...)=definition' works.

           -D and -U options are processed in the order they are given on the command line.  All -imacros file and -include file options are processed after all -D and -U options.

可以看出,主要是两个场景:

  • -D name
  • -D name=definition
示例演示 -D name

Makefile 文件的实现,

all:
	gcc -D TEST  test.c

源文件test.c,

#include <stdio.h>

int main(int argc, char **argv)
{
#ifdef TEST
    printf("Hi T \r\n");	
#endif    
    return 0;
}

在完成Makefile和test.c 的编写后,test.c 和 Makefile的所在目录下执行make命令,生成可执行程序a.out

test ls
Makefile  test.c
➜  test make
gcc -D TEST  test.c

然后在终端运行./a.out

test ./a.out 
Hi T 
➜  test 

可以看到打印了字符串"Hi T"
而当去掉Makefile中的-D TEST后,编译生成的a.out,运行不在打印字符串"Hi T"

示例演示 -D name=definition

当definition是数字时,
Makefile 文件的实现,

all:
	gcc -D TEST=12  test.c

源文件test.c,

#include <stdio.h>

int main(int argc, char **argv)
{
#ifdef TEST
    printf("TEST's value is %d \r\n", TEST);	
#endif 	    
    return 0;
}

在完成Makefile和test.c 的编写后,test.c 和 Makefile的所在目录下执行make命令,生成可执行程序a.out

test ls
Makefile  test.c
➜  test make
gcc -D TEST  test.c

然后在终端运行./a.out

test ./a.out 
TEST's value is 12test 

当definition是字符串时,
Makefile 文件的实现,

all:
	gcc -D TEST=\""hello"\"   test.c

源文件test.c,

#include <stdio.h>

int main(int argc, char **argv)
{
#ifdef TEST
    printf("TEST's value is %s \r\n", TEST);	
#endif 	    
    return 0;
}

在完成Makefile和test.c 的编写后,test.c 和 Makefile的所在目录下执行make命令,生成可执行程序a.out

test ls
Makefile  test.c
➜  test make
gcc -D TEST  test.c

然后在终端运行./a.out

test ./a.out 
TEST's value is hello
➜  test 

可执行程序打印了TEST值为hello.

总结

在使用gcc or g++的-D参数时需要注意的是在使用-D name=definition传递字符串时需要特别注意.
例如我需要传递的字符串是"hello",那么在上述例子中我们第一感觉的写法是:

all:
	gcc -D TEST="hello"  test.c 

然后在编译生成可执行程序时出现了报错,

test make
gcc -D TEST="hello"  test.c 
test.c: In function ‘main’:
<command-line>:0:6: error: ‘hello’ undeclared (first use in this function); did you mean ‘ftello’?
test.c:7:39: note: in expansion of macro ‘TEST’
     printf("TEST's value is %s \r\n", TEST);
                                       ^~~~
<command-line>:0:6: note: each undeclared identifier is reported only once for each function it appears in
test.c:7:39: note: in expansion of macro ‘TEST’
     printf("TEST's value is %s \r\n", TEST);
                                       ^~~~
Makefile:4: recipe for target 'all' failed

正确的写法是需要在"hello"字符串换加上" 转义,修正如下,

all:
	gcc -D TEST=\""hello"\"  test.c
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值