Конфликты «чтения» идентификатора C ?

#c

#c

Вопрос:

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

Вот упрощенный код.

 #include <iostream>
#include <fstream>
//using namespace std;
struct command{
    int a;
};
command read[1]; 
int main() {
    std::ifstream fin;
    fin.open("123.txt");
    if (!fin){
        std::cout << "failed" << std::endl;
        return 0;
    }
    char c;
    fin >> c;
    std::cout << c;
    return 0;
}
 

Он отлично работает Visual Studio 2019 с. Однако, когда я пытаюсь использовать devc 5.11 TDM-GCC 4.9.2 , возникает странная ошибка. Я получаю ошибку сегментации в строке fin>>c; с кодом возврата 3221225477.

С большими усилиями самый простой способ заставить этот код работать — это изменить идентификатор read на имена, подобные reading или любые другие. Кроме того, перемещение строки command read[1]; в основную функцию также помогает.

Мои вопросы:

  • Связано ли это поведение с компилятором? MSVC в порядке, но GCC 4.9.2 немного устарел или …?
  • read Конфликтует ли идентификатор с чем-то в моем коде? Почему это не ошибка компиляции, а ошибка сегментации?
  • Почему перемещение объявления read в основную функцию помогает?

Обновление: спасибо за советы, и я удалил using namespace std . Я думаю, это как-то связано с ifstream , потому что просто std::cout<<"hello world"; работает. -Wall -Wextra не выдает предупреждений.

Комментарии:

1. Что там read вообще происходит? Почему у вас есть массив из одной вещи?

2. Совет: избавьтесь от using namespace std std:: префикса и примите его. Это помогает отделить ваш код от стандартной библиотеки.

3. Возможно, это конфликт символов с read() функцией. Вы компилируете с -Wall , чтобы получать предупреждения?

4. @tadman это просто упрощенный код, в моем проекте read — это uesd для хранения некоторых данных, я нахожу здесь свою ошибку и удаляю бесполезный код. Его длина равна единице, потому что я пытаюсь уменьшить используемую память (из-за ошибки сегментации).

5. Справедливо, если это просто демонстрация минимального случая сбоя. Я вижу, что люди выделяют массивы размером один в реальном коде, хотя в большинстве случаев это анти-шаблон, поэтому просто упомяните его здесь, чтобы быть уверенным.

Ответ №1:

Компилятор GCC более строгий, чем другой компилятор.

Согласно описанию Тэдмана, мы можем предположить read , что в пространстве имен std есть символ.

Итак, вы убираете его из main, это конфликт, вы вставляете main, он становится локальным символом.

Комментарии:

1. read() на который ссылается @tadman, это системный вызов Linux и, следовательно, не в std. Строго говоря, компилятор здесь не соответствует стандарту C — определяет нестандартный глобальный.

2. Спасибо, я удалил using namespace std , но ошибка все еще выходит..

3. Это означает, что в глобальном пространстве имен есть другое чтение, а не в std.@ Хорошая игра

Ответ №2:

Очень вероятно, что между вашим read и другим в глобальном пространстве имен происходит столкновение. Не все компиляторы обрабатывают эту ситуацию одинаково, но вы всегда можете избежать этого, если будете осторожны.

Intellisense Visual Studio (или любая другая альтернатива, которую вы предпочитаете) может помочь вам определить, с каким символом вы read сталкиваетесь. Для этого закомментируйте или закомментируйте свой код, затем начните вводить « read «. Если read в вашей области есть другой, вы, вероятно, увидите его и сможете получить информацию о нем.

Это одна из причин, по которой мне не нравится using namespace std; . Это загрязняет ваше глобальное пространство имен кучей вещей и увеличивает вероятность столкновения со стандартным идентификатором библиотеки.

Комментарии:

1. Все наоборот: Visual Studio работает здесь корректно, а g имеет неожиданный глобальный read() характер.