У командному рядку 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";
FYI: Очевидно, навіть різні версії одного і того ж ланцюжка інструментів в одній системі можуть діяти по-різному в цьому відношенні ... (Як, здається, це було б проблемою проходження оболонки, але, очевидно, це не обмежується лише оболонкою).
Тут ми маємо xc32-gcc 4.8.3 проти (avr-) gcc 4.7.2 (та декілька інших), використовуючи той самий makefile та 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\"
) для маркерів, які ви збираєтесь визначити таким чином, щоб вони мали вигляд інших макросів.