/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
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


Søg
Reklame
Statistik
Spørgsmål : 177580
Tips : 31968
Nyheder : 719565
Indlæg : 6409081
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste