Вопрос

Предположим, у меня есть функция

void foo(char *)

Который, внутренне, необходимо лечить его вход как блок байтов Nul-завершения (скажем, это хеш-функция на струнах). Я мог бы бросить аргумент unsigned char* в функции. Я также мог изменить заявление

void foo(unsigned char *)

Теперь, учитывая, что char, signed char а также unsigned char являются три разных типа, Если бы это состоится изменение интерфейса, при любых разумных определении термина «интерфейс» в C?

(Этот вопрос предназначен для урегулирования обсуждение поднял другой вопрос. У меня есть свое мнение, но не приму ответ до тех пор, пока не подведет как «победитель» голосами других.)

Это было полезно?

Решение

Согласно ISO / IEC 9899: TC3,

  • Вызов функции через экспрессию несовместимого типа - не определенное поведение (6.5.2.2 §9)
  • Совместимые типы функций должны иметь совместимые типы параметров (6.7.5.3 §15)
  • Совместимые типы указателей должны указывать на совместимые типы (6.7.5.1 §2)
  • char, signed char а также unsigned char являются разными основными типами (6.2.5 §14) и, таким образом, несовместимы (6.2.7 §1), что также явно упомянуто в сноске 35 на стр. 35

Так что да, это явно изменение к интерфейсу программирования.

Однако как char *, signed char * а также unsigned char * будут иметь одинаковые представления и требования к выравниванию в любом вменяемости языка C, двоичный интерфейс останется без изменений.

Другие советы

Да это так. Клиентский код, который ранее составленный ранее скомпилирован, больше не сознает (или в любом случае, скорее всего, будет генерировать новые предупреждения), так что это разрывное изменение.

Я выбираю «C - ничего из вышеперечисленного».

Хотя это не прямой ответ на вопрос, который вы на самом деле спросили, правильное решение ситуации кажется довольно простым и очевидным для меня: вы не должны использовать любой из вышеперечисленных.

По крайней мере, IMO, у вас есть действительно веские причина для выполнения иначе, ваша функция должна принять void * или (желательно) void const *. Отказ Что вы ищете, это в основном непрозрачный указатель, и это именно то, что void * предоставляет. Пользователю не нужно ничего знать о внутренних органах вашей реализации, и поскольку любой другой тип указателя преобразуется в void * Неявно, это одно из немногих возможностей, которые либо не нарушают существующий код.

Разработает ли CHAR *, неявно преобразуется в беззнаковие *?

  • Да - вы не сломали свой интерфейс
  • Нет - вы просочились внедрение
    подробности.

Нет, нет. Любое изменение клиентского кода является тривиальным (особенно если это просто чтобы избежать предупреждения), а на практике в значительной степени любая реализация C вы обнаружите, что вам даже не нуждается в повторной компиляции, потому что указатели на char* а также unsigned char* будет передано точно так же, как в призвающейся конвенции.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top