Оператор вставки токена ##
требует, чтобы его два операнда были действительными токенами предварительной обработки, и выдает один токен предварительной обработки. Он часто используется для объединения двух идентификаторов в один идентификатор.
То, что вы пытаетесь сделать, - это не вставка токенов. Вместо этого вы стремитесь создать выражения типа s.x
или s.c.x
, где часть x
всегда представляет собой один токен. Следовательно, оператор ##
не должен использоваться. Вместо этого вы можете просто сделать это:
#define M(obj, y) obj.y x
Когда вы пытаетесь использовать оператор ##
, препроцессор пытается объединить последний токен в аргументе y
с токеном x
. В c.
.
является токеном, поэтому результатом является .x
, который не является допустимым токеном. Скорее, .x
действителен только как последовательность из двух токенов.