Является ли подпись char проблемой интерфейса? - PullRequest
4 голосов
/ 23 октября 2010

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

void foo(char *)

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

void foo(unsigned char *)

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

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

Ответы [ 5 ]

4 голосов
/ 23 октября 2010

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

3 голосов
/ 23 октября 2010

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

2 голосов
/ 23 октября 2010

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

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

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

0 голосов
/ 23 октября 2010

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

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

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

...