Avatar billede clone Nybegynder
23. november 2001 - 00:21 Der er 12 kommentarer

Define af funk. med ukendt antal parametre, hvordan?

Jeg har skrevet et funktion, som tager et ukendt antal parametre. Prototypen er vist herunder:

void Test(char ch, ...)

Den første parameter er altså en char, og de efterfølgende er ukendte.

Spørgsmål:
Hvordan laver jeg en define til en sådan funktion?

Løsningen skal ligne nedenstående:
#ifdef DEBUG
void Test2(char ch, char ch2)
#define TEST2(a, b) Test2(a, b)
#else
#define TEST(a, b)
#endif

Den opmærksomme ekspert har nok opdaget, at jeg er interesseret i at lave en funktion, som KUN er defineret i debug mode. Men hvordan laver man en sådan define til en funktion, som tager et ukendt antal parametre?
Avatar billede clone Nybegynder
23. november 2001 - 00:22 #1
Undskyld... det skulle naturligvis stå #define TEST2(a, b) nederst - ikke #define TEST(a, b).
Avatar billede jespernaur Nybegynder
23. november 2001 - 00:32 #2
Du skal benytte va_start, va_arg og va_end, som fx beskrevet i

http://www.mkssoftware.com/docs/man3/va_start.3.asp

og omkringliggende øer.

Mvh
Jesper Naur
Avatar billede jpk Nybegynder
23. november 2001 - 09:05 #3
Funktionen kan implementeres som her:
(Denne beregner et gennemsnit af alle tallene)

Du behøver ikke kalde funktionerne forskellige navne, hvis det du altså ønsker blot er en anden implementation af funktionen...

#ifdef DEBUG
int average( int first, ... )
{
  int count = 0, sum = 0, i = first;
  va_list marker;

  va_start( marker, first );    /* Initialize variable arguments. */
  while( i != -1 )
  {
      sum += i;
      count++;
      i = va_arg( marker, int);
  }
  va_end( marker );              /* Reset variable arguments.      */
  return( sum ? (sum / count) : 0 );
}
#else
// anden implemention
#endif
Avatar billede soepro Nybegynder
23. november 2001 - 10:27 #4
Avatar billede soepro Nybegynder
23. november 2001 - 10:35 #5
Hvis du i debug vil køre en anden funktion men med samme parametre, skal du lave en wrapper, dvs. i princippet bare overloade din Test funktion:

#ifdef DEBUG
  void Test(char a, char b) { Test2(a, b); };
#endif

Den originale Test funktion lægger du i en .cpp unit - debug versionen i en anden:

// orginale test cpp
#ifndef DEBUG

  : // Hele funktionen

#endif

// Debug test cpp
#ifdef DEBUG

  : // Hele funktionen

#endif

Hermed kan dit projekt se ens ud hver gang, og kun test modulets originale og debug cpp skal omkompileres for at du kører debug. (Husk at de fleste compilerer ikke automatisk laver ny MAKE, når du ændrer projektet faste declares.)
Avatar billede clone Nybegynder
25. november 2001 - 00:00 #6
Det jeg vil opnå er, at funktionen KUN eksisterer i debug-mode. Altså: i release-mode eksisterer funktionen slet ikke - det er derfor jeg vil lave en #define af funktionen.

Følgende programudsnit illustrerer problemstillingen:

#ifdef DEBUG
void Dummy(int x)
{
  printf(\"Debug mode - tallet er: %d\\n\", x);
}
#define DUMMY(a) Dummy(a)
#else
#define DUMMY(a)
#endif

void main()
{
  DUMMY(10);
}

Ovenstående vil i debug-mode udskrive teksten: \"Debug mode - tallet er: 10\". I release-mode vil det IKKE blive udskrevet noget, da funktionen Dummy() IKKE bliver kaldt (den eksisterer jo ikke i release-mode).

Ovenstående eksempel virker perfekt. Problemet er bare: hvordan laver man en define af en funktion med et variabelt antal parametre?
Jeg har ladet mig fortælle at det ikke kan lade sig gøre, men det har jeg ærlig talt lidt svært ved at tro på.
Avatar billede jpk Nybegynder
25. november 2001 - 14:12 #7
Hvorfor laver du ikke noget som understående, således at hvis der kompileres i release, findes kun en stub?

void Dummy(int x, ...)
{
  #ifdef DEBUG
  printf(\"Debug mode - tallet er: %d\\n\", x);
  // Do whatever you have to do...
  #endif
}
Avatar billede clone Nybegynder
25. november 2001 - 18:41 #8
Jeg vil helst undgå at lave et funktionskald til en funktion som ikke laver noget. Jeg ved godt, at et ekstra funktionskald engang i mellem ikke er det der trækker tænder ud, men det virker alligevel sjusket. Desuden drejer det sig om ca. 10.000 ekstra funktionskald i mit tilfælde - og det vil jeg meget gerne undgå!
Avatar billede clone Nybegynder
25. november 2001 - 18:43 #9
Jeg vil også helst undgå altid at skulle skrive

#ifdef DEBUG
Dummy(10);
#endif

alle de steder i koden, hvor jeg anvender debug-funktionen.

Avatar billede clone Nybegynder
25. november 2001 - 18:44 #10
... men jeg må nok indse, at det ikke kan lade sig gøre. øv.
Avatar billede jpk Nybegynder
26. november 2001 - 08:09 #11
Hvad så med at bruge ASSERT(Dummy(10)); // Dummy skal returnere en boolean

ASSERT\'s udføres ikke i release!
Avatar billede soepro Nybegynder
26. november 2001 - 08:43 #12
Jeg mener også du kan \"overloade\" #define, dvs. lave et antal (men ikke udbegrænset) varianter af din debug funktion:

#define DUMMY(a) Dummy(a)
#define DUMMY(a, b) Dummy(a, b)

osv.

Din Dummy() funktion kan du stadig definere som

void Dummy(a, ...);
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester