Раздел «Язык Си».CfaqFullDeclaration:

Декларация и инициализация

Наброски перевода полного списка из http://c-faq.com/questions.html

1.1

Q: Какой тип целочисленной переменной использовать ?

A: Если могут потребоваться большие числа, (больше 32767 или меньше -32767), используйте тип long. Если нет, и важна экономия памяти (большие массивы или много структур), используйте short. Во всех остальных случаях используйте int. Если важно точно определить момент переполнения и/или знак числа не имеет значения, используйте соответствующий тип unsigned. (Но будьте внимательны при совместном использовании типов signed и unsigned в выражениях). Похожие соображения применимы при выборе между float и double.

Хотя тип char или unsigned char может использоваться как целочисленный тип наименьшего размера, от этого больше вреда, чем пользы из-за непредсказуемых перемен знака и возрастающего размера программы.

Эти правила, очевидно, не применимы к адресам переменных, поскольку адрес должен иметь совершенно определенный тип.

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

Если вам нужны числа, большие чем гарантируют встроенные типы, или вам нужны вычисления с произвольной точностью (или "multiple precision"); см. вопрос 18.15d.

1.2 NEW

Q: Почему не определены точные размеры стандартных типов?

A: Хотя С считается низкоуровневым языком в семействе языков высокого уровня, точный размер в битах относится к реализации, а не к стандарту. (Единственное место, где С позволяет определить размер и порядок бит - это битовые поля структур, см. вопросы 2.25 и 2.26). Большинству программ не нужен контроль за размером этих данных; многие программы, которые пытаются достигнуть полного контроля, лучше от этого не становятся.

Предполагается, что int имеет размер машинного слова. Он подходит для большинства целочисленных переменных. Смотрите вопросы 1.1, 12.42 и 20.5.

1.3 NEW

Q: Так как С не определяет точные размеры типов, я могу определить, используя typedef, int16 и int32 через short, int, long в зависимости от машины. Это решит проблему контроля, верно?

A: Если вам действительно нужен контроль за размером типов, это правильный подход. Учтите, что:

См. также вопросы 10.16 и 20.5.

1.4

Q: Каким должен быть новый 64-битный тип на новых 64-битных машинах?

A: Некоторые поставщики С компиляторов для 64-битных машин поддерживают тип long int длиной 64 бита. Другие же, опасаясь, что слишком многие уже написанные программы зависят от sizeof(int) == sizeof(long) == 32 бита , вводят новый 64-битный тип long long (или __longlong).

Программисты, желающие писать мобильные программы, должны, следовательно, изолировать 64-битные типы с помощью средства typedef. Разработчики компиляторов, чувствующие необходимость ввести новый целочисленный тип большего размера, должны объявить его как "имеющий по крайней мере 64 бит" (это действительно новый тип, которого нет в традиционном С), а не как "имеющий точно 64 бит".

См. также вопросы 1.3 и 18.15d.

1.5 NEW

Q: Что неправильно в декларации
char* p1, p2;
При использовании p2 возникает ошибка

A: Декларация правильная, за исключением того, что она не делает то, что вы от нее ждете. В декларации указателей * не является частью базового типа; это часть декларатора, содержащаего декларируемое имя (см. 1.21). То есть, в С синтаксис и интерпретация декларации не
тип идентификатор;
а скорее
базовый_тип то_что_дает_базовый_тип;
где "то_что_дает_базовый_тип" — декларатор — либо просто идентификатор, либо запись подобная *p или a[10] или f(), показывающая, что переменная определена как указатель на, массив из, или это функция, возвращающая базовый_тип. (Конечно, могут быть более сложные деклараторы).

В декларации, описанной в вопросе, безотносительно того, на что намекает отсутствие пробела между базовым типом и , базовый тип char и первый декларатор p1, и так как декларатор содержит *, это определяет p1 как указатель-на-char. Декларатор для p2 не содержит ничего кроме p2, то есть p2 определена как переменная типа char, вероятно не то, что вы хотели. Для декларации двух указателей в единой декларации используйте
char *p1, *p2;
Так как * это часть декларатора, лучше использовать пробел, чтобы подчеркнуть это; написание char* вводит в заблуждение.

См. вопрос 1.13.

1.6 NEW

Q: Я пытаюсь определить указатель и захватить память, но это не работает. Что не так в этом коде?
char *p;
*p = malloc(10);

A: Декларированный указатель это p, а не *p. См. вопрос 4.2.

1.7

Q: A:

1.8

Q: A:

1.9

Q: A:

1.10

Q: A:

1.11

Q: A:

1.1

Q: A:

1.1

1.1

1.1

1.1

-- TatyanaDerbysheva - 02 Jan 2011