Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何避免GNU Make和shell在定义变量时展开逗号和撇号_C_Makefile - Fatal编程技术网

C 如何避免GNU Make和shell在定义变量时展开逗号和撇号

C 如何避免GNU Make和shell在定义变量时展开逗号和撇号,c,makefile,C,Makefile,我的makefile中有一个名为SELF的变量,我希望通过-D选项将该变量传递给GCC编译器以定义宏。这个宏在[0-9a-zA-Z]中只能有一个字符,但这本身就是另一个问题,我不会在这里讨论。 我很难找到一个解决方法来避免gnumake和shell删除定义中的逗号。 如何定义它的示例如下: #包括 #定义str(x)#x #定义xstr(x)str(x) #ifndef自我 #定义自我“0” #恩迪夫 #pragma消息(“SELF is:”xstr(SELF)) 内部主(空){ 返回0; }

我的makefile中有一个名为SELF的变量,我希望通过-D选项将该变量传递给GCC编译器以定义宏。这个宏在[0-9a-zA-Z]中只能有一个字符,但这本身就是另一个问题,我不会在这里讨论。 我很难找到一个解决方法来避免gnumake和shell删除定义中的逗号。 如何定义它的示例如下:

#包括
#定义str(x)#x
#定义xstr(x)str(x)
#ifndef自我
#定义自我“0”
#恩迪夫
#pragma消息(“SELF is:”xstr(SELF))
内部主(空){
返回0;
}
生成文件如下所示:

make SELF=0
ifdef SELF
DSELF = -DSELF="'$(SELF)'"
endif
CFLAGS = -std=c99 $(DSELF)
CC=gcc
WFLAGS=-Wall-Wextra
自我定义
DSELF=-DSELF=$(SELF)
恩迪夫
CFLAGS=-std=c99$(DSELF)
全部:清洁测试
%:%
.假冒:干净
清洁:
-rm-v试验
如果使用
make
执行makefile,将出现一个注释,该注释将标记SELF的定义:

test.c:9:9:note:'#pragma消息:SELF是:“0”
9 |#pragma消息(“SELF is:”xstr(SELF))
|         ^~~~~~~
另一方面,执行
make SELF='0'
将销毁撇号,正如您在GNU make的详细输出中所看到的:

gcc -std=c99 -DSELF=0    test.c   -o test
如果尝试用引号括住撇号,如
make SELF=“'0'”
,则定义将传递给GCC,但即使是shell也会删除撇号,因为#pragma消息仍将显示
0
。但是如果您直接执行gcc-std=c99-DSELF=“'0'”test.c-o test,定义将成功完成:

test.c:9:9:note:'#pragma消息:SELF是:“0”
9 |#pragma消息(“SELF is:”xstr(SELF))
|         ^~~~~~~

你怎样才能避免这一切的发生?这是否意味着您不能定义相同种类的字符串?

您的问题非常令人困惑,因为首先您讨论的是逗号,然后您开始讨论完全不同的撇号

在计算机ese中,我们通常将
字符称为“单引号”,而不是撇号,后者通常指完整字符集中的不同字符

无论如何,既然shell和逗号都不重要,我只能假设你在整个问题中都是单引号

答案是,make根本不在乎引用,也不会删除它们。但是,shell非常关心它们,并且会为您删除它们:重要的是要理解shell在启动程序之前删除引号,因此程序甚至没有机会知道引号是否存在。以你的第一个例子:

make SELF='0'
在这里,shell将在调用make之前删除引号。Make无法知道是运行了
Make SELF=0
还是
Make SELF=0'
,因为在调用Make时,引号已被删除

然后,当make运行shell命令启动编译器时,该shell命令还将在调用编译器之前删除引号。因此,您有这样一个命令来运行:

gcc -std=c99 -DSELF='0'    test.c   -o test
shell删除引号,编译器将获得参数
-DSELF=0

你如何防范这种情况?你需要避开引用。在您的情况下,您希望保留单引号,因此需要在其周围使用反斜杠或双引号(如您所发现的)

现在还不清楚您想要做什么,但假设您希望能够像这样运行make:

make SELF=0
ifdef SELF
DSELF = -DSELF="'$(SELF)'"
endif
CFLAGS = -std=c99 $(DSELF)
然后需要添加两个单引号,并在makefile中转义它们。 您可以这样将它们放入makefile中:

make SELF=0
ifdef SELF
DSELF = -DSELF="'$(SELF)'"
endif
CFLAGS = -std=c99 $(DSELF)

现在将使用
-DSELF=“'0'”
调用编译器,然后shell将删除外部引号,并使用
-DSELF='0'
调用您的程序,这正是您想要的。

我可能已经回答了自己的问题。如果将:DSELF=-DSELF=$(SELF)替换为:DSELF=-DSELF=\''$(SELF)\',则为“make SELF=”编写的任何内容都将使用撇号进行定义,但如果一开始不使用撇号或引号,则不会得到尊重。这非常快。谢谢你的回答,很抱歉弄糟了程序员的词汇,因为我不是以英语为母语的人。我的意思是在整个问题中谈论“单引号”和“双引号”。我也忘记了转义字符的概念,直到几秒钟后,我按下提交的问题。我相信这将是一个重复的问题在其他地方。