Открыть главное меню

stddef.h

ВключениеПравить

Для использования заголовочного файла «stddef.h» в коде на языке C используется директива препроцессора:

#include <stddef.h>

Стандарт языка C++ определяет эквивалентный заголовочный файл «cstddef», подключаемый директивой:

#include <cstddef>

Пространство имёнПравить

Основное отличие «stddef.h» от «cstddef» заключается в том, что в «cstddef» определения типов размещены в пространстве имён std. То есть, в C++ определены std::size_t и std::ptrdiff_t вместо size_t и ptrdiff_t.

NULLПравить

Константа #define препроцессора, обозначающая константный нулевой указатель и определённая одним из следующих способов (в зависимости от компилятора и языка).

#define NULL ((void*)0)
#define NULL 0
#define NULL 0L

offsetof(type, member)Править

Макрос препроцессора, определённый стандартом ANSI C и возвращающий значение типа size_t[1]. Макрос вычисляет смещение в байтах поля структуры или объединения от начала структуры или объединения[2].

Классическая реализация макроса работала с компиляторами, не проверяющими типы указателей, и основана на получении смещения поля структуры, размещёной в памяти по нулевому адресу:

#define offsetof( st, m ) ( (size_t) (& ((st *)0)->m ) )

Нулевой указатель преобразуется к указателю на структуру st. Затем оператор «&» получает адрес поля m указанной структуры.

Современные компиляторы реализуют макрос с помощью встроенных функций. Например, реализация gcc выглядит следующим образом[3]:

#define offsetof( st, m ) __builtin_offsetof( st, m )

Использование встроенной функции имеет несколько преимуществ. Например, для кода на C++ не вызывается перегруженный оператор «&»[4].

Макрос offsetof() позволяет писать код, работающий с разными структурами данных (см. обобщённое программирование). Например, в коде ядра ОС Linux с помощью offsetof() реализован макрос container_of(), получающий указатель на структуру по указателю на её поле[5]:

#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[31];
		char hp[30];
		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()[6], не описанный в стандарте языка C. Пример использования макроса container_of().

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 беззнаковый, создан специально для хранения размера объектов любых типов и имеет достаточную для этого разрядность[7]. Разрядность зависит от платформы: на 32-битных платформах может составлять 32 бита, на 64-битных — 64 бита. Значения этого типа возвращают операторы sizeof(), _Alignof() и макрос offsetof. Максимальное значение равно SIZE_MAX (константа #define из файла «stdint.h»).

Стандарт POSIX определяет знаковый тип ssize_t (файл «unistd.h» для ОС UNIX или файл «stddef.h» для GNU C). Тип ssize_t является типом size_t со знаком. Комментарий в файле «sys/types.h» гласит, что ssize_t используется для подсчёта байт и выявления ошибок, может хранить значения по крайней мере от -1 до SSIZE_MAX.

Тип wchar_tПравить

Тип wchar_t создан для хранения «широкого символа» (англ. wide character), определён в файлах «stddef.h» и «wchar.h». Разрядность «широкого символа» зависит от реализации компилятора.

Тип ptrdiff_tПравить

Тип ptrdiff_t создан для хранения разности между двумя указателями. Разрядность типа ptrdiff_t зависит от платформы и реализации компилятора.

СсылкиПравить

ПримечанияПравить

  1. Макрос offsetof() (англ.). cppreference.com
  2. offsetof reference. MSDN. Дата обращения 19 сентября 2010.
  3. Описание макроса offsetof(). Документация gcc. gnu.org. Free Software Foundation. Дата обращения 19 сентября 2010.
  4. What is the purpose and return type of the __builtin_offsetof operator?. Дата обращения 20 октября 2012.
  5. Greg Kroah-Hartman (англ.). Макрос container_of(). Журнал «Linux Journal» (Июнь 2003). Дата обращения 19 сентября 2010.
  6. Оператор typeof(). Документация gcc. gnu.org
  7. Тип size_t. cppreference.com