stddef.h — заголовочный файл стандартной библиотеки языка программирования С, определяющий макросы NULL и offsetof, а также типы ptrdiff_t, wchar_t и size_t.
Включение
Для использования заголовочного файла «stddef.h» в коде на языке C используется директива препроцессора: #include <stddef.h>
Стандарт языка C++ определяет эквивалентный заголовочный файл «cstddef», подключаемый директивой: #include <cstddef>
Пространство имён
Основное отличие «stddef.h» от «cstddef» заключается в том, что в «cstddef» определения типов размещены в пространстве имён . То есть, в C++ определены и вместо size_t и ptrdiff_t.
NULL
Константа препроцессора, обозначающая константный нулевой указатель и определённая одним из следующих способов (в зависимости от компилятора и языка). #define NULL ((void*)0) #define NULL 0 #define NULL 0L
offsetof(type, member)
Макрос препроцессора, определённый стандартом ANSI C и возвращающий значение типа size_tМакрос offsetof() . cppreference.com. Макрос вычисляет смещение в байтах поля структуры или объединения от начала структуры или объединения.
Классическая реализация макроса работала с компиляторами, не проверяющими типы указателей, и основана на получении смещения поля структуры, размещёной в памяти по нулевому адресу: #define offsetof( st, m ) ( (size_t) (& ((st *)0)->m ) ) Нулевой указатель преобразуется к указателю на структуру st. Затем оператор «&» получает адрес поля m указанной структуры.
Современные компиляторы реализуют макрос с помощью встроенных функций. Например, реализация gcc выглядит следующим образом: #define offsetof( st, m ) __builtin_offsetof( st, m ) Использование встроенной функции имеет несколько преимуществ. Например, для кода на C++ не вызывается перегруженный оператор «&».
Макрос позволяет писать код, работающий с разными структурами данных (см. обобщённое программирование). Например, в коде ядра ОС Linux с помощью реализован макрос , получающий указатель на структуру по указателю на её поле: #define container_of( ptr, type, member ) \ ( \ { \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof( type, member ) ); \ } \ )
#include <stddef.h> #include <stdio.h>
int main() { struct car { char brand; char hp; double price; double tmp; } t; //смещение относительно начала. printf("%lu\n", offsetof(struct car, brand)); printf("%lu\n", offsetof(struct car, hp)); printf("%lu\n", offsetof(struct car, price)); printf("%lu\n", offsetof(struct car, tmp));
printf("\n"); //размеры членов структуры printf("%lu\n", sizeof (t.brand)); printf("%lu\n", sizeof (t.hp)); printf("%lu\n", sizeof (t.price)); printf("%lu\n", sizeof (t.tmp));
// размер занимаемый структурой в памяти. printf("sizeof struct = %lu\n", sizeof(struct car));
В реализации используется оператор Оператор typeof() . Документация gcc. gnu.org, не описанный в стандарте языка C. Пример использования макроса . struct my_struct { const char * name; struct list_node list;
extern struct list_node * list_next ( struct list_node * );
void example () { struct list_node * current = /* ... */ while ( current != NULL ) { struct my_struct * element = container_of( current, struct my_struct, list ); printf( "%s\n", element->name ); current = list_next( &element->list );
В примере перебираются элементы связного списка, по указателю на поле list вычисляется указатель на структуру my_struct.
Тип size_t Тип беззнаковый, создан специально для хранения размера объектов любых типов и имеет достаточную для этого разрядностьТип size_t . cppreference.com. Разрядность зависит от платформы: на 32-битных платформах может составлять 32 бита, на 64-битных — 64 бита. Значения этого типа возвращают операторы , и макрос offsetof. Максимальное значение равно (константа из файла «stdint.h»).
Стандарт POSIX определяет знаковый тип (файл «unistd.h» для ОС UNIX или файл «stddef.h» для GNU C). Тип является типом со знаком. Комментарий в файле «sys/types.h» гласит, что используется для подсчёта байт и выявления ошибок, может хранить значения по крайней мере от до .
Тип wchar_t
Тип создан для хранения «широкого символа» (), определён в файлах «stddef.h» и «wchar.h». Разрядность «широкого символа» зависит от реализации компилятора.
Тип ptrdiff_t
Тип создан для хранения разности между двумя указателями. Разрядность типа зависит от платформы и реализации компилятора.
Ссылки ISO/IEC 9899:2011 Черновик стандарта C11. Описание файла «stddef.h» в стандарте «Single UNIX specification 2». Описание файла «cstddef». CPlusPlus.com.
Примечания