C Макросы для создания строк

Если вы используете BSD / OS X, вы можете использовать jot вместо seq:

for i in $(jot $END); do echo $i; done
29
задан Brian Tompsett - 汤莱恩 5 February 2016 в 09:56
поделиться

7 ответов

В C строковые литералы объединяются автоматически. Например,

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

s1 и s2 - это одна и та же строка.

Итак, для вашей задачи ответ (без вставки токена):

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

#define IV_SECURE "secure." IV_DOMAIN
#define IV_MOBILE "m." IV_DOMAIN
38
ответ дан Alex B 5 February 2016 в 09:56
поделиться

Есть несколько способов сделать это:

  1. если вы имеете дело только со строковыми литералами, вы можете просто использовать просто строки - размещение одного строкового литерала за другим вызывает компилятор для их объединения.

  2. если могут быть задействованы другие вещи, кроме строковых литералов (т. Е. Вы создаете новые идентификаторы из макросов), используйте оператор вставки токена препроцессора '##. Возможно, вам также понадобится использовать Строковый оператор '#', чтобы превратить ваши макросы в буквальные строки.

Пример # 1:

#ifdef __TESTING
    #define IV_DOMAIN "domain.org"                        //in house testing
#elif __LIVE_TESTING
    #define IV_DOMAIN "test.domain.com"           //live testing servers
#else
    #define IV_DOMAIN "domain.com"                        //production
#endif

// Sub-Domain
#define IV_SECURE "secure." IV_DOMAIN          //secure.domain.org etc
#define IV_MOBILE "m." IV_DOMAIN

И до вставки токена оператор идет, я не думаю, что большинство ответов, в которых предлагалось использовать оператор препроцессора вставки токена, действительно пытались это сделать - это может быть сложно использовать.

Использование часто предлагаемого ответа приведет к ошибка компилятора при попытке использовать макрос IV_SECURE, потому что:

#define IV_SECURE "secure."##IV_DOMAIN

расширяется до:

"secure"domain.org

Возможно, вы захотите попробовать использовать ' # `' оператор 'stringizing':

#define IV_SECURE "secure." #IV_DOMAIN

Но это не сработает, потому что он работает только с аргументами макроса, а не только с любым старым макросом.

Об этом нужно знать, когда вы с использованием Token-Paste ('##') или stringizing ('#') операторы обработки - это то, что вы должны использовать дополнительный уровень косвенности, чтобы они работали должным образом во всех случаях.

Если вы этого не сделаете, а элементы, переданные оператору вставки токена, сами являются макросами, вы Вы получите результаты, которые, вероятно, не соответствуют вашим ожиданиям:

#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 определения и макросы утилит сверху, вы можете сделайте это, чтобы получить то, что вы хотите:

// Sub-Domain
#define IV_SECURE "secure." STRINGIFY( IV_DOMAIN)   //secure.domain.org etc
#define IV_MOBILE "m." STRINGIFY( IV_DOMAIN)
25
ответ дан Michael Burr 5 February 2016 в 09:56
поделиться

Вам нужны операторы # и ## и автоматическая конкатенация строк.

Оператор предварительной обработки # превращает параметр макроса в строку. Оператор ## вставляет два токена (например, макропараметры) вместе.

Мне приходит в голову возможность

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

, которая должна изменить значение IV_SECURE на

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

, которое автоматически объединится в «secure.domain.org» (при условии, что фазы перевода в Си такие же, как и в С ++).

ДРУГОЕ РЕДАКТИРОВАНИЕ: Пожалуйста, прочитайте комментарии, которые показывают, как мне удалось запутаться. Имейте в виду, что я полностью опытен в Си, хотя, возможно, немного ржавый. Я бы удалил этот ответ, но я решил оставить его как пример того, как легко быть запутанным препроцессором Си.

5
ответ дан David Thornley 5 February 2016 в 09:56
поделиться

Я вижу много хороших и правильных ответов на ваш первый вопрос, но нет ответов на ваш второй, поэтому вот что: я думаю, что это ужасная идея. Почему вы должны пересобрать свое программное обеспечение (особенно выпускную версию), чтобы просто изменить имя сервера? Кроме того, как вы узнаете, какая версия вашего программного обеспечения указывает на какой сервер? Вам придется встроить механизм для проверки во время выполнения. Если это вообще практично для вашей платформы, я рекомендую вам загрузить домены / URL-адреса из файла конфигурации. Только самые маленькие встраиваемые платформы не могут быть «практичными» для этой цели:)

7
ответ дан rmeador 5 February 2016 в 09:56
поделиться

Как уже отмечалось, используйте вставку токенов. Вы также должны знать, что имена макросов, такие как

__TESTING

, зарезервированы в C (не знаю об Objective C) для реализации - вам не разрешено использовать их в своем собственном коде. Зарезервированные имена - это все, что содержит двойное подчеркивание и что-либо, начинающееся с подчеркивания и заглавной буквы.

3
ответ дан 5 February 2016 в 09:56
поделиться

Следующие вместе строки объединяются компилятором C.

#define DOMAIN "example.com"
#define SUBDOMAIN "test." DOMAIN
const char *asCString = SUBDOMAIN;
NSString *asNSString = @SUBDOMAIN;
8
ответ дан rpetrich 5 February 2016 в 09:56
поделиться

Попробуйте использовать оператор ##

#define IV_SECURE secure.##IV_DOMAIN
6
ответ дан JaredPar 5 February 2016 в 09:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: