Форум программистов, компьютерный форум, киберфорум
Наши страницы

C для начинающих

Войти
Регистрация
Восстановить пароль
 
 
zss
Модератор
Эксперт С++
6531 / 6093 / 2007
Регистрация: 18.12.2011
Сообщений: 15,845
Завершенные тесты: 1
#1

Распространенные ошибки - C (СИ)

02.10.2014, 12:49. Просмотров 42784. Ответов 57
Метки нет (Все метки)

Оглавление

Ошибки этапа компиляции
(В процессе компиляции выдается либо сообщение об ошибке, либо предупреждение)
- Попытка модифицировать константу через указатель
- Лишняя точка с запятой
- Отсутствие возврата значения из функции
- Приведение типа в стиле С++
- Использование = вместо ==


Ошибки этапа исполнения программы
(Во время исполнения программа прерывается с сообщением об ошибке)
- Возврат из функции локальной строки
- Выделение памяти без дальнейшего освобождения
- Использование неинциализированной переменной
- Использование функции strncpy как функции "безопасного" копирования строк
- Использование функций atoi/atof или sscanf для перевода строки в число
- Возврат ссылки/указателя на локальную переменную
- Выход за пределы массива
- Сравнение символьных массивов
- Использование чисел, записанных в других системах счисления.
- Работа с локальной копией объекта, вместо работы с самим объектом


Неправильное поведение программы на этапе исполнения
(Программа работает, но не так, как запланировано)
- Использование типов char, short и float при работе с va_arg
- Определение размера массива, переданного в качестве аргумента функции.
- "Неожиданное" закрытие окна.
- "Неожиданное" целочисленное деление в арифметических выражениях.
- Ошибки в логических выражениях.
- Использование символа цифры вместо числа
- Лишняя точка с запятой
- switch без break
- Сравнение вещественных чисел при вычислениях
- Проверки на принадлежность значения определенному интервалу.
- Неверный аргумент тригонометрических функций.
- Сравнение знаковой переменной с беззнаковой.
- Использование запятой для отделения дробной части
- Забытое выделение тела цикла for, while и операторов if else
- Локальная переменная экранирует переменную с таким же именем из вышестоящей области видимости
- Неправильное использование memset

Алгоритмические ошибки
(Неправильно составлен алгоритм программы)
- Двойная перестановка строк или элементов массива.

Ошибки ввода-вывода
- Ошибки при использовании функции scanf()!
- При работе с fgetc под Windows чтение файла обрывается при достижении буквы 'я'
- Оставление символа '\n' в потоке ввода
- scanf() - ввод текстовых строк

Ошибки, связанные с отклонением от стандарта языка
- Неверный тип функции main()
3
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.10.2014, 12:49
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Распространенные ошибки (C (СИ)):

Ошибки при компиляции - исправить ошибки в коде - C (СИ)
Помогите исправить ошибки , не понимаю в чем может быть причина ... #include <conio.h> #include <stdio.h> #include <math.h> ...

Распространенные ошибки - C++
Оглавление Ошибки этапа компиляции Программа не компилируется или компилируется с предупреждениями. Попытка модифицировать...

безопасность и распространенные ошибки - Perl
Тут наткнулся на очень интересные тексты: http://werad.narod.ru/articles/programm6.html http://werad.narod.ru/articles/programm9.html...

.NET 2.x Распространенные ошибки SEO и ASP.NET 2.0 - C# ASP.NET
Здравствуйте, существуют несколько СЕО проблем при использовании ASP.NET, ниже я опишу эти проблемы, нужно найти простое и эффективное...

Самые распространенные строки - Delphi
type Mytype = record name:string; surname:string; end; var Students:Mytype; MyFile:file of Mytype; ...

Вывести самые распространенные мужские и женские имена - C++
Имеется массив записей о студентах, каждая из которых включает поля: фамилия, имя, отчество, пол, возраст, курс. Разработать программу,...

57
Tulosba
:)
Эксперт С++
4397 / 3233 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
27.07.2016, 22:03 #46
Цитата Сообщение от emerael Посмотреть сообщение
использование = вместо ==
Любой современный компилятор ругается на это предупреждением. Хотя, справедливости ради, стоит заметить, что VC++ делает это только начиная с 4го уровня ворнингов.
1
Evg
Эксперт CАвтор FAQ
18248 / 6373 / 438
Регистрация: 30.03.2009
Сообщений: 17,641
Записей в блоге: 28
28.07.2016, 09:44 #47
Цитата Сообщение от Tulosba Посмотреть сообщение
Любой современный компилятор ругается на это предупреждением
Это никакой роли не играет, т.к. среди начинающих почти никто не умеет читать предупреждения

