|
| Uspecificerede argumenter... med float Fra : Klaus Petersen |
Dato : 13-06-03 15:41 |
|
Hej.
Jeg eksperimenter lidt med funktioner, der har uspecificerede argumenter.
Det virker fint med int, men med float virker det ikke.
Kan nogen se problemet?
<KODE>
#include <stdarg.h>
#include <stdio.h>
class floattest
{
private:
float a;
public:
void test ( float first, ... );
void testint ( int first, ... );
};
void floattest::test ( float first, ... )
{
va_list marker;
this->a = first;
float i;
int j;
j = 1;
va_start ( marker, first );
while ( (i = va_arg ( marker, float )) != -1.0f )
{
printf ("arg. %d = %.3f\n", j, i );
j++;
};
va_end ( marker );
};
void floattest::testint ( int first, ... )
{
va_list marker;
this->a = (float)first;
int i, j;
j = 1;
va_start ( marker, first );
while ( (i = va_arg ( marker, int )) != -1 )
{
printf ("arg. %d = %d\n", j, i );
j++;
};
va_end ( marker );
};
void Test (int cnt, char *tekst, ...) {
char *tmp;
va_list marker;
printf ("count er %d\n", cnt);
printf ("\nher kommer de restende argumenter:\n\n");
va_start (marker, cnt);
while ( (tmp = va_arg (marker, char* )) != NULL) {
printf (tmp);
printf ("\n");
}
va_end (marker);
};
int main(int argc, char* argv[])
{
floattest p;
printf ("Med float:\n\n");
p.test ( 10.5f, 5.0f, 7.021f, -1.0f );
printf ("Med int:\n\n");
p.testint ( 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, -1 );
};
</KODE>
| |
Bertel Brander (13-06-2003)
| Kommentar Fra : Bertel Brander |
Dato : 13-06-03 15:58 |
|
Klaus Petersen wrote:
> Hej.
>
> Jeg eksperimenter lidt med funktioner, der har uspecificerede argumenter.
>
> Det virker fint med int, men med float virker det ikke.
>
> Kan nogen se problemet?
>
> <KODE>
>
> #include <stdarg.h>
> #include <stdio.h>
>
> class floattest
> {
> private:
> float a;
> public:
>
> void test ( float first, ... );
> void testint ( int first, ... );
> };
>
> void floattest::test ( float first, ... )
> {
> va_list marker;
>
> this->a = first;
>
> float i;
> int j;
>
> j = 1;
>
> va_start ( marker, first );
>
> while ( (i = va_arg ( marker, float )) != -1.0f )
> {
> printf ("arg. %d = %.3f\n", j, i );
> j++;
> };
>
> va_end ( marker );
> };
>
> void floattest::testint ( int first, ... )
> {
> va_list marker;
>
> this->a = (float)first;
>
> int i, j;
>
> j = 1;
>
> va_start ( marker, first );
>
> while ( (i = va_arg ( marker, int )) != -1 )
> {
> printf ("arg. %d = %d\n", j, i );
> j++;
> };
>
> va_end ( marker );
> };
>
> void Test (int cnt, char *tekst, ...) {
>
> char *tmp;
>
> va_list marker;
>
> printf ("count er %d\n", cnt);
> printf ("\nher kommer de restende argumenter:\n\n");
>
> va_start (marker, cnt);
>
> while ( (tmp = va_arg (marker, char* )) != NULL) {
> printf (tmp);
> printf ("\n");
> }
>
> va_end (marker);
>
> };
>
>
> int main(int argc, char* argv[])
> {
> floattest p;
>
> printf ("Med float:\n\n");
> p.test ( 10.5f, 5.0f, 7.021f, -1.0f );
>
> printf ("Med int:\n\n");
> p.testint ( 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, -1 );
> };
>
>
> </KODE>
>
floats bliver "promotet" til double når man kalder en funktion med ...
det er det samme der sker med printf.
Så man skal bruge double i va_arg
/b
--
Bertel Brander, author of Wain, a free text editor for programmers:
http://home20.inet.tele.dk/midgaard/program.htm
| |
Klaus Petersen (13-06-2003)
| Kommentar Fra : Klaus Petersen |
Dato : 13-06-03 16:05 |
|
> floats bliver "promotet" til double når man kalder en funktion med ...
> det er det samme der sker med printf.
> Så man skal bruge double i va_arg
Jeps .. det har du ret i. Tak.
| |
Klaus Petersen (14-06-2003)
| Kommentar Fra : Klaus Petersen |
Dato : 14-06-03 10:42 |
|
> floats bliver "promotet" til double når man kalder en funktion med ...
> det er det samme der sker med printf.
> Så man skal bruge double i va_arg
Er det muligt at få va_start til at state før argumentet?
Hvorfor skal den egentlig start efter?
Det kunne være en lidt pænere måde at få det første argument med også.
| |
Bertel Brander (14-06-2003)
| Kommentar Fra : Bertel Brander |
Dato : 14-06-03 13:22 |
|
Klaus Petersen wrote:
>>floats bliver "promotet" til double når man kalder en funktion med ...
>>det er det samme der sker med printf.
>>Så man skal bruge double i va_arg
>
>
> Er det muligt at få va_start til at state før argumentet?
>
> Hvorfor skal den egentlig start efter?
>
> Det kunne være en lidt pænere måde at få det første argument med også.
>
>
Jeg forstår ikke spørgsmålene.
/b
| |
Klaus Petersen (14-06-2003)
| Kommentar Fra : Klaus Petersen |
Dato : 14-06-03 15:02 |
|
> Jeg forstår ikke spørgsmålene.
Så må jeg lige forklare mig nærmere.
Normalt, som jeg har forstået det, bruger man va_start, va_arg og va_end på
følgende måde:
void Test (int cnt, char *tekst, ...) {
char *tmp;
va_list marker;
printf ("count er %d\n", cnt);
printf ("\nher kommer de restende argumenter:\n\n");
va_start (marker, cnt);
while ( (tmp = va_arg (marker, char* )) != NULL) {
printf (tmp);
printf ("\n");
}
va_end (marker);
};
Når du siger va_start til den, skal du angive en af argumenterne til
funktion og va_start vil få va_arg til at pege på argumentet umiddelbart
efter.
Så er det jeg spørger, om man ikke kan få det til at tage det første
argument med, så man ikke er nødt til at behandle det seperat.
| |
Bertel Brander (14-06-2003)
| Kommentar Fra : Bertel Brander |
Dato : 14-06-03 23:22 |
|
Klaus Petersen wrote:
>>Jeg forstår ikke spørgsmålene.
>
>
> Så må jeg lige forklare mig nærmere.
>
> Normalt, som jeg har forstået det, bruger man va_start, va_arg og va_end på
> følgende måde:
>
> void Test (int cnt, char *tekst, ...) {
For at få resten af koden til at passe tror jeg funktionen skulle hedde:
void Test (int cnt, ...) {
>
> char *tmp;
>
> va_list marker;
>
> printf ("count er %d\n", cnt);
> printf ("\nher kommer de restende argumenter:\n\n");
>
> va_start (marker, cnt);
>
> while ( (tmp = va_arg (marker, char* )) != NULL) {
> printf (tmp);
> printf ("\n");
> }
>
> va_end (marker);
>
> };
>
> Når du siger va_start til den, skal du angive en af argumenterne til
> funktion og va_start vil få va_arg til at pege på argumentet umiddelbart
> efter.
Når du bruger va_start skal du angive det sidste faste argument.
>
> Så er det jeg spørger, om man ikke kan få det til at tage det første
> argument med, så man ikke er nødt til at behandle det seperat.
Det kan man ikke hvis man vil lave et portabelt C-program der overholder
C-standarden.
Man kan dog godt være en "anelse" kreativ:
void test(char *arg, ...)
{
char **p = &arg;
while(*p)
{
printf("Arg: %s ", *p);
p++;
}
printf("\n");
}
int main(void)
{
test("First", "Second", "Third", NULL);
test("4", "6", "8", "10", NULL);
return 0;
}
Dette lille program kompiler og kører fint med de tre kompilere som jeg
prøvede det med (BorlandC, Cygwin-GCC og Visual C++), men det er ikke
garanteret at det vil virke med alle kompilere på alle platforme.
Hvis man vil bruge va_ macro'erne kan man gøre sådan:
void test2(char *arg, ...)
{
char *p;
va_list marker;
va_start(marker, arg);
((char *)marker) -= sizeof(arg);
while((p = va_arg(marker, char *)) != NULL)
printf("Arg %s ", p);
printf("\n");
va_end(marker);
}
Bemærk linien:
((char *)marker) -= sizeof(arg);
Det er ikke portabelt, men mine kompilere har ingen problemer.
/b
| |
Klaus Petersen (15-06-2003)
| Kommentar Fra : Klaus Petersen |
Dato : 15-06-03 12:02 |
|
> Det kan man ikke hvis man vil lave et portabelt C-program der overholder
> C-standarden.
Apropros C standarden - kan man hente den på nettet?
Bare i tilfælde at jeg skulle få lyst til at overholde den... :-}
| |
Bertel Brander (15-06-2003)
| Kommentar Fra : Bertel Brander |
Dato : 15-06-03 13:45 |
|
Klaus Petersen wrote:
>>Det kan man ikke hvis man vil lave et portabelt C-program der overholder
>>C-standarden.
>
>
> Apropros C standarden - kan man hente den på nettet?
>
Man kan downloade den sidste draft til C99 gratis, den hedder n2794.pdf,
den er tæt nok på den endelige standard til at den kan bruges, det er
dog en fordel at vide hvad der er nyt i C99, hvis man vil lave C89
programmer.
Man kan købe den officielle C-standard (både C89 og C99) på www.ansi.org
/b
| |
Klaus Petersen (15-06-2003)
| Kommentar Fra : Klaus Petersen |
Dato : 15-06-03 19:19 |
|
> Man kan købe den officielle C-standard (både C89 og C99) på www.ansi.org
Er det rigtigt forstået, at når man overholder standarden kan programmet
compiles af alle compilere? (forudsagt at *de* også overholder standarden)
| |
Bertel Brander (15-06-2003)
| Kommentar Fra : Bertel Brander |
Dato : 15-06-03 22:35 |
|
Klaus Petersen wrote:
>>Man kan købe den officielle C-standard (både C89 og C99) på www.ansi.org
>
>
> Er det rigtigt forstået, at når man overholder standarden kan programmet
> compiles af alle compilere? (forudsagt at *de* også overholder standarden)
>
Ja, et standard-C program kan kompileres af alle standard-C kompilere,
(medmindre programmet gør brug af nogle optionelle features).
Det er ikke sikkert at alle standard-C programmer opfører sig ens efter
at de er kompileret på en anden platform eller med en anden kompiler.
C-standarden nævner f.ex. en række impelementations specifikke ting
f.ex størrelsen på en int eller output fra strftime().
I virkeligheden er det svært at lave et program der gør noget fornuftigt
uden at bruge ting der ligger uden for C-standarden.
Men at følge C-standarden er stadig den bedste metode til at sikre at
programmet vil opføre sig korrekt på andre platforme, og har man en valg
skal man (efter min mening) have en meget god grund til ikke at
overholde standarden.
/b
| |
|
|