ISO C equivalente de grupos apoiados dentro expressões
Pergunta
Como posso fazer o seguinte em um compatível forma (ISO C99)?
#define MALLOC(type, length, message) ({ \
type * a_##__LINE__ = (type *)malloc((length) * sizeof(type)); \
assert(message && (a_##__LINE__ != NULL)); \
a_##__LINE__; \
})
double **matrix = MALLOC(double *, height, "Failed to reserve");
NB: para compilar eu uso: gcc -std = c99 -pedantic ...
Solução
Você não deve colocar o teste para malloc()
em uma assert()
: ele não será compilado em quando você faz uma compilação de lançamento. Eu não usei assert()
o seguinte programa.
#include <stdio.h>
#include <stdlib.h>
void *mymalloc(size_t siz, size_t length,
const char *message, const char *f, int l) {
void *x = malloc(siz * length);
if (x == NULL) {
fprintf(stderr, "a.out: %s:%d: MALLOC: "
"Assertion `\"%s\" && x != ((void *)0)' failed.\n",
f, l, message);
fprintf(stderr, "Aborted\n");
exit(EXIT_FAILURE);
}
return x;
}
#define MALLOC(type, length, message)\
mymalloc(sizeof (type), length, message, __FILE__, __LINE__);
int main(void) {
int height = 100;
double **matrix = MALLOC(double *, height, "Failed to reserve");
/* work; */
free(matrix);
return 0;
}
Outras dicas
Não há padrão equivalente à extensão GCC você está usando.
Você pode obter o resultado equivalente usando uma função (possivelmente até mesmo uma função inline se você estiver usando C99) no lugar do código na macro. Você ainda precisa de uma macro para invocar essa função porque um dos argumentos é um 'nome do tipo' e você não pode passar os para funções.
Veja a resposta por @pmg para uma ilustração do tipo de função e macro usá-lo.