Spec-Zone.ru › Elisp

Целочисленные типы 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API