Я знаю, что это старый вопрос, но, на мой взгляд, можно сказать еще кое-что, а некоторые другие ответы неверны.
Во-первых, этот актерский состав:
(struct Base *)ptr
... разрешено, но только при условии соблюдения требований по выравниванию. На многих компиляторах ваши две структуры будут иметь одинаковые требования к выравниванию, и это легко проверить в любом случае. Если вы преодолеете это препятствие, то следующим будет то, что результат приведения в основном не определен, то есть в стандарте C не требуется, чтобы указатель после приведения все еще ссылался на тот же объект (только после приведения его обратно к исходному типу обязательно так и будет).
Однако на практике компиляторы для распространенных систем обычно заставляют результат приведения указателя ссылаться на один и тот же объект.
(Приведение указателей описано в разделе 6.3.2.3 как стандарта C99, так и более нового стандарта C11. Я считаю, что правила в обоих случаях практически одинаковы).
Наконец, у вас есть так называемые правила "строгого алиасинга", с которыми нужно бороться (C99 / C11 6.5, параграф 7); по сути, вам не разрешен доступ к объекту одного типа через указатель другого типа (с некоторыми исключениями, которые не применимы в вашем примере). См. «Что такое правило строгого наложения имен?» или для очень подробного обсуждения прочитайте мой пост в блоге на эту тему.
В заключение, то, что вы пытаетесь в своем коде, не гарантируется. Может быть гарантированно всегда работать с определенными компиляторами (и с определенными параметрами компилятора), и это может работать случайно со многими компиляторами, но это, безусловно, вызывает неопределенное поведение в соответствии со стандартом языка C.
Что вы могли бы сделать вместо этого:
*((int *)ptr) = 1;
... т.е. поскольку вы знаете, что первым членом структуры является int
, вы просто приводите непосредственно к int
, что позволяет обойти проблему псевдонимов, поскольку оба типа структуры на самом деле содержат int
по этому адресу. Вы полагаетесь на знание структуры структуры, которую будет использовать компилятор, и вы все еще полагаетесь на нестандартную семантику приведения указателей, но на практике это значительно реже создает проблемы.