В любом случае этот пункт уже есть - "Ошибки в логических выражениях". Правда ссылка ведёт на параллельную тему в разделе C++
0
gng
645 / 491 / 133
Регистрация: 08.09.2013
Сообщений: 1,326
28.07.2016, 12:50 #48
Цитата Сообщение от Tulosba Посмотреть сообщение
Любой современный компилятор ругается на это предупреждением.
А на это уже нет
C
1
2
3
if ((a=0) || (b=0)) {
  ...
}
0
Evg
Эксперт CАвтор FAQ
18248 / 6373 / 438
Регистрация: 30.03.2009
Сообщений: 17,641
Записей в блоге: 28
28.07.2016, 13:00 #49
Цитата Сообщение от gng Посмотреть сообщение
А на это уже нет
А это негласная договорённость. Чтобы оставить программисту возможность писать присваивание, когда ему нужно именно присваивание, а не сравнение
1
gng
645 / 491 / 133
Регистрация: 08.09.2013
Сообщений: 1,326
28.07.2016, 13:08 #50
Цитата Сообщение от Evg Посмотреть сообщение
А это негласная договорённость.
Поэтому для меня, често говоря, стало новостью, чо без двойных скобок ругается на
C
1
if (a=0)
Не приходилось как-то получать таких предупреждений.
0
linuxdesk
3 / 3 / 2
Регистрация: 25.03.2015
Сообщений: 22
02.08.2016, 17:30 #51
Цитата Сообщение от Evg Посмотреть сообщение
А это негласная договорённость.
Подскажите, пожалуйста, как изменить следующую строчку, чтобы варнинга не было?
C
1
while ((vqty = get_vcqty(Seq, os, qty)) && (TableOrder[qS].prc <= prc))
upd: присваивание мне тут нужно
0
Evg
Эксперт CАвтор FAQ
18248 / 6373 / 438
Регистрация: 30.03.2009
Сообщений: 17,641
Записей в блоге: 28
02.08.2016, 20:30 #52
А какой у тебя компилятор? Наверняка не все компиляторы этого придерживаются

Добавлено через 31 минуту
На крайний случай всегда можно написать явное сравнение (лично на мой взгляд такой код почти всегда более читаемый). Т.е. вместо

C
if ((x = y))
писать

C
if ((x = y) != 0)
Тут уже warning'а не будет
1
linuxdesk
3 / 3 / 2
Регистрация: 25.03.2015
Сообщений: 22
03.08.2016, 03:27 #53
Цитата Сообщение от Evg Посмотреть сообщение
А какой у тебя компилятор?
VS2015.
Цитата Сообщение от Evg Посмотреть сообщение
if ((x = y) != 0)
Спасибо
0
MrGluck
Модератор
Эксперт CЭксперт С++
7491 / 4606 / 692
Регистрация: 29.11.2010
Сообщений: 12,592
25.01.2017, 18:09 #54
Попытка компилировать программу, написанную на С, с помощью компилятора С++
Пожалуй, одна из самых частых ошибок. Чаще всего, напарываются на попытку привести тип void *, возвращаемый функцией malloc/calloc, к типу, на который указывает указатель, принимающий результат.
C
1
int *arr = malloc(sizeof(*arr) * N)
Компилятор при этом выдаёт сообщение вида
Код
cannot convert from 'void *' to 'int *'
Дело в том, что в С приведение указателя, возвращаемого malloc, к конкретному типу является моветоном и ведёт к трудноуловимым ошибкам, то есть код выше написан правильно.
А в С++ введён запрет на неявное приведение из void *, то есть для С++ надо явно кастануть результат к (int *).
По историческим причинам (до первого стандарта ANSI/ISO malloc возвращал char * и была ошибка приведения, но потом придумали void *), в некоторой литературе приводятся примеры с явным приведением типа указателя, но вызваны они бездумным копированием старого кода.

Решение:
Для Windows необходимо переименовать расширение файла на .c
Для Linux использовать компилятор gcc вместо g++. Для clang указывать во флаге компиляции правильный стандарт языка (например -std=c99 вместо -std=c++98).
2
Evg
Эксперт CАвтор FAQ
18248 / 6373 / 438
Регистрация: 30.03.2009
Сообщений: 17,641
Записей в блоге: 28
25.01.2017, 19:02 #55
Цитата Сообщение от MrGluck Посмотреть сообщение
компилятор gcc вместо g++
Можно ещё подать опцию -xc СЛЕВА от имени файла (т.е. "-xc t.cc", но не "t.cc -xc")
0
MrGluck
Модератор
Эксперт CЭксперт С++
7491 / 4606 / 692
Регистрация: 29.11.2010
Сообщений: 12,592
26.01.2017, 19:38 #56
Цитата Сообщение от MrGluck Посмотреть сообщение
Попытка компилировать программу, написанную на С, с помощью компилятора С++
Продолжая данную проблему.
Квалификатор const в С и С++ работает по разному. В последнем, он при возможности создаёт константу времени компиляции. Но в С этого не происходит. Чем это грозит?
Когда используется запись вида const int N = 30; в С++ создаётся константа времени компиляции, в С лишь переменная с запретом на изменение значения (read-only). И дальнейшее объявление вида
int arr[N]; для С внезапно даст VLA (variable-length array) массив. Но это лишь при условии, что стандарт поддерживает данную опцию (C89 не поддерживает, С99 поддерживает, С11 optional). Также, VLA есть в gnu расширении. Плохо это по двум причинам:
1. Для VLA массивов память выделяется через alloca, то есть из стека системы, а это лучше не делать, учитывая, что размер массива может быть и достаточно большим, а проверить выделилась ли память с помощью alloca нельзя (в отличие от malloc). Примечание: реализация VLA может отличаться, стандарт не накладывает ограничений на этот счёт. Однако, GCC использует именно описанный способ.
2. Сам того не подозревая, автор вносит зависимость на стандарт/расширение. А учитывая, что VS до сих пор не научилась работать с VLA, при переносе кода и честной компиляции сишным компилятором, могут вывалиться ошибки.

