2009-08-13 12 views
2

Ich habe eine Klasse nicht-statische Elementfunktion, und es hat variable Argumente, Ich kompiliere auf Visual Studio 2005 mit der 64-Bit-Laufzeit auf 64-Bit-Windows.x64 va_list in Visual Studio 2005

void Class::Foo(void* ptr,...) 
{ 
    va_list args; 
    va_start(args,ptr); 
    float f=va_arg(args,float); 
    va_end(args) 
} 

Ich erwarte einen Float, ich übergebe einen Schwimmer an die Funktion. Aber wenn ich debugge - ich bekomme nicht den Float, den ich bestanden habe. Tatsächlich - es wird von der Funktion als 64-Bit-Double empfangen! Ich muss dies tun:

double d=va_arg(args,double); 
float f=(float)d; 

Jetzt weiß ich Win64 mag Parameter in Registern übergeben, und wirft schwimmt, wenn er dies tut, sollte kein va_list immer auf dem Stapel sein?

Nach most references sollte ich nur einen sauberen Stapel voller der übergebenen Parameter haben.

Meine Frage ist: ist das richtige Verhalten oder ein Fehler? Und wenn es ein Fehler ist, ist es mein Fehler oder Microsoft?

Ich habe die definiert WIN64 und _M_AMD64, und WIN32 ist nicht definiert.

Antwort

1

Ich habe nicht den C++ Standard hier, aber es folgt dem C-Standard in dieser Angelegenheit. C99, 6.5.2.2p7 sagt

Wenn der Ausdruck, der die genannte Funktion hat einen Typ bezeichnet, die einen Prototyp enthält, die Argumente implizit konvertiert, wie durch Zuordnung zu den Typen der entsprechende Parameter, wobei der Typ jedes Parameters die unqualifizierte Version seines deklarierten Typs ist. Die Ellipsenschreibweise in einem Funktionsmusterprototyp-Deklarator bewirkt, dass die Konvertierung des Argumenttyps nach dem letzten deklarierten Parameter stoppt. Die Standardargument-Promotionen sind , die für nachfolgende Argumente ausgeführt werden.

Also für Ihre Float-Argument, "Standard-Argument Promotions" durchgeführt werden. Diese werden in p6 definiert als

Wenn der Ausdruck, der die aufgerufenen Funktion bezeichnet einen Typ aufweist, der kein Prototyp umfassen, die ganzzahlige aktionen auf jedem Argument durchgeführt werden, und die Argumente, die Art haben Float wird zum Double befördert. Diese heißen das Standardargument Promotionen. [...]

Also werden alle Floats in Doppel umgewandelt, wenn sie an eine Ellipse übergeben werden. VS entspricht offenbar in dieser Hinsicht, und der Fehler ist in Ihrem Code, der float in va_arg nicht verwenden sollte.

+0

Ich denke, das ist richtig. Obwohl es im C++ - Standard nichts über "Standard-Argument-Promotions" gibt, glaube ich, dass der C-Standard zutrifft.Wie ich es verstehe, besagt der von Ihnen zitierte Text, dass ein Argument, das an eine Variable-Argument-Funktion übergeben wird, nicht prototyped ist (da Sie die Typen nicht prototypieren können, wenn sie variabel sind), werden sie immer zum größten relevanten Typ hochgestuft. int oder doppelt. Odd Verhalten denke ich - aber anscheinend sind dies die Regeln. – Roderick