Тут важен сам механизм присваиваивания. Для C оно будет выглядеть так же. И для char тоже. Ты по сути скажи что-то лучше. А то нашёл тоже, к чему докопаться, смехота.
не надо так писать, даже если это валидное выражение.
#define SET_A(a, b, c) ((__builtin_types_compatible_p(typeof(a), char*) && (a)) ? (*(char*)(a) = c) : (b = c))
не претендую ни на что, но все-таки понятнее вашего и ф-цию не надо новую писать, и b все-таки не в пустую присваивается значение, но это gnu99, не C99.
А в C11 уже добавили полноценную стандартную проверку типов.
но вообще, такую вещь удобнее и логичнее оформить как ф-цию, тогда проверки пройдут автоматически, но тогда мы вернемся к первому моему утверждению - «не стоит так писать»