Вопрос по c – Будет ли этот трюк работать в C?

2

Я хочу добавить поле к структуре в C. Так, например, у меня есть следующая структура.

struct A
{
 some_type x;
 some_type y;
}

Я объявляю новую структуру, как это.

struct B
{
 A a;
 some_type z;
}

Теперь скажите, что у меня есть такая функция.

int some_function( A * a )

Можно ли передать ему переменную типа B, как это в программе.

B * b;
......
A * a = (A*)b;
some_function( a );

А также сможете использовать поля внутриsome_function используяa->x например?

Да, это действительно C. (Просто пишите это как комментарий, а не как ответ, потому что тот, кто отвечает, должен уточнить и найти ссылки, почему он действителен.) R..
Также, если вы хотите подобрать ООП, это можно сделать с помощью неназванных структур, если вы используете компилятор C11, и я бы предложил сделать параметр some_function () пустым *, чтобы продемонстрировать, что он может принимать оба типа A и тип B структура Lefteris
Я бы предложилA *a = &(b->a); В противном случае вы полагаетесь на (факт? Совпадение?), Что А оказывается первым в Б. paulsm4
Нет, это не сработает; должен быть ';' после '}'. Также в C, struct A {...}; является не определение типа. (вы компилируете C с помощью компилятора C ++?) wildplasser
Lefteris: Нет, я не могу сделать это недействительным *, я должен работать над устаревшим кодом. pythonic

Ваш Ответ

5   ответов
9

... Указатель на объект структуры, соответствующим образом преобразованный, указывает на его начальный элемент (или, если этот элемент является битовым полем, то на модуль, в котором он находится), и наоборот. Внутри объекта структуры может быть безымянный отступ, но не в его начале.

1

Вот как некоторые моделировали ОО-наследование в С

Вы можете использовать

  &b->a

вместо актерского состава. И, вероятно, сделать ASSERT, как

 ASSERT (&b->a == b)

быть предупрежденным, когда ты случайно уничтожил эту семантику

1

Почему бы просто не вызвать метод для члена?

some_function( &b->a );

Твой код работает сейчас, но что, если кто-то решит изменить членовB? Или добавьте нового участника передa?

Потому что это не то, что я хочу pythonic
@ user1018562 что ты хочешь? Luchian Grigore
@ user1018562 ты не хочешь передать участникаa ofb к методу? Luchian Grigore
Я хочу функциональность, эквивалентную производному классу C ++. pythonic
@ user1018562 - «То, что вы хотите» не считается :). Вы должны практиковать «Защитное программирование». Другими словами, с извинениями перед Миком Джаггером: «Если вы очень стараетесь, вы иногда получаете то, что вам нужно»;) paulsm4
0

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

Не позволяй этому думать, что это хорошая идея.

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

Напишите

A *a = &(b->a);

(как следует из приведенного выше комментария) и ваш смысл понятен.

Если по какой-то непонятной причине тебе нужно сыгратьB* вA*, тогда напишиочен четкий комментарий, объясняющий, почему у вас нет другого выбора, кроме как делать то, что вам нужно, уверяющий читателя в его легитимности и указывающий на подраздел подраздела C99, который его лицензирует.

Если вы действительно не можете найти этот подраздел (и обнаружите, что это ваша домашняя работа / покаяние), прокомментируйте так, и я выкопаю его.

0

Нет, это не сработает. Этобыло б работай, если немного поменяешь:

struct A
{
 some_type x;
 some_type y;
}; /* <- note semicolon here */


struct B
{
 struct A a;
 some_type z;
}; /* ... and here */


int some_function(struct A *a ); /* ... and here ... */


struct B *b;
......
struct A *a = (struct A*)b;
some_function( a );
Хотя это правда, ты не понимаешь сути вопроса. Luchian Grigore
Нет, я не. Вопрос был не на языке Си, и я это исправил. Я не могу ответить на вопросы о несуществующих языках. wildplasser
Downvoter: пожалуйста, объясните. (вы знакомы с C ++?) wildplasser

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