Является ли подпись char проблемой интерфейса?

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

void foo(char *)

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

void foo(unsigned char *)

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

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

5 ответов

Решение

Согласно 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, двоичный интерфейс останется неизменным.

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

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

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

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

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

Преобразует ли символ * неявно в символ * без знака?

  • Да - вы не сломали свой интерфейс
  • Нет - вы слили реализацию
    подробности.
Другие вопросы по тегам