PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : leere C-Makros funktionieren nicht richtig



nobody0
27-09-2004, 10:54
Zum Debuggen benutze ich ein mc_debug-Makro:



// Debug messages for user and kernel space (if DeBuG is defined, else do nothing).
// Preparation because ANSI-/ISO-C99 does not know __FUNCTION__ (gcc feature).
# ifndef __FUNCTION__
# define __FUNCTION__ __func__
# endif
# if defined(DeBuG) || defined(DEBUG)
# ifdef __KERNEL__
# define mc_DEBUG(fmt, args...) { (void)printk(KERN_EMERG "mc_DEBUG: \"%s\", \"%s\", line %d: ", \
__FILE__, __FUNCTION__, __LINE__); (void)printk(KERN_EMERG fmt, ## args); }
# else
# define mc_DEBUG(fmt, args...) { (void)fprintf(stderr, "mc_DEBUG: \"%s\", \"%s\", line %d: ", \
__FILE__, __FUNCTION__, __LINE__); (void)fprintf(stderr, fmt, ## args); }
# endif
# else
# define mc_DEBUG(fmt, args...)
# endif

// same with debug level
# if defined(DeBuG) || defined(DEBUG)
# define mc_debug(debug_level, fmt, args...)\
if (debug_level >= DEBUG_LEVEL)\
{mc_DEBUG(fmt, ##args);}
# else
# define mc_debug(debug_level, fmt, args...)
# endif


und gelegentlich brauche ich Hilfsvariablen zum Debuggen:



#define DeBuG
#define DEBUG_LEVEL 2

#if defined (DeBuG) and (DEBUG_LEVEL<2)
unsigned long int uli_time = time(NULL); // start time
#endif

mc_debug (1, "time marker 1; start for ic=%d, difftime=%ld\n", ic, time (NULL) - uli_time);


Aber damit habe ich das Problem, dass wenn DEBUG_LEVEL gleich 1 ist, dass dann der gcc diese Variable vermißt und error meldet, obwohl das Debug-Makro doch zu einer leeren Anweisung (d. h. in einer Zeile steht nur ein Semikolon, das hinter das Makro im Sourcecode steht) expandiert wird.
Was mache ich da falsch oder macht der gcc da etwas falsch? :confused:

wraith
27-09-2004, 11:58
Wie lautet denn jetzt die Fehlermeldung genau?
Das Problem ist doch, daß die Zeile unsigned long int uli_time = time(NULL); zwar korrektes C++ ist, aber kein korrektes C (wenn es sich hier um eine globale Variable handelt).
Wenn DEBUG_LEVEL also 1 ist, dann gibt es einen Compiler-Fehler.

nobody0
27-09-2004, 20:43
Die Fehlermeldung ist:

analy4.c: In function `extrapol_nn1':
analy4.c:1619: error: `uli_time' undeclared (first use in this function)
analy4.c:1619: error: (Each undeclared identifier is reported only once
analy4.c:1619: error: for each function it appears in.)

D. h. die nicht angelegte Variable wird vermißt, obwohl die Makros, die sie verwenden, zu nichts (d. h. leere Anweisung) expandiert werden.
Und wieso sollte
unsigned long int uli_time = time(NULL);
C++ sein? time(NULL) hat als return type time_t, so dass der return value von time_t nach unsigned long int gecastet wird.

nobody0
27-09-2004, 20:55
Also nun habe ich des Rätsels Lösung: Das zweite if in dem Block mit mc_debug ist ein Compiler-if und kein Präprozessor-if; dadurch werden alle Parameter gebraucht und das Makro nicht zu nichts expandiert.

Richtig sieht das Makro nun so aus:



# if ( defined(DeBuG) || defined(DEBUG) ) && (debug_level >= DEBUG_LEVEL)
# define mc_debug(debug_level, fmt, args...) mc_DEBUG(fmt, ##args)
# else
# define mc_debug(debug_level, fmt, args...)
# endif


Damit funktioniert es nun :)
Ein bischen erstaunlich ist aber, dass debug_level schon in der Zeile vor dem define mc_debug (das ja erst debug_level definiert) bekannt ist, auch wenn ich vor dem block ein undef debug_level setze. Das muß ein gcc feature sein, meine ich.

wraith
27-09-2004, 21:22
Und wieso sollte
unsigned long int uli_time = time(NULL);
C++ sein? time(NULL) hat als return type time_t, so dass der return value von time_t nach unsigned long int gecastet wird.
Das ist nicht das Problem, die Zeile ist, wenn global (was in dem Codeschnispel nicht 100% zu sagen ist), kein korrektes C, weil time(NULL) keine "constant expression" ist.
Genauso wenig geht in C (auf globaler Ebene)


int i = 0;
int k = i;

Schluckt das dein Compiler?

Zum nachlesen irgendwo im Standard unter 6.7.8 Initialization.

nobody0
27-09-2004, 23:30
Das ist nicht das Problem, die Zeile ist, wenn global (was in dem Codeschnispel nicht 100% zu sagen ist), kein korrektes C, weil time(NULL) keine "constant expression" ist.
Genauso wenig geht in C (auf globaler Ebene)


int i = 0;
int k = i;

Schluckt das dein Compiler?

Zum nachlesen irgendwo im Standard unter 6.7.8 Initialization.

Das betrifft nur arrays, aber nicht einzelne Variblen.
Ich kenne keinen C-Compiler, der deine Beispiele nicht problemlos akzeptiert; da ist doch kein Problem.

Inzwischen habe ich herausbekommen, dass mein obiger Code nicht richtig funktioniert, weil der Präprozessor fehlende Variablen nicht bemängelt; das alte Problem besteht weiterhin :mad:

wraith
28-09-2004, 09:03
Ich kenne keinen C-Compiler, der deine Beispiele nicht problemlos akzeptiert;
Dann benutze ich hier nur Fantasie-Compiler.
K.A. warum dein gcc das schluckt, wohl gemoddet.
Oder probier den hier (online) http://www.comeaucomputing.com/tryitout/ (aber vorher auf C stellen).
Eine Suche auf comp.lang.c wird dir auch zeigen, das es _kein_ korrektes C ist.
Suche nach "initializer element is not constant", das ist die Fehlermeldung, die dein Compiler auswerfen sollte.


Das betrifft nur arrays, aber nicht einzelne Variblen.

Wo steht das?Das steht in 6.7.8 Unterpunkt 4, object, und object bezeichnet auch die nativen Typen, beachte dazu noch die Fussnote auf Seite 96.
Die würde keinen Sinn machen, wenn 6.7.8.4 sich nicht auch darauf beziehen würde.

nobody0
28-09-2004, 12:31
Wo steht das?Das steht in 6.7.8 Unterpunkt 4, object, und object bezeichnet auch die nativen Typen, beachte dazu noch die Fussnote auf Seite 96.


Unterpunkt 4 betrifft nur staische Variablen; nach Definition muß dafür der storage class qualifier static verwendet werden.
Der Hintergrund ist, dass nur statische Variablen schon beim Programmstart im Speicher stehen und nicht erst zur Laufzeit angelegt werden; da muß schon dem Compiler bekannt sein, was dort hin muß.
Ich verwende aber gar keine static Variablen und habe das Problem somit nicht.