source

C에서 문자열을 만들 매크로

ittop 2023. 10. 19. 22:45
반응형

C에서 문자열을 만들 매크로

대체 제목(검색을 지원하기

  • 전처리기 토큰을 문자열로 변환
  • C 매크로 값으로 문자열을 만들려면 어떻게 해야 합니까?

원래 질문

C를 사용하고 싶습니다. #define컴파일 타임에 문자 문자열을 만듭니다.

문자열은 디버그, 릴리스 등을 위해 변경되는 도메인입니다.

저는 다음과 같은 일을 하고 싶습니다.

#ifdef __TESTING
    #define IV_DOMAIN example.org            // In house testing
#elif __LIVE_TESTING
    #define IV_DOMAIN test.example.com       // Live testing servers
#else
    #define IV_DOMAIN example.com            // Production
#endif

// Subdomain
#define IV_SECURE "secure.IV_DOMAIN"         // secure.example.org, etc.
#define IV_MOBILE "m.IV_DOMAIN"

그러나 전처리기는 "" 내에서 어떤 것도 평가하지 않습니다.

  1. 이 문제를 해결할 방법이 있습니까?
  2. 이게 좋은 생각일까요?

C에서는 문자열 리터럴이 자동으로 연결됩니다.예를들면,

const char * s1 = "foo" "bar";
const char * s2 = "foobar";

s1그리고.s2같은 문자열입니다.

따라서 문제에 대한 답은 (토큰 붙여넣기 없이)

#ifdef __TESTING
    #define IV_DOMAIN "example.org"
#elif __LIVE_TESTING
    #define IV_DOMAIN "test.example.com"
#else
    #define IV_DOMAIN "example.com"
#endif

#define IV_SECURE "secure." IV_DOMAIN
#define IV_MOBILE "m." IV_DOMAIN

다음과 같은 몇 가지 방법이 있습니다.

  1. 문자열 리터럴만 다루면 간단히 문자열을 사용할 수 있습니다. placing 한 문자열 리터럴을 사용하면 컴파일러가 문자열을 연결할 수 있습니다.

  2. 문자열 리터럴 이외에 다른 것이 포함되어 있을 수 있다면(즉, 매크로에서 새 식별자를 생성하는 경우) '을 사용합니다.##" 전처리기 토큰 붙여넣기 연산자.당신은 아마 '를 사용해야 할 것입니다.#' 매크로를 문자 그대로의 문자열로 만들기 위해 연산자를 조정합니다.

#1의 예:

#ifdef __TESTING
    #define IV_DOMAIN "example.org"            // In house testing
#elif __LIVE_TESTING
    #define IV_DOMAIN "test.example.com"       // Live testing servers
#else
    #define IV_DOMAIN "example.com"            // Production
#endif

// Subdomain
#define IV_SECURE "secure." IV_DOMAIN          // secure.example.org, etc.
#define IV_MOBILE "m." IV_DOMAIN

토큰 붙여넣기 연산자에 관해서는 토큰 붙여넣기 전처리기 연산자를 사용하는 것을 제안한 대부분의 답변이 실제로 시도해 본 적은 없다고 생각합니다. 사용하기가 까다로울 수 있습니다.

자주 제안되는 답변을 사용하면 컴파일러 오류가 발생합니다.IV_SECURE매크로, 이유:

#define IV_SECURE "secure."##IV_DOMAIN

확장 대상:

"secure"example.org

사용을 시도해 볼 수도 있습니다.'#`' '스트링' 연산자:

#define IV_SECURE "secure." #IV_DOMAIN

그러나 이는 기존 매크로가 아닌 매크로 인수에서만 작동하기 때문에 작동하지 않습니다.

토큰 paste('##')를 사용하거나 전처리 연산자를 문자열화('#')할 때 주의해야 할 한 가지 사항은 모든 경우에 적절하게 작동하려면 추가 수준의 간접 지시를 사용해야 한다는 것입니다.

이렇게 하지 않고 토큰 붙여넣기 연산자에게 전달된 항목이 매크로 자체라면 원하는 결과가 아닐 수 있습니다.

#include <stdio.h>

#define STRINGIFY2( x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#define PASTE2( a, b) a##b
#define PASTE( a, b) PASTE2( a, b)

#define BAD_PASTE(x,y) x##y
#define BAD_STRINGIFY(x) #x

#define SOME_MACRO function_name

int main()
{
    printf( "buggy results:\n");
    printf( "%s\n", STRINGIFY( BAD_PASTE( SOME_MACRO, __LINE__)));
    printf( "%s\n", BAD_STRINGIFY( BAD_PASTE( SOME_MACRO, __LINE__)));
    printf( "%s\n", BAD_STRINGIFY( PASTE( SOME_MACRO, __LINE__)));

    printf( "\n" "desired result:\n");
    printf( "%s\n", STRINGIFY( PASTE( SOME_MACRO, __LINE__)));
}

출력:

buggy results:
SOME_MACRO__LINE__
BAD_PASTE( SOME_MACRO, __LINE__)
PASTE( SOME_MACRO, __LINE__)

desired result:
function_name21

그래서 당신의 오리지널을 사용해서.IV_DOMAIN를 정의하고 위에서 유틸리티 매크로를 실행하면 원하는 것을 얻을 수 있습니다.

// Subdomain
#define IV_SECURE "secure." STRINGIFY( IV_DOMAIN)   //secure.domain.org etc
#define IV_MOBILE "m." STRINGIFY( IV_DOMAIN)

첫 번째 질문에 대한 좋은 답변과 정답은 많이 보았지만 두 번째 질문에는 답이 없었습니다. 그래서 여기 있습니다.저는 이것이 끔찍한 생각이라고 생각합니다.

서버 이름을 변경하기 위해 소프트웨어(특히 릴리스 버전)를 재구축해야 하는 이유는 무엇입니까?또한 소프트웨어의 어떤 버전이 어떤 서버를 가리키는지 어떻게 알 수 있습니까?런타임에 확인할 수 있는 메커니즘을 구축해야 합니다.

플랫폼에서 실용적이라면 구성 파일에서 도메인/URL을 로드하는 것이 좋습니다.가장 작은 임베디드 플랫폼만이 이러한 목적을 위해 "실용적"이지 않을 수 있습니다.

다음에 같이 있는 문자열들은 C 컴파일러에 의해 결합됩니다.

#define DOMAIN "example.com"
#define SUBDOMAIN "test." DOMAIN
const char *asCString = SUBDOMAIN;
NSString *asNSString = @SUBDOMAIN;

## 연산자를 사용해 보십시오.

#define IV_SECURE secure.##IV_DOMAIN

필요한 것은 #와 ## 연산자와 자동 문자열 연결입니다.

# 전처리 연산자는 매크로 파라미터를 문자열로 바꿉니다.## 연산자는 두 개의 토큰(예: 매크로 매개 변수)을 함께 붙여 넣습니다.

생각나는 가능성은

#define IV_DOMAIN domain.org
#define IV_SECURE(DOMAIN) "secure." #DOMAIN

IV_SECure를 다음으로 변경해야 합니다.

#define IV_SECURE "secure." "domain.org"

자동으로 "secure.domain.org "에 연결됩니다(assuming 번역 단계는 C에서 C++와 동일함).

제발 제가 어떻게 혼란스러웠는지 댓글을 읽어주세요.비록 녹슬지는 않았지만, 저는 C에 대해 충분히 경험이 있다는 것을 명심하세요.이 답변은 삭제하겠지만, C 전처리기 때문에 혼동하기 쉽다는 것을 보여주는 사례로 남겨두려고 생각했습니다.

다른 사람들이 언급한 것처럼 토큰 붙여넣기를 사용합니다.매크로 이름은 다음과 같습니다.

__TESTING

구현을 위해 C(목표 C에 대해 알 수 없음)에 예약되어 있습니다. 자신의 코드에서 사용할 수 없습니다.예약된 이름은 밑줄이 이중으로 포함된 모든 이름과 밑줄과 대문자로 시작하는 모든 이름입니다.

언급URL : https://stackoverflow.com/questions/798221/macros-to-create-strings-in-c

반응형