O uso de macros C / C ++ como atalho para compilação condicional é uma boa prática?

13

Digamos que eu quero ter vários tipos de mensagens de saída no meu código. Um deles é DEBUG, que é impresso apenas, quando o código é compilado no modo de Depuração.

Normalmente eu teria que escrever algo como

#ifdef DEBUG
    std::cout << "Debug message" << std::endl;
#endif

o que é bastante complicado e chato de usar em muitos lugares.

É uma boa prática definir uma macro para o snippet de código, para que você a use dessa maneira?

MSG_DEBUG("Debug message")

Ou existe outra maneira mais elegante de lidar com isso sem macros? Estou interessado em possíveis soluções em C e C ++, pois estou usando as duas linguagens em diferentes projetos.

Eenoku
fonte
Não está claro na pergunta por que você não colocaria o código condicional em uma função e a chamaria. Existe alguma outra restrição que impediria isso?
Alex
@gnat A pergunta que você mencionou é tão ampla que a maioria das pessoas não o conectou a esse tópico, principalmente quando eles procuravam essa pergunta específica na Internet.
Eenoku
3
Sua pergunta está marcada com c e c ++ ; no entanto, essas são linguagens bem diferentes. Você pode esclarecer sobre qual deles está falando? Seu exemplo seria perfeitamente adequado em C, mas poderia ser melhor implementado com um constexpr ifem C ++, por exemplo.
Jörg W Mittag
1
Como um aparte, o diagnóstico deve ir para STDERR. Além disso, por que não fazê-lo depender NDEBUGcomo em assert()vez disso? Então você pode definir como #define DEBUG_MSG(MSG) assert(std::cerr << MSG), que também testa o estado do fluxo.
Deduplicator

Respostas:

19

Claro, se você está bem em usar macros em primeiro lugar, definir um parametrizado em vez de continuar repetindo o mesmo código condicional é certamente preferível a qualquer medida de boa codificação.

Você deve usar macros? Na minha opinião, você deveria, já que é uma prática aceita em C, e qualquer solução sem macro exigiria que pelo menos algo fosse executado mesmo fora do modo de depuração. O programador C típico seleciona uma macro um pouco feia com esforço desnecessário em tempo de execução a qualquer momento.

Kilian Foth
fonte
13

Há um elemento de preferência pessoal aqui, mas em C ++ eu prefiro fazer isso no arquivo de cabeçalho:

#ifdef _DEBUG
    void DebugMessage(...);
#else
    inline void DebugMessage(...) {}
#endif

Para que a função seja destacada nas compilações de versão, mas seja uma função adequada na compilação de depuração para que você possa ter uma verificação de tipo adequada, mensagens de erro sensatas etc. e a capacidade de adicionar mais funcionalidades (log, talvez?) Posteriormente.

Obviamente, você também precisa incluir a definição correspondente da função no .cpparquivo em um #ifdef _DEBUGbloco.

Jack Aidley
fonte
Mas a sobrecarga de chamadas ainda está presente aqui, não é?
Eenoku
7
Se o seu compilador irá gerar código para chamar uma função vazia conhecida em uma versão, a primeira e maior coisa que você precisa fazer para melhorar a eficiência é obter um compilador muito melhor. Isso é realmente otimização trivial.
David Thornley
@Eenoku Não, como David diz, ele será removido por qualquer compilador que você deva usar.
Jack Aidley
3
Há uma diferença importante aqui: a macro (dependendo de como está escrita) não avaliaria suas expressões de argumento, enquanto a função sempre avaliava. Além disso, é um comportamento indefinido passar argumentos não triviais para funções varargs (e geralmente aciona avisos do compilador).
Sebastian Redl
2

Definitivamente, verifique se você não está seguindo as diretrizes de código fornecidas por sua equipe. Certifique-se de que nenhum outro código no sistema tente alcançar a mesma funcionalidade por meio de uma condição geral.

James O
fonte