0

誰かが私にこの振る舞いを説明できますか?

static short nDoSomething(const char* pcMsg, ...)
{
  va_list pvArgument;
  long lTest;
  void* pvTest = NULL;

  va_start(pvArgument, pcMsg);

  pvTest = va_arg(pvArgument, void*);
  lTest  = (long) pvTest;

  va_end(pvArgument);
  return 0;
}

この関数をメインで次のように呼び出すと:

int main(int argc, char* argv[])
 {
   char acTest1[20];
   nDoSomething("TestMessage", 1234567L, acTest1);


  return 0;
}

pvTestのアドレスはlTestにあると思っていたのですが、実は1234567が入っていて…

これはどのように可能ですか?

4

2 に答える 2

1

あなたはここで幸運です。

va_start(pvArgument, pcMsg);

型であると仮定してva_arg(pvArgument,T)、次の可変引数を抽出する準備をします。pcMsgT

後の次の引数pcMsgは、実際にはlong int 1234567; です。しかし、誤って として抽出してvoid *から にキャストlonglTestます。void *システム上の が と同じサイズであることは幸運ですlong

(または、奇妙に不運を意味するかもしれません)

于 2013-07-22T08:33:15.300 に答える
1

コードに未定義の動作が含まれています。標準では、 を使用して抽出さva_argれた型が、渡された型に対応する必要があります (モジュロ cv 修飾子など): a を渡し、 alongを読み取ったvoid*ため、コンパイラが行うことはすべて正しいです。

実際には、ほとんどのコンパイラは型チェックを行わないコードを生成します。あなたのマシン上で同じサイズlongvoid*持っている場合(そしてマシンが線形アドレス指定を持っている場合)、あなたが渡したものはおそらくlong. 2 つのサイズが異なっていても、マシンがリトル エンディアンであり、十分に小さい値を渡すと、同じ値になる可能性があります。しかし、これはまったく保証されていません。

于 2013-07-22T09:00:09.073 に答える