Решение:
Прежде всего, стоит использовать сишный компилятор для языка С, а плюсовый для С++. О том, как это сделать:
Цитата Сообщение от MrGluck Посмотреть сообщение
Для Windows необходимо переименовать расширение файла на .c
Для Linux использовать компилятор gcc вместо g++. Для clang указывать во флаге компиляции правильный стандарт языка (например -std=c99 вместо -std=c++98).
Цитата Сообщение от Evg Посмотреть сообщение
Можно ещё подать опцию -xc СЛЕВА от имени файла (т.е. "-xc t.cc", но не "t.cc -xc")
Для задания констант (в данном случае, идентификаторов), известных во время компиляции и позволяющих задать статический массив определённого размера, в С используют препроцессорную директиву define. Подробнее о её работе вы можете ознакомиться тут.
В данном случае, стоило бы написать #define N 30
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
3945 / 2169 / 553
Регистрация: 18.10.2014
Сообщений: 3,783
26.01.2017, 21:34 #57
Цитата Сообщение от MrGluck Посмотреть сообщение
Для Windows необходимо переименовать расширение файла на .c
Для Linux использовать компилятор gcc вместо g++. Для clang указывать во флаге компиляции правильный стандарт языка (например -std=c99 вместо -std=c++98).
Не совсем понятно разделение на "Windows и Linux". Способы выбора языка компиляции зависят только от используемого компилятора и никак не связаны с операционной системой.

Для MSVC это: расширение имени файла или явное указание языка при помощи параметров компилятора /TC для C и /TP для C++.

Для GCC и Clang это: расширение имени файла или явное указание языка при помощи параметров компилятора -x c для C и -x c++ для C++. При этом расширение файла для умолчательного определения языка используют только gcc и clang, а g++ и clang++ по умолчанию рассматривают все файлы как С++, независимо от расширения.
1
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
3945 / 2169 / 553
Регистрация: 18.10.2014
Сообщений: 3,783
16.02.2017, 05:10 #58
Частые множественные вызовы srand(time(NULL))

Если код программы содержит множественные попытки "перезапустить" генератор псевдослучайных чисел, используя в качестве seed-значения текущее значение времени, полученное через вызов time(NULL)

C
1
2
3
...
srand(time(NULL));
...
то может получиться так, что такие вызовы srand будут следовать друг за другом очень быстро. Так быстро, что time(NULL) будет возвращать одно и то же значение времени. Это приведет к тому, что генератор псевдослучайных чисел будет постоянно перезапускаться с указанием одного и того же seed-значения. В результате последующие вызовы rand() будут порождать одну и ту же псевдослучайную последовательность.

Например, вот такой код, будучи запущенным на выполнение, вероятнее всего выведет одну и ту же псевдослучайную последовательность два раза

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
 
int main()
{
    srand(time(NULL));
    for (unsigned n = 20; n > 0; --n) 
      printf("%d ", rand());
    printf("\n");  
     
    srand(time(NULL));
    for (unsigned n = 20; n > 0; --n) 
      printf("%d ", rand());
    printf("\n");  
}
Эта проблема также иногда рапортуется в следующем виде: "Под дебаггерром у меня в программе получаются разные случайные числа, а без дебаггера - одни и те же". Действительно, когда программа выполняется по шагам в интерактивном дебаггере, она выполняется "медленно" и между вызовами srand значение времени time(NULL) успевает измениться, что создает иллюзию того, что все работает "как задумано". Но стоит запустить программу в свободное выполнение, как проблема проявляется во всей красе.

Если вам нужен вызов srand(time(NULL)); в вашей программе, то в большинстве случаев его достаточно сделать всего один-единственный раз на старте программы.
3
16.02.2017, 05:10
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.02.2017, 05:10
Привет! Вот еще темы с ответами:

Вывести самые распространенные женские и мужские имена - C++
Помогите решить задачу пожалуйста! Написать программу, которая формирует файл записей данной структуры Type Student=Record ...

Вирус блокирует выход на сайт вк и другие распространенные сайты - Удаление вирусов
я чайник поэтому если что то не загрузилось..напишите пожалуйста, и помогите... второй день вожусь с этим. Hosts чистый, drweb выявил один...

Найти и вывести самые распространенные женские те мужские имена - Pascal ABC
О каждом студенте факультета доступна следующая информация: фамилия, имя, отчество, пол, возраст, курс. Найти и вывести самые...

Какие самые распространенные бесплатные спам-фильтры Вам известны? - Безопасность сайтов
Всем привет понимаю что не заслуживаю как новенький о помощи но все же попрошу помогите . Вопрос жизни . Какие самые распространенные...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
58
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru