0

Почему программисты на C используют typedef для переименования базовых типов?

9

Я не эксперт в C, но меня давно беспокоит один вопрос по поводу кода, который я читаю: можете ли вы объяснить, почему программисты на C (и C++) используют typedef для переименования простых типов? Я понимаю, зачем это нужно для структур, но в чем именно причина таких объявлений, как:

typedef unsigned char uch;
typedef uch UBYTE;
typedef unsigned long ulg;
typedef unsigned int u32;
typedef signed short s16;

Есть ли какие-то преимущества в этом, которые мне не до конца ясны (учитывая, что мой опыт начинается с Java и я не сильно углублялся в языки с строгой типизацией)? Я не могу подумать ни о какой причине для этого — кажется, что это только усложняет чтение кода для людей, незнакомых с проектом.

Не стесняйтесь считать меня новичком в C, я действительно знаю о нем очень мало и, вероятно, есть вещи, которые я неправильно понимаю с самого начала. 😉

5 ответ(ов)

0

Переименование типов без изменения их семантики или характеристик не имеет большого смысла. В вашем примере

typedef unsigned char uch;
typedef unsigned long ulg;

это именно та категория. Я не вижу в этом смысла, кроме как сделать имена короче.

Но в случае этих определений

typedef uch UBYTE;
typedef unsigned int u32;
typedef signed short s16;

это совершенно иная история. Например, s16 обозначает "знаковый тип 16 бит". Этот тип не обязательно должен быть signed short. Конкретный тип, скрывающийся за s16, зависит от платформы. Программисты вводят этот дополнительный уровень именования, чтобы упростить поддержку нескольких платформ. Если на какой-то другой платформе знаковый 16-битный тип оказывается signed int, программисту нужно будет изменить лишь одно определение типа. UBYTE, очевидно, обозначает "беззнаковый байт машины", который не обязательно соответствует unsigned char.

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

0

Это обеспечивает переносимость. Например, вам нужен беззнаковый 32-битный целочисленный тип. Какой стандартный тип для этого? Вы не знаете — это определяется реализацией. Вот почему вы используете typedef, чтобы создать отдельный тип для 32-битного беззнакового целого числа и используете этот новый тип в своем коде. Когда вам нужно скомпилировать код на другой реализации C, вы просто изменяете typedefs.

0

Иногда typedef используется для упрощения сложных типов, таких как volatile unsigned long, превращая их в более компактные обозначения, например, vuint32_t.

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

0

Есть несколько причин для этого. На мой взгляд, можно выделить следующие:

  1. Имя типа становится короче, что приводит к уменьшению объема кода и повышению его читаемости.
  2. Эффект псевдонима для более длинных названий структур.
  3. Конвенции, принятые в конкретной команде/компании/стиле программирования.
  4. Портируемость - использование одинаковых имен на всех операционных системах и на разных машинах. Его нативная структура данных может немного отличаться.
0

Ответ на ваш вопрос можно сформулировать следующим образом:

Далее приведена цитата из книги "Язык программирования C" (K&R):

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

Первая причина — параметризовать программу

Первая причина заключается в параметризации программы в отношении проблем портируемости. Если typedef используются для типов данных, которые могут зависеть от конкретной машины, то только typedef нужно будет изменить при переносе программы.

Одна распространенная ситуация — использовать имена typedef для различных целочисленных величин, а затем сделать соответствующий набор выборов типа short, int и long для каждой конкретной машины. Типы, такие как size_t и ptrdiff_t из стандартной библиотеки, являются примерами.

Курсивом выделенные части указывают на то, что программисты используют typedef для базовых типов данных, чтобы обеспечить портативность. Если я хочу убедиться, что моя программа работает на различных платформах и с разными компиляторами, я постараюсь обеспечить её портируемость всеми возможными способами, и typedef является одним из них.

Когда я начал программировать, используя компилятор Turbo C на платформе Windows, размер int составил 2. Когда я перешел на платформу Linux и компилятор GCC, размер, который я получил, оказался 4. Если бы я разработал программу с использованием Turbo C, которая полагалась на утверждение, что sizeof(int) всегда равен двум, она бы не перенеслась корректно на мою новую платформу.

Надеюсь, это поможет.

Следующая цитата из K&R не относится напрямую к вашему вопросу, но я привожу её для полноты:

Вторая причина — для лучшей документации

Вторая цель использования typedef — это предоставление лучшей документации для программы. Тип, называемый Treeptr, может быть легче понять, чем тот, который объявлен только как указатель на сложную структуру.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь