Структура программирования C передана как приведенная к char *? - PullRequest
5 голосов
/ 02 марта 2010

У меня есть небольшая проблема в сценарии, где:

while (read(dp->fd, (char *) &dirbuf, sizeof(dirbuf)) == sizeof(dirbuf)) { ... }

, где dirbuf:

struct direct dirbuf { 
    ino_t d_ino; char d_name[DIRSIZ]; 
};  

Как C узнает, что данные считываются в нашу структуру случайно?С read () Как, выравнивание нашего dirbuf идеально подходит как массив символов?поскольку read принимает void * в качестве второго аргумента, передача структуры в качестве приведения к char * имеет для меня мало смысла, как она правильно обрабатывает другие элементы-члены?

Я не уверен, что яЯ даже задаю этот вопрос должным образом, я надеюсь, что кто-то сможет расшифровать мою проблему из-за моего безумия и помочь мне.

Спасибо.

Ответы [ 3 ]

6 голосов
/ 02 марта 2010

Истерические изюминки

Приведение буферов к char * - это устаревший шаблон кода, который часто можно увидеть. Он использовался так часто, что по-прежнему набирается сегодня, даже после того, как он перестал быть необходимым.

В какой-то момент не было типа void, поэтому такой API, как read(2), объявил бы параметр буфера как char *, и все вызывающие стороны передали бы свои данные в char *.

Но read(2) был void * долгое время. Прошло так много времени с тех пор, как на сайте для звонков требовался какой-либо актерский состав.

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

Это не приносит никакого вреда.

Что касается непрерывных данных, то происходит одно из двух. Либо структура данных и тип предназначены для плотного размещения на большинстве или на всех вероятных машинах, либо аналогичный оператор использовался для записи данных в первую очередь, поэтому байты pad не имеют значения, если файл данных не должен быть перемещен между несопоставимыми архитектурами.

3 голосов
/ 02 марта 2010

Не читает и не выравнивает поля в структуре. Он просто берет общий размер структуры (от sizeof) и начальный адрес (от &dirbuf) и считывает в эту память независимо от объявления структуры.

Предполагается, что все, что было в файле, было уже правильно выровнено, чтобы соответствовать структуре.

(char *) приведен только для того, чтобы закрыть компилятор. (void *) сделал бы так же хорошо. Или вообще не приведение, поскольку компилятор преобразует тип указателя в void * без преобразования.

0 голосов
/ 02 марта 2010

Это должно быть данью архаичным версиям языка C, которые не имели типа void * и использовали вместо него char *. Если вы используете неархаичный компилятор и параметр действительно void *, нет необходимости приводить что-либо к char * (и нет необходимости также приводить что-либо к void *)

read(dp->fd, &dirbuf, sizeof(dirbuf)) 

И С не знает и не должен знать, как читать данные в вашей конкретной структуре. Когда вы делаете что-то подобное, двоичные данные из файла вслепую читаются в необработанную память, занятую вашим dirbuf объектом. Если расположение этих двоичных данных правильное (например, если файл был создан путем записи той же структуры одинаковым образом), то все будет правильно выровнено и все автоматически встанет на свое место.

Обратите внимание, что если вы не работаете с чем-то, на что распространяется очень строгая спецификация, такие простые двоичные методы записи / чтения могут использоваться только в пределах одного сеанса одной и той же программы или, возможно, между различными сеансами одной и той же версии. программы на той же платформе. Как только вы начинаете работать с разными платформами и / или разными версиями кода на одной и той же платформе, все может легко развалиться, как только изменится структура исходной памяти данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...