Это подпись CHAR интерфейсной проблемы?
-
25-09-2019 - |
Вопрос
Предположим, у меня есть функция
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*
будет передано точно так же, как в призвающейся конвенции.