En aras de la depuración, ¿puedo obtener el número de línea en los compiladores C / C ++? (forma estándar o formas específicas para ciertos compiladores)
p.ej
if(!Logical)
printf("Not logical value at line number %d \n",LineNumber);
// How to get LineNumber without writing it by my hand?(dynamic compilation)
Respuestas:
Debería utilizar la macro del preprocesador
__LINE__
y__FILE__
. Son macros predefinidas y forman parte del estándar C / C ++. Durante el preprocesamiento, se reemplazan respectivamente por una cadena constante que contiene un número entero que representa el número de línea actual y por el nombre del archivo actual.Otras variables de preprocesador:
__func__
: nombre de la función (esto es parte de C99 , no todos los compiladores de C ++ lo admiten)__DATE__
: una cadena de formato "Mmm dd aaaa"__TIME__
: una cadena de formato "hh: mm: ss"Tu código será:
fuente
#define S1(N) #N
#define S2(N) S1(N)
#define LINESTR S2(__LINE__)
. Ver c-faq.com/ansi/stringize.html__func__
no es una macro, es una variable declarada implícitamente.Como parte del estándar C ++, existen algunas macros predefinidas que puede utilizar. La sección 16.8 del estándar C ++ define, entre otras cosas, la
__LINE__
macro.Entonces tu código sería:
fuente
Puede usar una macro con el mismo comportamiento que printf () , excepto que también incluye información de depuración como el nombre de la función, la clase y el número de línea:
Estas macros deberían comportarse de manera idéntica a printf () , mientras que incluyen información similar a la de Java stacktrace. Aquí hay un ejemplo de main:
Lo que da como resultado la siguiente salida:
fuente
#include
a<stdio.h>
Use
__LINE__
(que es doble subrayado LINE doble subrayado), el preprocesador lo reemplazará con el número de línea en el que se encuentra.fuente
Checkout
__FILE__
y__LINE__
macrosfuente
C ++ 20 ofrece una nueva forma de lograr esto usando std :: source_location . Esto es actualmente accesible en gcc an clang como
std::experimental::source_location
con#include <experimental/source_location>
.El problema con las macros como
__LINE__
es que si desea crear, por ejemplo, una función de registro que muestre el número de línea actual junto con un mensaje, siempre debe pasar__LINE__
como un argumento de función, porque se expande en el sitio de la llamada. Algo como esto:Siempre generará la línea de la declaración de función y no la línea desde donde
log
se llamó realmente. Por otro lado, constd::source_location
puedes escribir algo como esto:Aquí,
loc
se inicializa con el número de línea apuntando a la ubicación dondelog
se llamó. Puedes probarlo en línea aquí.fuente
Prueba
__FILE__
y__LINE__
.También puede encontrar
__DATE__
y__TIME__
útil.Aunque, a menos que tenga que depurar un programa en el lado del cliente y, por lo tanto, necesite registrar esta información, debe utilizar la depuración normal.
fuente
raw code
comillas invertidas para marcarlos como (así: `__`). @mmyers intentó ayudar, pero solo escapó uno de los guiones bajos, por lo que se quedó con la sintaxis de marcado en cursiva . Los votos negativos son un poco duros aquí, sin embargo, estoy de acuerdo.Dado que ahora también estoy enfrentando este problema y no puedo agregar una respuesta a una pregunta diferente pero también válida hecha aquí , proporcionaré una solución de ejemplo para el problema de: obtener solo el número de línea donde se ha llamado a la función C ++ usando plantillas.
Antecedentes: en C ++ se pueden utilizar valores enteros que no sean de tipo como argumento de plantilla. Esto es diferente al uso típico de tipos de datos como argumentos de plantilla. Entonces, la idea es usar tales valores enteros para una llamada de función.
Salida:
Una cosa a mencionar aquí es que en C ++ 11 Standard es posible dar valores de plantilla predeterminados para funciones usando template. En pre C ++ 11, los valores predeterminados para argumentos que no son de tipo parecen funcionar solo para argumentos de plantilla de clase. Por lo tanto, en C ++ 11, no sería necesario tener definiciones de función duplicadas como se indicó anteriormente. En C ++ 11 también es válido tener argumentos de plantilla const char * pero no es posible usarlos con literales como
__FILE__
o__func__
como se menciona aquí .Entonces, al final, si está usando C ++ o C ++ 11, esta podría ser una alternativa muy interesante que usar macro para obtener la línea de llamada.
fuente
Uso
__LINE__
, pero ¿cuál es su tipo?Como una constante entera , el código a menudo puede asumir que el valor es
__LINE__ <= INT_MAX
y, por tanto, el tipoint
.Para imprimir en C,
printf()
necesita el especificador de juego:"%d"
. Esta es una preocupación mucho menor en C ++ concout
.Preocupación pedante: si el número de línea excede
INT_MAX
1 (algo concebible con 16 bitsint
), es de esperar que el compilador produzca una advertencia. Ejemplo:Alternativamente, el código podría obligar a tipos más amplios a evitar tales advertencias.
Evitar
printf()
Para evitar todas las limitaciones de enteros: stringify . El código podría imprimirse directamente sin una
printf()
llamada: algo bueno para evitar en el manejo de errores 2 .1 Ciertamente una mala práctica de programación para tener un archivo tan grande, sin embargo, quizás el código generado por la máquina puede ser alto.
2 En la depuración, a veces el código simplemente no funciona como se esperaba. Llamar a funciones complejas como
*printf()
puede generar problemas en sí mismo frente a un simplefputs()
.fuente
Para aquellos que puedan necesitarlo, una macro "FILE_LINE" para imprimir fácilmente archivos y líneas:
fuente