gcc 명령 줄에서 문자열 리터럴을 정의하는 방법은 무엇입니까?


80

gcc 명령 줄에서 -Dname=Mary다음 과 같은 문자열을 정의한 다음 소스 코드 printf("%s", name);에서 인쇄 하려는 Mary.
어떻게 할 수 있습니까?


8
-DNAME=\"Mary\"이런 식으로 정의 할 토큰에 대해 모두 대문자 ( )를 사용하여 다른 매크로처럼 보이도록하는 것이 좋습니다.
JSB ձոգչ 2010 년

답변:


97

두 가지 옵션. 먼저 따옴표를 이스케이프하여 껍질이 먹지 않도록합니다.

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는 매크로의 최종 정의까지 기꺼이 평가합니다.


아서 감사합니다. 당신은 C의 전문가 여야합니다. 추가 질문 : 두 번째 옵션을 추천합니다. STRINGIZE_VALUE_OF (name)을 사용할 때 gcc -Dname = Mary -DMary가있는 경우 "1"로 변환됩니다. 메리 interprite GCC 정지를 할 수 어쨌든이
리차드

Richard, 많은 검토 끝에 위의 예에서 작동하는 방법을 찾을 수 없다고 생각합니다. 안타깝게도 선택은 확장 (예 : "이름"제공) 및 전체 확장 (예 : Mary가 1로 정의 된 경우 name-> Mary-> 1)입니다. 정확한 사용 사례에 따라이 문제를 해결할 수있는 방법이있을 수 있습니다. 예를 들어 Mary가 정의가 아닌 const int가 될 수 있습니다.
Arthur Shipkowski 2010 년

누구든지 왜 그런 중첩 문자열 화 매크로를 사용해야하는지에 대한 근거를 제시 할 수 있습니까? 결과는 같아야하지만 STRINGIZE_VALUE_OF () 호출은 인수의 매크로 확장을 강제하는 것처럼 보이지만 STRINGIZE ()는 그렇지 않습니다.
Ionoclast Brigham

1
@IonoclastBrigham, 오늘까지 이것을 보지 못했습니다. 예를 들어, 많은 경우 stringize를 사용하여 assert ()를 구현하여 보유하고있는 정확한 표현식을 출력 할 수 있습니다.이 경우 매크로를 확장하지 않으려는 경우도 있습니다. 기본 스트링 화가 그런 방식으로 작동한다는 것을 알게되면 중첩은 두 번째 매크로 확장을 강제합니다.
Arthur Shipkowski 2014

29

쉘이 따옴표 및 기타 문자를 "먹는"것을 방지하려면 다음과 같이 작은 따옴표를 사용해보십시오.

gcc -o test test.cpp -DNAME='"Mary"'

이렇게하면 정의 된 내용 (따옴표, 공백, 특수 문자 등)을 완전히 제어 할 수 있습니다.


8

지금까지 찾은 가장 이식 가능한 방법은 사용 \"Mary\"하는 것입니다. gcc뿐만 아니라 다른 C 컴파일러에서도 작동합니다. 예를 들어 /Dname='"Mary"'Microsoft 컴파일러와 함께 사용하려고 하면 오류와 함께 중지되지만 /Dname=\"Mary\"작동합니다.


6

우분투에서는 CFLAGS를 정의하는 별칭을 사용하고 있었고 CFLAGS에는 문자열을 정의하는 매크로가 포함 된 다음 Makefile에서 CFLAGS를 사용합니다. 큰 따옴표 문자와 \ 문자도 이스케이프해야했습니다. 다음과 같이 보입니다.

CFLAGS='" -DMYPATH=\\\"/home/root\\\" "'

2
때로는 작은 이스케이프와 작은 따옴표로 묶는 것이 작동하지 않았지만 작동했습니다. 다른 때는 그렇지 않았습니다. 차이점은 플래그가 전체적으로 따옴표로 묶여 있는지 여부입니다. 1) DEFINES=-DLOGPATH=\"./logfile\" CFLAGS = -v $(DEFINES).... 2) DEFINES=-DLOGPATH=\\\"./logfile\\\" CFLAGS = "-v $(DEFINES)...." -v 컴파일러 옵션을 사용하면 전처리 기가 수행하는 작업을 볼 수 있습니다.
Den-Jason

2

다음은 간단한 예입니다.

#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

이것은 부울처럼 사용되는 정의의 좋은 예입니다. 그러나 OP는 더 까다로운 문자열을 정의합니다.
Lassi 2011

1

이것은 내 솔루션입니다 : GNU Make 3.81 (GnuWin32에서) 및 avr-g ++ (AVR_8_bit_GNU_Toolchain_3.5.0_1662) 4.9.2 -DUSB_PRODUCT=\""Arduino Leonardo\""
와 함께 makefile에서 사용했습니다.


사전 컴파일 된 파일 (g ++의 경우 -E 옵션)의 결과는 다음과 같습니다.
const u8 STRING_PRODUCT[] __attribute__((__progmem__)) = "Arduino Leonardo";


0

참고 : 분명히 동일한 시스템에서 동일한 툴체인 심지어 다른 버전 (마찬가지로, 것입니다 ...이 점에서 다른 역할을 할 수 보이는 이 쉘 통과 문제가 될 것입니다,하지만 분명히 그것은 단지 쉘에 제한 아니에요).

여기서 우리는 동일한 makefile과 main.c를 사용하는 xc32-gcc 4.8.3 대 (avr-) gcc 4.7.2 (및 기타 여러 가지 )가 있습니다 'make CC=xc32-gcc'.

CFLAGS += -D'THING="$(THINGDIR)/thing.h"'에에서 사용되었습니다 많은 몇 년 동안 GCC (배쉬)의 버전.

이것을 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 , btw 도움을 주셔서 감사합니다 ).


0

방금 우리 응용 프로그램 중 하나가 Ubuntu에서 컴파일되지 않는다는 것을 발견했습니다. 그리고 Linux와 Windows는 일반적인 접근 방식에 동의하지 않았기 때문에 다음을 사용했습니다.

NAME := "Mary"

ifeq ($(SystemRoot),)
    # building on another OS
    CFLAGS_ADD += -Dname=\"Mary\"
else
    # building on Windows
    CFLAGS_ADD += -Dname=\\\"Mary\\\"
endif

0
{
    "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 SHERAJVS 코드 여기에. 다음과 같이 경쟁 프로그램에 적합합니다.

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;
    }
}

Mac과 Windows 모두에서 VS Code에서 저에게 효과적이었습니다. 다른 방법은 여기에 같은 설명 "-Dname=\"SHERAJ\"""-Dname=\\\"SHERAJ\\\""나를 위해 작동하지 않았다.

그래서 대답은 "-DSHERAJ"

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.