код, как показано ниже:ошибка сегментации при использовании fprintf выходного __LINE__
#include <stdio.h>
int main() {
fprintf(stderr, "%s \n", __LINE__);
return 0;
}
# gcc b.c
# ./a.out
Segmentation fault (core dumped)
код, как показано ниже:ошибка сегментации при использовании fprintf выходного __LINE__
#include <stdio.h>
int main() {
fprintf(stderr, "%s \n", __LINE__);
return 0;
}
# gcc b.c
# ./a.out
Segmentation fault (core dumped)
__LINE__
расширяется до целочисленной константы. Используйте %d
печатать:
fprintf(stderr, "%d \n", __LINE__);
§6.10.8.1 Обязательные макросы (C11 проект)
__LINE__ Предполагаемая номер строки (в пределах текущего источника фи ле) текущей строки источника (AN целочисленная константа).
Если __LINE__
макрос существо перелива int
является проблемой, то вы можете привести его к uintmax_t
и распечатать его. Это самый безопасный способ, так как uintmax_t
- самый большой целочисленный тип.
#include <stdint.h>
fprintf(stderr, "%ju \n", (uintmax_t)__LINE__);
Это будет UB, если файл имеет более 32767 строк, а ваша платформа имеет 16 бит 'int'. – Bathsheba
@ Bathsheba В этой логике «долгий срок» тоже не сработает. Как правило, 'int' составляет 32 бита на большинстве платформ, и если ваш исходный файл имеет строки' 4294967296' ('2^32 - 1'), то макрос' __LINE__' является наименьшей из ваших проблем :) –
Хотя это хороший ответ (плюс один), вызывает беспокойство то, что C так пропущен в типе для '__LINE__'. Я до сих пор считаю, что, в балансе, использование '(long) __ LINE__' является самой безопасной задачей. – Bathsheba
__LINE__
фактически действует постоянная Integer, и пытается напечатать его в виде строки, то система ищет вещи, не печатать до терминатора, что целая константа не имеет, в результате чего процесс идти в память его не предполагается. В этом случае результатом является segfault.
длинный рассказ короткий, использование %d
как спецификатор формата для печати.
__LINE__
требуется как минимум %d
формат, поскольку это целочисленная константа.
Хороший совет: скомпилируйте всегда с помощью опции -Wall
. В вашем случае вы увидите:
b.c: In function ‘main’:
b.c:5:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat=]
fprintf(stderr, "%s \n", __LINE__);
поведения вашей программы неопределенные, так как ваш спецификатор формата является неправильным.
Тем не менее, стандарт С вызывает раздражающее уклонение от типа от __LINE__
. Он просто утверждает, что это интегральный тип. Это означает, что это может быть int
или, если int
не является достаточно большим (int
может иметь максимальный размер 32767), то это будет long
.
Так, чтобы быть действительно уверены, я бы использовал %ld
в качестве спецификатора формата и писать
fprintf(stderr, "%ld \n", (long)__LINE__);
Для действительно большие файлы, я conject это может быть long long
типа; то вы бы нужно
fprintf(stderr, "%lld \n", (long long)__LINE__);
Поскольку __LINE__
целая константа, вы не можете использовать его как строку.Если вам нужна строка, вам нужно сообщить препроцессору, чтобы преобразовать номер в строку:
#define STRINGIFY(x) #x
#define STR(x) STRINGIFY(x)
fprintf(stderr, "%s \n", STR(__LINE__));
__LINE__ is% s ?? –