C / C ++ номер строки - PullRequest
       70

C / C ++ номер строки

97 голосов
/ 17 мая 2010

В целях отладки могу ли я получить номер строки в C / C ++ компиляторах?(стандартный или особый способ для определенных компиляторов)

например

if(!Logical)
    printf("Not logical value at line number %d \n",LineNumber);
    // How to get LineNumber without writing it by my hand?(dynamic compilation)

Ответы [ 7 ]

158 голосов
/ 17 мая 2010

Вы должны использовать макрос препроцессора __LINE__ и __FILE__. Это предопределенные макросы и часть стандарта C / C ++. Во время предварительной обработки они заменяются соответственно константной строкой, содержащей целое число, представляющее текущий номер строки, и текущим именем файла.

Другие переменные препроцессора:

  • __func__: имя функции (это часть C99 , не все компиляторы C ++ поддерживают его)
  • __DATE__: строка вида "Ммм дд гггг"
  • __TIME__: строка в формате "чч: мм: сс"

Ваш код будет:

if(!Logical)
  printf("Not logical value at line number %d in file %s\n", __LINE__, __FILE__);
60 голосов
/ 17 мая 2010

В рамках стандарта C ++ существует несколько предопределенных макросов, которые вы можете использовать. Раздел 16.8 стандарта C ++ определяет среди прочего макрос __LINE__.

__LINE__: Номер строки текущей строки источника (десятичная дробь константа).
__FILE__: Предполагаемое имя исходного файла (строка символов дословный).
__DATE__: Дата перевода исходного файла (символьная строка Буквальный ...)
__TIME__: Время перевода исходного файла (символьная строка Буквальный ...)
__STDC__: Предопределено ли __STDC__
__cplusplus: Имя __cplusplus определяется значением 199711L, когда компиляция модуля перевода C ++

Итак, ваш код будет:

if(!Logical)
  printf("Not logical value at line number %d \n",__LINE__);
17 голосов
/ 08 ноября 2014

Вы можете использовать макрос с тем же поведением, что и printf () , за исключением того, что он также включает в себя отладочную информацию, такую ​​как имя функции, класс и номер строки:

#include <cstdio>  //needed for printf
#define print(a, args...) printf("%s(%s:%d) " a,  __func__,__FILE__, __LINE__, ##args)
#define println(a, args...) print(a "\n", ##args)

Эти макросы должны вести себя идентично printf () , включая информацию, подобную трассировке Java. Вот основной пример:

void exampleMethod() {
    println("printf() syntax: string = %s, int = %d", "foobar", 42);
}

int main(int argc, char** argv) {
    print("Before exampleMethod()...\n");
    exampleMethod();
    println("Success!");
}

Что приводит к следующему выводу:

main (main.cpp: 11) Перед примеромMethod () ...
exampleMethod (main.cpp: 7) синтаксис printf (): строка = foobar, int = 42
main (main.cpp: 13) Удачи!

11 голосов
/ 17 мая 2010

Используйте __LINE__ (это двойное подчеркивание LINE и двойное подчеркивание), препроцессор заменит его на номер строки, с которой он встречается.

9 голосов
/ 17 мая 2010

Оформить заказ __FILE__ и __LINE__ макросы

4 голосов
/ 17 мая 2010

Попробуйте __FILE__ и __LINE__.
Вы также можете найти __DATE__ и __TIME__ полезными.
Хотя, если вам не нужно отлаживать программу на стороне клиента и, следовательно, нужно регистрировать эту информацию, вам следует использовать обычную отладку.

1 голос
/ 09 февраля 2016

Поскольку я также столкнулся с этой проблемой сейчас, и я не могу добавить ответ на другой, но также действительный вопрос, заданный здесь , Я приведу пример решения проблемы: получить только номер строки, где функция была вызвана в C ++ с использованием шаблонов.

Справочная информация: в C ++ можно использовать нетипичные целочисленные значения в качестве аргумента шаблона. Это отличается от типичного использования типов данных в качестве аргументов шаблона. Поэтому идея состоит в том, чтобы использовать такие целочисленные значения для вызова функции.

#include <iostream>

class Test{
    public:
        template<unsigned int L>
        int test(){
            std::cout << "the function has been called at line number: " << L << std::endl;
            return 0;
        }
        int test(){ return this->test<0>(); }
};

int main(int argc, char **argv){
    Test t;
    t.test();
    t.test<__LINE__>();
    return 0;
}

Выход:

функция была вызвана по номеру строки: 0

функция была вызвана по номеру строки: 16

Здесь следует упомянуть, что в C ++ 11 Standard можно задавать значения шаблона по умолчанию для функций, использующих шаблон. В pre C ++ 11 значения по умолчанию для не типовых аргументов, кажется, работают только для аргументов шаблона класса. Таким образом, в C ++ 11 не было бы необходимости иметь дублирующиеся определения функций, как указано выше. В C ++ 11 также допустимо иметь аргументы шаблона const char *, но невозможно использовать их с литералами, такими как __FILE__ или __func__, как упоминалось здесь .

В итоге, если вы используете C ++ или C ++ 11, это может быть очень интересной альтернативой, чем использование макросов для получения вызывающей строки.

...