1: void f(mystruct *a)
2: void f(const mystruct *a)
関数シグネチャを 1->2 から変更すると、C の API/ABI が壊れますか?
2→1に変えてみたら?
1: void f(mystruct *a)
2: void f(const mystruct *a)
関数シグネチャを 1->2 から変更すると、C の API/ABI が壊れますか?
2→1に変えてみたら?
C99 標準 6.2.5/26 の「タイプ」から:
互換性のある型の修飾または非修飾バージョンへのポインターは、同じ表現およびアライメント要件を持たなければなりません。
そのため、ABI/API は 1 から 2 に移行しても影響を受けません。(API は変更されません。これは、const 修飾されていない型へのポインターが、その型の const 修飾されたバージョンへのポインターに変換される可能性があるためです - 6.3 .2.3/2「変換 - ポインター」)。
ただし、2 から 1 に変更すると、const オブジェクトへのポインターを非 const オブジェクトへのポインターに暗黙的に変換できないため、API が変更されます。次のコードは、バージョン 2 ではコンパイルできますが、バージョン 1 ではコンパイルできません。
static const mystruct foo;
f(&foo);
1->2 になる前の 2 つの回答に記載されている以外は、API が壊れる場合と壊れない場合があります。これはベース タイプによって異なりますmystruct
。名前が示すもの以外が配列型にmystruct
なると、 API が壊れます。typedef
typedef struct toto mystruct[1];
そんな野獣に
mystruct A;
f(&A);
への呼び出しはf
、API の変更前は有効ですが、その後は無効になります。
APIの意味によって異なります。コンパイル時に、 aT *
は常に暗黙的に a に変換される場合がありますconst T *
(注: Jens Gustedt が回答で指摘した例外は別として! )。逆は正しくありません。aconst T *
は暗黙的に aT *
に変換されないため、コンパイラ エラーを回避するには常にキャストが必要です。そのため、インターフェイス関数の宣言をconst
から non-const
に変更すると、クライアント コードはコンパイルされません。(すべての呼び出しで -ness をキャストするだけでこれconst
を回避できますが、動作が定義されておらず、独自のインターフェイスの契約を破ったことを意味するため、絶対に避けられない場合を除き、そうすることは避ける必要があります)。
ビット レベル (つまり ABI) では、ポインタまたはオブジェクトの表現に違いはありません。const
ただし、これらの表現を処理するマシンコードを生成するときにマークされているものに基づいて、コンパイラが最適化/仮定を行わないというわけではありません。-ness を捨てるとconst
、これらの仮定が成り立たなくなり、コードが壊れる可能性があります。
ABIに関する限り、いいえ、const
コンパイル段階でエラーに影響を与えるだけです。コンパイルされたオブジェクト ファイルには、const 指定子の残りがあってはなりません。
OLD: void f(mystruct *a)
NEW: void f(const mystruct *a)
ABI: outパラメーターの場合a
、古いアプリが壊れる可能性があります。
API:互換性があるようです。
OLD: void f(const mystruct *a)
NEW: void f(mystruct *a)
ABI:関数f
は、古いアプリでは変更されていないはずのパラメーター値を変更しようとする場合があります。
API:コンパイラ エラー。
編集 (1):これは、パラメーターを非 const に変更するよりもコンパイラ エラーを示す例です。
ライブラリ header.h:
struct mystruct {
int f;
};
void f(struct mystruct *a);
応用:
int main()
{
const struct mystruct x = {1};
f(&x);
return 0;
}
コンパイラ エラー ( gcc -Werror app.c
):
error: passing argument 1 of ‘f’ discards qualifiers from pointer target type
note: expected ‘struct mystruct *’ but argument is of type ‘const struct mystruct *’
C ではデフォルトで警告ですが、C++ ではエラーです。-Werror
そのため、オプションでコンパイルされた C ベースのアプリと、G++ を使用してコンパイルされた C++ベースのアプリが壊れます。