3

構造体へのポインターを符号付きの値に型キャストして、さまざまな種類のエラーを返すことはできますか? C標準はこれを許可していますか、それとも未定義の動作です。

typedef enum lError
{
  l_OK = 0,
  l_ERROR = -1,
  l_ABORT = -2,
  l_HALT = -3
}L_STATUS;


typedef struct dataCards
{
  int card1;
  int card2;
  char flag;
}DATACARD;

DATACARD dataCardG;

DATACARD *getCard(int i)
{
  if(i == 1)
    return &dataCardG;
  else if (i == 2)
    return (DATACARD *)l_ERROR;
  else if (i==3)
    return (DATACARD *)l_ABORT;
  else
   return (DATACARD *)l_HALT;

}

int main ()
{
  DATACARD *ptr = NULL;

  ptr = getCard(3);
  if(ptr < (DATACARD *) 1)   /* Is this allowed or undefined behaviour */
    printf("Card failed\n");

}

この条件を機能させるにはどうすればよいですか?

4

3 に答える 3

4

C 標準ではこれを「許可」していますが、サポートしていません。つまり、これを試した場合に発生する動作は定義されていません。C 実装も、これを試した場合に発生する動作を定義していない可能性があります。

こんなことしないで。

実際のオブジェクトを作成することで、これを合法的に機能させることができます。

DATACARD okay, error, abort, halt

#define Okay  (&okay)
#define Error (&error)
#define Abort (&abort)
#define Halt  (&halt)

DATACARDが大きく、これらの余分なオブジェクトのためにスペースを無駄にしたくない場合は、他の手法を利用できます。多くの場合、 のようなルーチンは、エラーの場合getCardに戻りNULL、エラー コードを格納する場所を指す追加のパラメーターなど、別のメカニズムを介してエラー コードを提供するように定義されます。

于 2013-10-02T14:25:37.707 に答える
3

UNIX の sbrk() 関数は、特定の状況を示すポインタ値として -1 を返すという点で、この動作に依存しています。したがって、C標準はそれが機能することを保証していませんが....機能します。

ただし、値を比較する場合は、常にポインターを整数型にキャストします。その逆ではありません。これにより、64 ビット システムでのビット幅の問題が回避され、署名されたコンテキストで処理を行うことが保証されます。

于 2013-10-02T14:26:59.897 に答える
0

これは未定義の動作です。

仕様 (以下) は少し長いですが、重要なのは のgetCard()ような値を返すことです(DATACARD *) some_int。負である可能性はありませんsome_int。0 以外の任意の整数であり、それでも問題が発生する可能性があります。戻り値は NULL 以外の実際の既存の変数に基づいていない可能性があるため(DATACARD *)、そのような比較は未定義です。

@Eric Postpischil を使用することをお勧めします。

DATACARD okay, ...
#define Okay  (&okay)

さらに、(DATACARD *) -1必ずしも結果が「負の」ポインタになるとは限りません。ポインターが署名されているか、署名されていないか、またはそのいずれかであるかどうかを確認する C 仕様は見つかりませんでした。(仕様が存在する可能性があります。)-1は確かに負ですが、そのような派生ポインターの符号は確かではありません。

C11dr 6.5.8 5 "2 つのポインターを比較すると、結果は、指しているオブジェクトのアドレス空間内の相対位置によって異なります。オブジェクト型への 2 つのポインターが両方とも同じオブジェクトを指している場合、またはオブジェクトが指している場合同じ集約オブジェクトのメンバーです...その他のすべて場合、動作は未定義です。」

于 2013-10-02T20:26:49.277 に答える