web-dev-qa-db-fra.com

assert () avec message

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?

39
Alexandru

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");
70
pmg

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 boucle for vérifie son état; deuxième fois, lorsque assert évalue l'expression passée!)

21
bugfeeder

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é.

Basé sur http://c.learncodethehardway.org/book/ex20.html

12
frmdstryr

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!");
0
Arthur2e5

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.

0
Cacahuete Frito

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))
0
JiaHao Xu