Para fins de depuração, posso obter o número da linha em compiladores C / C ++? (forma padrão ou formas específicas para certos compiladores)
por exemplo
if(!Logical)
printf("Not logical value at line number %d \n",LineNumber);
// How to get LineNumber without writing it by my hand?(dynamic compilation)
Respostas:
Você deve usar a macro do pré-processador
__LINE__
e__FILE__
. Eles são macros predefinidas e fazem parte do padrão C / C ++. Durante o pré-processamento, eles são substituídos respectivamente por uma string constante contendo um número inteiro que representa o número da linha atual e pelo nome do arquivo atual.Outras variáveis de pré-processador:
__func__
: nome da função (faz parte do C99 , nem todos os compiladores C ++ o suportam)__DATE__
: uma string no formato "Mmm dd aaaa"__TIME__
: uma string no formato "hh: mm: ss"Seu código será:
fonte
#define S1(N) #N
#define S2(N) S1(N)
#define LINESTR S2(__LINE__)
. Consulte c-faq.com/ansi/stringize.html__func__
não é uma macro, é uma variável declarada implicitamente.Como parte do padrão C ++, existem algumas macros predefinidas que você pode usar. A seção 16.8 do padrão C ++ define, entre outras coisas, a
__LINE__
macro.Portanto, seu código seria:
fonte
Você pode usar uma macro com o mesmo comportamento de printf () , exceto que também inclui informações de depuração, como nome da função, classe e número da linha:
Essas macros devem se comportar de forma idêntica a printf () , enquanto incluem informações semelhantes a java stacktrace. Aqui está um exemplo principal:
O que resulta na seguinte saída:
fonte
#include
para<stdio.h>
Use
__LINE__
(isto é, sublinhado duplo LINE), o pré-processador irá substituí-lo pelo número da linha na qual ele foi encontrado.fonte
Check
__FILE__
- out e__LINE__
macrosfonte
C ++ 20 oferece uma nova maneira de conseguir isso usando std :: source_location . Isso está atualmente acessível no gcc an clang como
std::experimental::source_location
com#include <experimental/source_location>
.O problema com macros como
__LINE__
é que se você deseja criar, por exemplo, uma função de registro que produza o número da linha atual junto com uma mensagem, você sempre deve passar__LINE__
como um argumento de função, porque é expandido no local da chamada. Algo assim:Sempre produzirá a linha da declaração da função e não a linha de onde
log
foi realmente chamada. Por outro lado, comstd::source_location
você pode escrever algo assim:Aqui,
loc
é inicializado com o número da linha apontando para o local ondelog
foi chamado. Você pode tentar online aqui.fonte
Experimente
__FILE__
e__LINE__
.Você também pode achar
__DATE__
e__TIME__
útil.Porém, a menos que você tenha que depurar um programa no lado do cliente e, portanto, precise registrar essas informações, você deve usar a depuração normal.
fonte
raw code
(como este: `__`). @mmyers tentou ajudar, mas escapou apenas de um dos sublinhados e, portanto, você ficou com a sintaxe de marcação para itálico . Os votos negativos são um pouco duros aqui, eu concordo.Para quem precisar, uma macro "FILE_LINE" para imprimir facilmente o arquivo e a linha:
fonte
Como também estou enfrentando esse problema agora e não posso adicionar uma resposta a uma pergunta diferente, mas também válida, feita aqui , vou fornecer uma solução de exemplo para o problema de: obter apenas o número da linha de onde a função foi chamada C ++ usando modelos.
Contexto: em C ++, pode-se usar valores inteiros sem tipo como um argumento de modelo. Isso é diferente do uso típico de tipos de dados como argumentos de modelo. Portanto, a ideia é usar esses valores inteiros para uma chamada de função.
Resultado:
Algo a ser mencionado aqui é que no C ++ 11 Standard é possível fornecer valores de template padrão para funções usando template. No pré C ++ 11, os valores padrão para argumentos sem tipo parecem funcionar apenas para argumentos de modelo de classe. Assim, em C ++ 11, não haveria necessidade de ter definições de função duplicadas como acima. Em C ++ 11 também é válido ter argumentos de template const char *, mas não é possível usá-los com literais como
__FILE__
ou__func__
como mencionado aqui .Portanto, no final, se você estiver usando C ++ ou C ++ 11, esta pode ser uma alternativa muito interessante do que usar macro para obter a linha de chamada.
fonte
Use
__LINE__
, mas qual é o seu tipo?Como uma constante inteira , o código geralmente pode assumir que o valor é
__LINE__ <= INT_MAX
e, portanto, o tipo éint
.Para impressão em C,
printf()
precisa o especificador Coincidindo:"%d"
. Esta é uma preocupação muito menor em C ++ comcout
.Preocupação pedante: Se o número da linha exceder
INT_MAX
1 (algo concebível com 16 bitsint
), espero que o compilador produza um aviso. Exemplo:Como alternativa, o código pode forçar tipos mais amplos a evitar esses avisos.
Evitar
printf()
Para evitar todas as limitações de inteiros: stringify . O código pode ser impresso diretamente sem uma
printf()
chamada: uma boa coisa a evitar no tratamento de erros 2 .1 Certamente uma prática de programação ruim para ter um arquivo tão grande, mas talvez o código gerado por máquina possa ser alto.
2 Na depuração, às vezes o código simplesmente não funciona como esperado. Chamar funções complexas como
*printf()
pode gerar problemas em vez de simplesfputs()
.fonte