ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.12.2020
Просмотров: 4264
Скачиваний: 28
Часть I. Язык программирования С
116
Листинг 8.6. Объявление функции при помощи синонима типа
#include <stdio.h>
int foo(int n) { return n; }
typedef int f(int), (*pf)(int);
f foo;
pf pfoo = &foo;
int main(void)
{
int n;
n = foo(10);
printf("%d\n", n); /* 10 */
n = pfoo(20);
printf("%d\n", n); /* 20 */
return 0;
}
8.8. Оператор
sizeof
Для определения длины, как встроенных типов данных, так и ти-
пов данных, определенных программистом, используется опера-
тор
sizeof
, который имеет следующий синтаксис:
sizeof выражение
или:
sizeof(тип)
Работает этот оператор на этапе компиляции программы. Опера-
тор
sizeof
возвращает целочисленную константу без знака, кото-
рая равна длине операнда в байтах. Эта константа имеет тип
size_t
, который описан в заголовочном файле stddef.h. Оператор
sizeof
применяется для того, чтобы избежать использования ап-
паратно-зависимых длин данных в программе. Не допускаются
операнды, которые имеют тип битового поля, функции или не-
Глава 8. Типы данных, определяемые программистом
117
полного типа. К
неполным
(incomplete) типам данных относятся
следующие типы:
тип
void
;
массив неопределенного размера;
массив, элементы которого имеют неполный тип;
перечисление, структура или объединение с неопределенными
членами.
Например, если объявлен указатель на структуру:
struct demo *p;
а сама структура не объявлена, то тип структуры будет неполным
типом.
Если операндом оператора
sizeof
является массив или структура,
то в результате получаем длину этого массива или структуры.
Если последним элементом структуры является массив неопреде-
ленной длины, то оператор
sizeof
возвращает размер структуры
без этого массива.
В листинге 8.7 приведены примеры работы оператора
sizeof
,
операндом которого являются выражения.
Листинг 8.7. Определение длины переменных
посредством оператора
sizeof
#include <stdio.h>
int main(void)
{
int n = 0;
double d = 0;
char c = 'c';
char a[10] = "array";
printf("sizeof n = %d\n", sizeof n); /* sizeof n = 4 */
printf("sizeof d = %d\n", sizeof d); /* sizeof d = 8 */
printf("sizeof c = %d\n", sizeof c); /* sizeof c = 1 */
printf("sizeof a = %d\n", sizeof a); /* sizeof a = 10 */
return 0;
}
Часть I. Язык программирования С
118
В листинге 8.8 приведены примеры работы оператора
sizeof
,
операндом которого является тип данных.
Листинг 8.8. Определение длины типов посредством
оператора
sizeof
#include <stdio.h>
struct emp
{
int empno;
char name[20];
double salary;
};
int main()
{
/* sizeof(int) = 4 */
printf("sizeof(int) = %d\n", sizeof(int));
/* sizeof(char) = 1 */
printf("sizeof(char) = %d\n", sizeof(char));
/* sizeof(double) = 8 */
printf("sizeof(double) = %d\n\n", sizeof(double));
/* sizeof(struct emp) = 32 */
printf("sizeof(emp) = %d\n", sizeof(struct emp));
return 0;
}
В языке программирования С++ при использовании оператора
sizeof
допускается любой тип операнда брать в скобки.
Учитывая это замечание, в языке программирования С++ можно
написать следующие выражения:
int a[] = {0, 1, 2};
size_t s = sizeof(a); // s = 12
Глава 8. Типы данных, определяемые программистом
119
8.9. Сравнимые типы
Если рассматривать типы как множества значений и операций,
допустимых над этими значениями, то можно определить отно-
шение сравнения между типами. Тип A сравним с типом B, если
тип A содержит все значения типа B и операции, допустимые над
этими значениями. Например, тип
int
сравним с типом
char
. Два
типа называются
сравнимыми
, если каждый из них сравним с
другим. Можно также сказать, что два типа сравнимы, если один
из них может использоваться вместо другого. Очевидно, что
идентичные типы сравнимы. Сравнимы также следующие встро-
енные типы данных:
char
и
signed char
;
short int
,
short
,
signed short int
и
signed short
;
unsigned short int
и
unsigned short
;
signed int
,
signed
и
int
;
unsigned int
и
unsigned
;
long int
,
long
,
signed long int
и
signed long
;
unsigned long int
и
unsigned long
.
Собственно говоря, понятие сравнимых типов и было введено в
язык программирования С по причине существования разных
спецификаторов встроенных типов, по сути описывающих один
тип данных.
Сравнимые типы можно объединять, в результате получается
тип, который называется
композиционным
(composite). Компози-
ционный тип данных не теряет множество значений ни одного из
сравнимых типов и допускает одинаковый набор операций над
этими значениями. Отсюда следует, что сравнимые типы допус-
кают связывание идентификаторов. В этом случае связанные
идентификаторы будут ссылаться на переменную композицион-
ного типа.
Новые типы данных могут объявляться в разных исходных фай-
лах программы. Вопрос состоит в том, каким требованиям долж-
ны удовлетворять объявления одного и того же типа в разных
Часть I. Язык программирования С
120
исходных файлах, чтобы программа работала правильно. Компи-
лятор языка программирования С требует, чтобы такие типы бы-
ли сравнимыми.
Обычно, для того чтобы избежать ошибок кодирования, объявле-
ния типов помещают в заголовочный файл, который затем вклю-
чают в тексты разных исходных файлов командой препроцессора
#include
. Работа с заголовочными файлами рассмотрена в
разд. 9.5
.
Сейчас же перечислим требования, которым должны удовлетво-
рять сравнимые типы, объявляемые в разных исходных файлах
программы:
сравнимые перечисления, структуры и объединения должны
иметь одинаковые имена тегов, если они присутствуют, а так-
же одинаковые имена своих членов, типы которых должны
быть сравнимы;
члены сравнимых перечислений должны иметь одинаковые
значения;
члены сравнимых структур должны быть расположены в оди-
наковом порядке.
Кроме того, в языке программирования C перечисления сравни-
мы с целочисленными типами, которые включают их значения.
В языке программирования C++ перечисления не сравнимы с це-
лочисленными типами.
Теперь рассмотрим сравнимость других сложных типов данных.
Два указателя сравнимы по типу, если они указывают на сравни-
мые типы.
Два массива сравнимы, если сравнимы типы их элементов, и если
оба массива имеют размерности, то эти размерности должны сов-
падать. Отсюда следует, что массив неопределенной длины срав-
ним с массивом любой длины, если сравнимы типы элементов
этих массивов.
Две функции считаются сравнимыми, если сравнимы типы воз-
вращаемых ими значений. Если для функций объявлены прото-