Целочисленные типы C
Ниже приведены рекомендации по использованию целочисленных типов в исходном коде Emacs на языке C. Иногда эти рекомендации противоречат друг другу; руководствуйтесь здравым смыслом.
- Избегайте произвольных ограничений. Например, избегайте
int len = strlen (s);, если только длинаsпо другим причинам не должна укладываться в диапазонint. -
Не предполагайте, что переполнение знаковой целочисленной арифметики приводит к циклическому переходу через границу диапазона. Для целевых платформ Emacs это уже неверно: на практике переполнение знакового целого имеет неопределённое поведение и может вызвать дамп памяти или даже привести к нелогичной работе более раннего или последующего кода. Переполнение беззнакового целого надёжно приводит к циклическому переходу по модулю степени двойки, если типы всех операндов беззнаковые и имеют ширину не менее
unsigned int. - Используйте макросы из
<stdckdint.h>для проверки переполнения целых чисел или надёжной реализации арифметики с циклическим переходом через границу диапазона для целочисленных типов, которые являются знаковыми или имеют меньшую ширину, чемunsigned int. Хотя<stdckdint.h>был стандартизирован только в C23, на платформах без поддержки C23 Emacs предоставляет внутреннюю резервную замену. Избегайте сложных аргументов для его макросовckd_add,ckd_subиckd_mul, поскольку резервные макросы могут вычислять аргументы более одного раза. - Предпочитайте знаковые типы беззнаковым, поскольку совместное использование знаковых и беззнаковых типов усложняет понимание кода. Многие другие рекомендации предполагают использование знаковых типов; в более редких случаях, когда нужны беззнаковые типы, могут применяться аналогичные рекомендации для их беззнаковых аналогов (например,
size_tвместоptrdiff_tилиuintptr_tвместоintptr_t). - Для кодов символов Emacs в диапазоне 0 .. 0x3FFFFF предпочитайте
int. В более общем случае предпочитайтеintдля целых чисел, которые заведомо находятся в диапазонеint, например для счётчиков столбцов экрана. - Для размеров, то есть целых чисел, ограниченных максимальным размером любого отдельного объекта C или максимальным количеством элементов в любом массиве C, предпочитайте
ptrdiff_t. Это соответствует общему предпочтению Emacs в пользу знаковых типов. Использованиеptrdiff_tограничивает размер объектовPTRDIFF_MAXбайтами, однако более крупные объекты всё равно вызвали бы проблемы, поскольку нарушили бы вычитание указателей, поэтому это не накладывает произвольного ограничения. - Избегайте
ssize_t, кроме случаев взаимодействия с низкоуровневыми API, имеющими ограничения, связанные сssize_t. Хотя на типичных платформах этот тип эквивалентенptrdiff_t, иногдаssize_tимеет меньшую ширину, поэтому его использование в вычислениях, связанных с размерами, может привести к переполнению. Кроме того,ptrdiff_tболее распространён и лучше стандартизирован, имеет стандартные форматыprintfи лежит в основе внутренней проверки переполнения размеров в Emacs. При использованииssize_tучитывайте, что POSIX требует поддержки только значений в диапазоне −1 ..SSIZE_MAX. - Обычно предпочитайте
intptr_tдля внутреннего представления указателей или целых чисел, ограниченных только количеством объектов, которые могут существовать в любой момент времени, либо общим количеством выделяемых байтов. Однако для представления арифметики указателей, которая может пересекать границы страниц, предпочитайтеuintptr_t. Например, на машине с 32-разрядным адресным пространством массив может пересекать границу 0x7fffffff/0x80000000, что приведёт к переполнению целого числа при прибавлении 1 к(intptr_t) 0x7fffffff. - Для представления значений, преобразуемых в fixnum Emacs Lisp или из него, предпочитайте определённый в Emacs тип
EMACS_INT, поскольку арифметика с fixnum основана наEMACS_INT. - Для представления системного значения (например, размера файла или количества секунд, прошедших с начала эпохи) предпочитайте соответствующий системный тип (например,
off_t,time_t). Не предполагайте, что системный тип является знаковым, если это предположение не заведомо безопасно. Например, хотяoff_tвсегда является знаковым,time_tне обязательно таков. - Для представления значений, которые могут быть любым знаковым целым числом в машинном диапазоне, предпочитайте
intmax_t. Функция из семействаprintfможет вывести такое значение, используя формат вроде"%"PRIdMAX. - Для представления значений, которые могут выходить за пределы машинного диапазона, предпочитайте целые числа Emacs — fixnum или bignum. Хотя низкоуровневый код напрямую использует GMP для повышения эффективности, на более высоких уровнях абстракции целые числа Emacs обычно удобнее.
- Для логических значений предпочитайте
bool,falseиtrue. Использованиеboolможет сделать программы более понятными и немного быстрее, чем использованиеint. Также допустимо использоватьint,0и1, однако этот старый стиль постепенно выходит из употребления. При использованииboolучитывайте ограничения заменяющей реализацииbool. В частности, битовые поля для логических значений должны иметь типbool_bf, а неbool, чтобы они работали корректно даже при компиляции Objective C стандартным GCC. - В битовых полях предпочитайте
unsigned intилиsigned intвместоint, посколькуintменее переносим: он может быть как знаковым, так и беззнаковым. Однобитовые битовые поля должны иметь типunsigned intилиbool_bf, чтобы их значения были равны 0 или 1.
Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/C-Integer-Types.html