#c
#c
Вопрос:
#include <stdio.h>
int main(){
FILE *fp = ("Hello.txt","w");
fprintf (fp, "n Hello World");
fclose(fp);
return 0;
}
Я получаю это сообщение при запуске этой программы
«Ошибка сегментации (сброс ядра)».
Было бы очень полезно, если бы я получил представление о том, почему это происходит и как это исправить. В настоящее время я использую
кодовые блоки в ubuntu. Заранее спасибо 🙂
Комментарии:
1.
FILE *fp = ("Hello.txt","w");
->FILE *fp = fopen("Hello.txt","w");
Разве ваш компилятор не показывал хотя бы предупреждения?2. Перед использованием функции fprintf() вы проверили, был ли файл успешно создан ==> fp != NULL?
3. Да, пропустил это 🙂
4. @J.Piquard, учитывая это состояние его кода, эта проверка действительно пройдет.
Ответ №1:
да. как прокомментировал Майкл Уолц. вы пропустили fopen
#include <stdio.h>
int main(){
FILE *fp = fopen("Hello.txt","w");
fprintf (fp, "n Hello World");
fclose(fp);
return 0;
}
Ответ №2:
В вашем коде отсутствует fopen. Кроме того, чтобы избежать других проблем, всегда проверяйте возвращаемое значение fopen. Значение будет нулевым, если при открытии файла что-то пошло не так (например, не хватает места, неправильные разрешения)
#include <stdio.h>
int main(int argc, char **argv)
{
FILE *fp = fopen("Hello.txt", "w");
if (fp==NULL)
return -1;
fprintf (fp, "n Hello World");
fclose(fp);
return 0;
}
Ответ №3:
Строка:
FILE *fp = ("Hello.txt","w");
явно ошибочен с точки зрения намерения, поскольку вы, похоже, пропустили этап указания компилятору, какую фактическую функцию вы хотите вызвать. То, что вы почти наверняка хотели сделать, было:
FILE *fp = fopen("Hello.txt", "w");
Любой приличный компилятор должен был предупредить вас об этом, например, с gcc
предупреждением:
FILE *fp = ("Hello.txt","w");
^
warning: initialization from incompatible pointer type
и я часто компилирую с -Werror
флагом, чтобы компилятор обрабатывал предупреждения как ошибки, чтобы перехватывать именно такие вещи.
На самом деле вам может быть интересно, почему компилятор считает это просто предупреждением, но правда в том, что это совершенно корректный код. Круглые скобки вокруг выражения допустимы, поэтому вы можете написать либо x = 7
, либо x = (7)
, либо даже x = (((((7)))))
, и это будет означать одно и то же.
Тогда остается только выражение, заключенное в круглые скобки, и для этого используется оператор запятой C. По сути, выражение a, b
вычисляет a
(отбрасывая результат), затем вычисляет b
и использует это как результат выражения.
Вы можете проверить это поведение с помощью следующей программы, которая выводит w
:
#include <stdio.h>
int main (void) {
char *fp = ("Hello.txt", "w");
puts (fp);
return 0;
}
Вы можете подумать, что у вас было бы ограниченное использование для такого зверя, но я гарантирую, что вы используете его гораздо чаще, чем вы думаете, например, с:
for (i = 0, j = 0; i < 100; i , j = 2)
printf ("%d x 2 = %dn", i, j);
В подобных ситуациях вполне нормально выбросить результат подвыражений, поскольку вы просто полагаетесь на
побочный эффект вычисления.
В вашем случае утверждение:
FILE *fp = ("Hello.txt","w");
будет оценивать "Hello.txt"
и использовать "w"
для присвоения fp
(отсюда предупреждение о несовместимости указателя).
Затем, когда вы пытаетесь использовать адрес "w"
, как если бы это был действительный FILE
указатель, все ставки отменяются.
И, в качестве дополнительного примечания, вам обычно следует проверять возвращаемое значение всех функций, которые могут завершиться сбоем, если такой сбой может впоследствии повлиять на вашу программу. Неразумно предполагать, что fopen
(или malloc
, или множество других функций) будут работать всегда. Для fopen
это вопрос обеспечения того, чтобы возвращаемое значение не было NULL
.