8
1: void f(mystruct *a)
2: void f(const mystruct *a)

関数シグネチャを 1->2 から変更すると、C の API/ABI が壊れますか?
2→1に変えてみたら?

4

5 に答える 5

5

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);
于 2011-02-22T21:08:15.307 に答える
4

1->2 になる前の 2 つの回答に記載されている以外は、API が壊れる場合と壊れない場合があります。これはベース タイプによって異なりますmystruct。名前が示すもの以外が配列型にmystructなると、 API が壊れます。typedef

typedef struct toto mystruct[1];

そんな野獣に

mystruct A;
f(&A);

への呼び出しはf、API の変更前は有効ですが、その後は無効になります。

于 2011-02-22T22:39:57.747 に答える
3

APIの意味によって異なります。コンパイル時に、 aT *は常に暗黙的に a に変換される場合がありますconst T *(注: Jens Gustedt が回答で指摘した例外は別として! )。逆は正しくありません。aconst T *は暗黙的に aT *に変換されないため、コンパイラ エラーを回避するには常にキャストが必要です。そのため、インターフェイス関数の宣言をconstから non-constに変更すると、クライアント コードはコンパイルされません。(すべての呼び出しで -ness をキャストするだけでこれconstを回避できますが、動作が定義されておらず、独自のインターフェイスの契約を破ったことを意味するため、絶対に避けられない場合を除き、そうすることは避ける必要があります)。

ビット レベル (つまり ABI) では、ポインタまたはオブジェクトの表現に違いはありません。constただし、これらの表現を処理するマシンコードを生成するときにマークされているものに基づいて、コンパイラが最適化/仮定を行わないというわけではありません。-ness を捨てるとconst、これらの仮定が成り立たなくなり、コードが壊れる可能性があります。

于 2011-02-22T20:48:23.100 に答える
2

ABIに関する限り、いいえ、constコンパイル段階でエラーに影響を与えるだけです。コンパイルされたオブジェクト ファイルには、const 指定子の残りがあってはなりません。

于 2011-02-22T20:47:41.227 に答える
0
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++ベースのアプリが壊れます。

于 2011-09-01T20:50:57.307 に答える