Различия в операторе сцепления Macro ## между Visual-C ++ и gcc

StackOverflow https://stackoverflow.com/questions/1206624

Вопрос

У меня такой макрос (не совсем, но функция вполне эквивалентна):

#define STRUCTMEMBER(Member,Value) GlobalStructInstance. ## Member = Value
...
STRUCTMEMBER(Item,1);

Это прекрасно работает в Visual C ++, но gcc 3.4.5 (MingGW) выдает следующую ошибку:

  

вставка ". " и " Предмет " не дает действительный токен предварительной обработки

Это также происходит, когда я использую " - > " оператор. Я не нашел намеков на конкатенацию, что использование этих операторов запрещено.

У кого-нибудь есть идея?

Это было полезно?

Решение

Может быть, Visual C ++ вставляет несколько пробелов вместе, чтобы создать еще один пробел. Не то, чтобы пробелы были токенами, но это позволило бы вашему коду работать.

object.member не является токеном, это три токена, поэтому вам не нужно вставлять токены для реализации макроса, который вы описываете. Просто удалите «##», и он должен работать везде.

[Правка: только что отмечен, и результат использования ## для формирования чего-то, что не является допустимым токеном, не определено. Поэтому GCC разрешено отклонять его, а MSVC разрешено игнорировать его и не выполнять вставку, насколько я могу судить.]

Другие советы

В соответствии со стандартом C, результатом оператора предварительной обработки ' ## ' должен быть 'токен предварительной обработки', или результат не определен (C99 6.10.3.3 (3) - ## оператор).

Список токенов предварительной обработки (C99 6.4 (3) - Лексические элементы):

  

имена заголовков, идентификаторы, числа предварительной обработки, символьные константы, строковые литералы, знаки пунктуации и одиночные символы, не являющиеся пробелами, которые лексически не соответствуют другим категориям токенов предварительной обработки.

GCC сообщает, что вы входите на неопределенную территорию. MSVC безмолвно рад неизвестному результату (именно этого вы и ожидаете).

Обратите внимание, что если вы все равно не создаете один токен, вам не нужен оператор вставки токена. Как правило (я уверен, что, возможно, есть исключение или два), 2 токена, разделенные пробелом, эквивалентны 2 токенам, не разделенным пробелом - как в вашем примере.

Из документации препроцессора gcc c :

  

Однако два токена, которые вместе не образуют действительный токен, не могут быть вставлены вместе.

Structure.member - это не один токен.

В этом случае вам не нужно использовать оператор ## (конкатенация токенов). Вы можете просто удалить это. Вот пример, протестированный с gcc 4.2.4 на linux:

#include <stdio.h>

#define STRUCTMEMBER(Member, Value) GlobalStructInstance.Member = Value

struct {
    const char* member1;
}GlobalStructInstance;

int main(void)
{

    STRUCTMEMBER(member1, "Hello!");

    printf("GlobalStructInstance.member1 = %s\n",
           GlobalStructInstance.member1);

    return 0;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top