J'ai vu quelque part assert utilisé avec un message de la manière suivante:
assert(("message", condition));
Cela semble très bien fonctionner, sauf que gcc lance l'avertissement suivant:
warning: left-hand operand of comma expression has no effect
Comment puis-je arrêter l'avertissement?
Utilisation -Wno-unused-value
pour arrêter l'avertissement; (l'option -Wall
comprend -Wunused-value
).
Je pense que c'est encore mieux d'utiliser une autre méthode, comme
assert(condition && "message");
Essayer:
#define assert__(x) for ( ; !(x) ; assert(x) )
utiliser comme tel:
assert__(x) {
printf("assertion will fail\n");
}
Exécute le bloc uniquement lorsque l'assertion échoue.
REMARQUE IMPORTANTE: Cette méthode évaluera l'expression
x
deux fois, dans le cas oùx
évalue àfalse
! (Première fois, lorsque la bouclefor
vérifie son état; deuxième fois, lorsqueassert
évalue l'expression passée!)
Si vous souhaitez transmettre un message formaté, vous pouvez utiliser les macros suivantes:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_error(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define assertf(A, M, ...) if(!(A)) {log_error(M, ##__VA_ARGS__); assert(A); }
Ensuite, utilisez-le comme printf:
// With no args
assertf(self != NULL,"[Server] Failed to create server.");
// With formatting args
assertf((self->socket = u_open(self->port)) != -1,"[Server] Failed to bind to port %i:",self->port);
// etc...
Production:
[ERREUR] (../src/webserver.c:180: errno: adresse déjà utilisée) [Server] Impossible de se lier au port 8080: serveur Web: ../src/webserver.c:180: server_run: Assertion `( self-> socket = u_open (self-> port))! = -1 'a échoué.
Par tradition, (void)
communique au compilateur que vous ignorez sciemment une expression:
/* picard.c, TNG S6E11. */
#define assertmsg(x, msg) assert(((void) msg, x))
assertmsg(2+2==5, "There! are! four! lights!");
Vous pouvez écrire votre propre macro qui fournit la même utilisation de _Static_assert(expr, msg)
:
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
/*
* void assert_msg(bool expr, const char *msg);
*/
#if !defined(NDEBUG)
#define assert_msg(expr, msg) do \
{ \
const bool e_ = expr; \
\
if (!e_) { \
fputs(msg, stderr); \
fputc('\n', stderr); \
assert(e_); \
} \
} while (0)
#else
#define assert_msg(expr, msg) do \
{ \
\
if (!(expr)) \
warn_bug(msg); \
} while (0)
#endif
J'ai également une macro warn_bug()
qui affiche le nom du programme, le fichier, la ligne, la fonction, la valeur et la chaîne errno et un message utilisateur, même si les assertions sont désactivées. La raison derrière cela est qu'il ne cassera pas le programme, mais il avertira qu'un bug sera probablement présent. Vous pouvez simplement définir assert_msg
Comme étant vide si defined(NDEBUG)
, cependant.
Une fonction qui prend const char*
et renvoie true
vous sauverait probablement de toutes sortes d'avertissements:
#include <assert.h>
int always_true(const char *msg) {
return 1;
}
#define assert_msg(expr, msg) assert((expr) && always_true(msg))