Charの署名はインターフェイスの問題ですか?
-
25-09-2019 - |
質問
機能があるとします
void foo(char *)
内部的には、入力をヌル終端バイトのブロックとして扱う必要があります(たとえば、文字列のハッシュ関数です)。私は議論を投げることができました unsigned char*
関数で。宣言を変更することもできます
void foo(unsigned char *)
今、それを考えると char
, signed char
と unsigned char
それは 3つの異なるタイプ, 、これは、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)。
したがって、これは明らかにプログラミングインターフェイスの変更です。
ただし、As char *
, signed char *
と unsigned char *
C言語の正気の実装には、同一の表現とアラインメント要件があり、バイナリインターフェイスは変更されません。
他のヒント
はい、そうです。以前にコンパイルしたクライアントコードはコンパイルされなくなります(または、とにかく新しい警告が生成される可能性が高い)ため、これは壊れた変更です。
「C-上記のいずれでもない」を選択します。
それはあなたが実際に尋ねた質問に対する直接的な答えではありませんが、状況に対する正しい解決策は私にはかなり単純で明白に思えます。あなたは本当に上記のいずれかを使用するべきではありません。
少なくともIMO、あなたはそれ以外の場合は本当に正当な理由があります、あなたの機能は void *
または(できれば) void const *
. 。あなたが探しているのは基本的に不透明なポインターです、そしてそれはまさにそれです void *
提供します。ユーザーは、実装の内部について何も知る必要はありません。他のポインタータイプはに変換されるため void *
暗黙的に、それは既存のコードを破らない数少ない可能性の1つです。
char*は、符号なしのchar*に暗黙的に変換されますか?
- はい - インターフェイスを破っていません
- いいえ - 実装をリークしました
詳細。
いいえ、そうではありません。クライアントコードへの変更は些細なことです(特に警告を避けるためだけの場合)。 char*
と unsigned char*
通話条約ではまったく同じように渡されます。