|
Программирование >> Перегруженные имена функций и идентификаторы
Я слышал, что структуры можно копировать как целое, что они могут быть переданы функциям и возвращены ими, но в K&R I сказано, что этого делать нельзя В K&R I сказано лишь, что ограничения на операции со структурами будут сняты в следующих версиях компилятора; эти операции уже б1ли возможны в компиляторе Денниса Ритчи, когда издавалась книга K&R I. Хотя некоторые старые компиляторы не поддерживают копирование структур, все современные компиляторы имеют такую возможность, предусмотренную стандартом ANSI C, так что не должно быть колебаний при копировании и передаче структур функциям. Каков механизм передачи и возврата структур? Структура, передаваемая функции как параметр, обычно целиком размещается на стеке, используя необходимое количество машинных слов. (Часто для снижения ненужных затрат программисты предпочитают передавать функции указатель на структуру вместо самой структуры). Структуры часто возвращаются функциями в ту область памяти, на которую указывает дополнительный поддерживаемый компилятором скрытый аргумент. Некоторые старые компиляторы используют для возврата структур фиксированную область памяти, хотя это делает невозможным рекурсивный вызов такой функции, что противоречит стандарту ANSI. Эта программа работает правильно, но после завершения выдает дамп оперативной памяти. Почему? struct list char *item; struct list *next; /* Здесь функция main */ main(argc, argv) Из-за пропущенной точки с запятой компилятор считает, что main возвращает структуру. (Связь структуры с функцией main трудно определить, мешает комментарий). Так как для возврата структур компилятор обычно использует в качестве скрытого параметра указатель, код, сгенерированный для main() пытается принять три аргумента, хотя передаются (в данном случае стартовым кодом Си) только два. Почему нельзя сравнивать структуры? Не существует разумного способа сделать сравнение структур совместимым с низкоуровневой природой языка Си. Побайтовое сравнение может быть неверным из-за случайнгх бит в неиспользуемых дырках (такое заполнение необходимо, чтобы сохранить выравнивание для последующих полей). Почленное сравнение потребовало бы неприемлемого количества повторяющихся машинных инструкций в случае больших структур. Если необходимо сравнить две структуры, напишите для этого свою собственную функцию. C++ позволит создать оператор ==, чтобы связать его с вашей функцией. Как читать/писать структуры из файла/в файл? Писать структуры в файл можно непосредственно с помощью fwrite: fwrite((char *)&somestruct, sizeof(somestruct), 1, fp); а соответствующий вызов fread прочитает структуру из файла. Однако файлы, записанные таким образом будут не особенно переносимы. Заметьте также, что на многих системах нужно использовать в функции fopen флаг b . Мне попалась программа, в которой структура определяется так: struct name int namelen; char name[1]; затем идут хитрые манипуляции с памятью, чтобы массив name вел себя будто в нем несколько элементов. Такие манипуляции законны/мобильны? Такой прием популярен, хотя Деннис Ритчи назвал это слишком фамильярным обращением с реализацией Си . ANSI полагает, что выход за пределы объявленного размера члена структуры не полностью соответствует стандарту, хотя детальное обсуждение всех связанных с этим проблем не входит в задачу данных вопросов и ответов. Похоже, однако, что описанный прием будет одинаково хорошо принят всеми известными реализациями Си. (Компиляторы, тщательно проверяющие границы массивов, могут выдать предупреждения). Для страховки будет лучше объявить переменную очень большого размера чем очень малого. В нашем случае char name[MAXSIZE]; где MAXSIZE больше, чем длина любого имени, которое будет сохранено в массиве name[]. (Есть мнение, что такая модификация будет соответствовать Стандарту). Как определить смещение члена структуры в байтах? Если это возможно, необходимо использовать макрос offsetof, который определен стандартом ANSI. Если макрос отсутствует, предлагается такая (не на все 100% мобильная) его реализация: #define offsetof(type, mem) ((size t) \ ((char *)&((type *) 0)->mem - (char *)((type *) 0))) Для некоторых компиляторов использование этого макроса может оказаться незаконным. Как осуществить доступ к членам структур по их именам во время выполнения программы? Создайте таблицу имен и смещений, используя макрос offsetof(). Смещение члена структуры b в структуре типа a равно: offsetb = offsetof(struct a, b) Если structp указывает на начало структуры, а b - чен структуры типа int, смещение которого получено выше, b может быть установлен косвенно с помощью: *(int *)((char *)structp + offsetb) = value; Почему sizeof выдает больший размер структурного типа, чем я ожидал, как будто в конце структуры лишние символы? Это происходит (возможны также внутренние дыры , когда необходимо выравнивание при задании массива непрерывных структур. Мой компилятор оставляет дыры в структурах, что приводит к потере памяти и препятствует двоичному вводу/выводу при работе с внешними файлами. Могу я отключить дырообразование или как-то контролировать выравнивание? В вашем компиляторе, возможно, есть расширение, (например, #pragma), которое позволит это сделать, но стандартного способа не существует.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |