В командной строке gcc я хочу определить строку, например -Dname=Mary
, затем в исходном коде, который я хочу printf("%s", name);
напечатать Mary
.
Как я мог это сделать?
В командной строке gcc я хочу определить строку, например -Dname=Mary
, затем в исходном коде, который я хочу printf("%s", name);
напечатать Mary
.
Как я мог это сделать?
Ответы:
Два варианта. Во-первых, избегайте кавычек, чтобы оболочка их не съела:
gcc -Dname=\"Mary\"
Или, если вы действительно хотите -Dname = Mary, вы можете преобразовать его в строку, хотя это немного взломано.
#include <stdio.h>
#define STRINGIZE(x) #x
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
int main(int argc, char *argv[])
{
printf("%s", STRINGIZE_VALUE_OF(name));
}
Обратите внимание, что STRINGIZE_VALUE_OF с радостью выполнит оценку вплоть до окончательного определения макроса.
Самый переносимый способ, который я нашел до сих пор, - это использовать \"Mary\"
- он будет работать не только с gcc, но и с любым другим компилятором C. Например, если вы попытаетесь использовать /Dname='"Mary"'
компилятор Microsoft, он остановится с ошибкой, но /Dname=\"Mary\"
будет работать.
В Ubuntu я использовал псевдоним, определяющий CFLAGS, а CFLAGS включал макрос, который определяет строку, а затем я использую CFLAGS в Makefile. Мне пришлось избегать символов двойных кавычек, а также символов \. Выглядело это примерно так:
CFLAGS='" -DMYPATH=\\\"/home/root\\\" "'
1) DEFINES=-DLOGPATH=\"./logfile\" CFLAGS = -v $(DEFINES)....
2) DEFINES=-DLOGPATH=\\\"./logfile\\\" CFLAGS = "-v $(DEFINES)...."
использование параметра компилятора -v полезно, чтобы увидеть, что делает препроцессор.
Вот простой пример:
#include <stdio.h>
#define A B+20
#define B 10
int main()
{
#ifdef __DEBUG__
printf("__DEBUG__ DEFINED\n");
printf("%d\n",A);
#else
printf("__DEBUG__ not defined\n");
printf("%d\n",B);
#endif
return 0;
}
Если я компилирую:
$gcc test.c
Вывод:
__DEBUG__ not defined
10
Если я компилирую:
$gcc -D __DEBUG__ test.c
Вывод:
__DEBUG__ defined
30
Это мое решение для: -DUSB_PRODUCT=\""Arduino Leonardo\""
Я использовал его в make-файле с:
GNU Make 3.81 (из GnuWin32)
и
avr-g ++ (AVR_8_bit_GNU_Toolchain_3.5.0_1662) 4.9.2
Результаты в предварительно скомпилированном файле (опция -E для g ++):
const u8 STRING_PRODUCT[] __attribute__((__progmem__)) = "Arduino Leonardo";
К вашему сведению: очевидно, что даже разные версии одной и той же инструментальной цепочки в одной и той же системе могут действовать по-разному в этом отношении ... (Как и в случае, казалось бы , это проблема передачи оболочки, но, очевидно, она не ограничивается только оболочкой).
Здесь у нас xc32-gcc 4.8.3 vs. (avr-) gcc 4.7.2 (и несколько других) с использованием того же make-файла и main.c, единственная разница в том 'make CC=xc32-gcc'
и т. Д.
CFLAGS += -D'THING="$(THINGDIR)/thing.h"'
использовался на многих несколько лет версиях gcc (и bash).
Чтобы сделать это совместимым с xc32-gcc (и в свете другого комментария, утверждающего, что \ "более переносимо, чем '"), необходимо было сделать следующее:
CFLAGS += -DTHING=\"$(THINGDIR)/thing.h\"
ifeq "$(CC)" "xc32-gcc"
CFLAGS := $(subst \",\\\",$(CFLAGS))
endif
чтобы сделать вещи действительно запутанными при обнаружении этого: очевидно, что -D без кавычек с // приводит к #define с комментарием в конце ... например,
THINGDIR=/thingDir/
-> #define /thingDir//thing.h
->#define /thingDir
(Спасибо за помощь ответа S здесь, кстати).
Я только что обнаружил, что одно из наших приложений не компилируется на Ubuntu. И поскольку Linux и Windows не пришли к единому подходу, я использовал это:
NAME := "Mary"
ifeq ($(SystemRoot),)
# building on another OS
CFLAGS_ADD += -Dname=\"Mary\"
else
# building on Windows
CFLAGS_ADD += -Dname=\\\"Mary\\\"
endif
{
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++.exe build active file",
"command": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin\\g++.exe",
"args": [
"-g",
"-DSHERAJ",
"${file}",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "compiler: \"C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin\\g++.exe\""
}
]
}
Я сделал это #define SHERAJ
здесь, в VS Code. Он отлично подходит для соревновательного программирования, так как -
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef SHERAJ
freopen("input.txt" , "r", stdin);
#endif
int T;
cin>>T;
for(int test_case = 1;test_case<=T;test_case++) {
cout<<"Hello World"<<endl;
}
}
У меня это сработало для VS Code как на Mac, так и на Windows. Остальные методы, описанные здесь, мне понравились "-Dname=\"SHERAJ\""
и "-Dname=\\\"SHERAJ\\\""
не работали.
Итак, ответ "-DSHERAJ"
-DNAME=\"Mary\"
) для токенов, которые вы собираетесь определить таким образом, чтобы они выглядели как другие макросы.