2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Вопрос по СИ (не С++)
Сообщение16.04.2014, 16:19 


16/04/14
3
Такой код:
Код:
#define fl_1    1
#define fl_2    2
#define fl_3    3
/************************************************/
typedef struct cr {
   char flCR;
   char *sCR;
};

typedef struct us {
   char flInt1;
   char flGlobal;
   cr CR1[3];
};

cr CR1[] =  {{fl_1, "string_1"},
         {fl_2, "string_2"},
         {fl_3, "string_3"}};

us US_1, US_2, US_3;
/************************************************/
int main(void)
{
   char ch;

   ch = US_1.CR1[1].sCR[7];

   return 0;
}

Компиляция проходит успешно.
Во время отладки вываливается следующая ошибка в 26 строке:
Unhandled exception at 0x00411373 in structure5.exe: 0xC0000005: Access violation reading location 0x00000007.
Не могу найти ошибку.

Используется IDE - Visual Studio 2010

 Профиль  
                  
 
 Re: Вопрос по СИ (не С++)
Сообщение16.04.2014, 17:15 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Вам не кажется, что US_1 неинициализирована?

 Профиль  
                  
 
 Re: Вопрос по СИ (не С++)
Сообщение16.04.2014, 17:51 
Заслуженный участник
Аватара пользователя


28/07/09
1238
hubble.tvv в сообщении #850493 писал(а):
Код:
typedef struct cr {
   char flCR;
   char *sCR;
};

Что? Так нельзя. Спецификатор typedef имеет не такой синтаксис. Сначала тип, потом его синоним. Соответственно, нужно:
Код:
typedef struct {
   char flCR;
   char *sCR;
}cr;


Ко второй структуре та же претензия.

 Профиль  
                  
 
 Re: Вопрос по СИ (не С++)
Сообщение16.04.2014, 18:09 
Аватара пользователя


02/01/14
292
Legioner93 в сообщении #850520 писал(а):
Что? Так нельзя. Спецификатор typedef имеет не такой синтаксис.
Компилятор не ругается. Некрасиво, но можно.

 Профиль  
                  
 
 Re: Вопрос по СИ (не С++)
Сообщение16.04.2014, 18:21 
Заслуженный участник
Аватара пользователя


28/07/09
1238
zvm
Переменную вы можете объявить типа cr?
Код:
typedef struct cr {
   char flCR;
   char *sCR;
};
cr a={'z', "test"};
...
putchar(a.flCR);

Нормально у вас такой код работает? Мой TCC на телефоне справедливо не компилирует, на gcc проверю чуть позже.

-- Ср апр 16, 2014 19:31:13 --

gcc тоже валится. Но стоит слово cr перенести в правильное место и всё работает.

-- Ср апр 16, 2014 19:33:38 --

zvm в сообщении #850523 писал(а):
Компилятор не ругается.


Насколько я знаю язык, конкретно на сам typedef компилятор и не должен ругаться, там вообще всякий треш может быть. Но стоит попытаться этот тип хоть как-то этот тип использовать, например просто создать переменную...

 Профиль  
                  
 
 Re: Вопрос по СИ (не С++)
Сообщение16.04.2014, 18:39 
Заслуженный участник


28/04/09
1933
Legioner93 в сообщении #850530 писал(а):
Переменную вы можете объявить типа cr?
Типа cr не можем (поскольку компиляторы расценивают такую конструкцию как простое объявление структуры cr). Типа struct cr $\text{---}$ можем. Со словом struct Ваш код у меня не компилируется только на clang с флагом -pedantic-errors (gcc и vc код проглатывают).

 Профиль  
                  
 
 Re: Вопрос по СИ (не С++)
Сообщение16.04.2014, 18:50 
Заслуженный участник
Аватара пользователя


28/07/09
1238
EtCetera
Ну это естественно. -pedantic-errors тут отлавливает пустой синоним в typedef, как я понимаю?:)

Проблема в том, что ТС явно не хочет везде тащить слово struct в объявлениях, а хочет использовать именно так:

hubble.tvv в сообщении #850493 писал(а):
Код:
cr CR1[] = {{fl_1, "string_1"},
{fl_2, "string_2"},
{fl_3, "string_3"}};

А если так, то его использование typedef неправильно.

-- Ср апр 16, 2014 19:54:02 --

А если везде тащить struct cr, то слово typedef тогда можно и нужно выкинуть.

 Профиль  
                  
 
 Re: Вопрос по СИ (не С++)
Сообщение16.04.2014, 19:18 
Заслуженный участник


28/04/09
1933
Legioner93 в сообщении #850545 писал(а):
Ну это естественно. -pedantic-errors тут отлавливает пустой синоним в typedef, как я понимаю?:)
В том-то и дело, что gcc даже с таким флагом не отлавливает. Только clang. Лично я согласен с clang'ом, но по стандарту этот код может оказаться и вполне правильным:
Стандарт языка C99 в 1-м абзаце параграфа 6.7.1 "Storage-class specifiers" писал(а):
storage-class-specifier:
typedef
extern
static
auto
register
Стандарт языка C99 в 3-м абзаце параграфа 6.7.1 "Storage-class specifiers" писал(а):
The typedef specifier is called a ‘‘storage-class specifier’’ for syntactic convenience only; it is discussed in 6.7.7.
Т.е. с синтаксической точки зрения typedef расценивается как спецификатор класса памяти.

 Профиль  
                  
 
 Re: Вопрос по СИ (не С++)
Сообщение16.04.2014, 22:48 
Заслуженный участник
Аватара пользователя


30/01/06
72407

(Оффтоп)

Вот любители обсуждать заточку мечей... :-)

 Профиль  
                  
 
 Re: Вопрос по СИ (не С++)
Сообщение17.04.2014, 07:30 
Заслуженный участник


02/08/11
7013
Код валится потому что тот CR1, который вы объявили и проинициализировали, и тот CR1, который внутри US_1, никак не связаны. В результате указатель sCR оказывается нулём (поскольку глобальные переменные забиваются по дефолту нулями) и при попытке получить доступ к нему всё падает.

И да, перепишите typedef'ы нормально, а то выглядит как упражнение в извращённом программировании.

 Профиль  
                  
 
 Re: Вопрос по СИ (не С++)
Сообщение18.04.2014, 13:42 


16/04/14
3
Legioner93 в сообщении #850545 писал(а):
Проблема в том, что ТС явно не хочет везде тащить слово struct в объявлениях, а хочет использовать именно так:

Да, именно поэтому.
Legioner93 в сообщении #850545 писал(а):
А если так, то его использование typedef неправильно.

Либо я не правильно смотрю, когда пытаюсь разобраться со структурами, либо не врубаюсь почему не правильно.
warlock66613 в сообщении #850716 писал(а):
Код валится потому что тот CR1, который вы объявили и проинициализировали, и тот CR1, который внутри US_1, никак не связаны. В результате указатель sCR оказывается нулём (поскольку глобальные переменные забиваются по дефолту нулями) и при попытке получить доступ к нему всё падает.

Вроде ведь связаны?
В переменной US_1 поля из массива CR1[3]; является вложенной структурой. Для доступа к полю вложенной структуры сначала обращаюсь к внешней структуре US_1, затем к вложенной CR1[1].
Никак не въеду в структуры.

 Профиль  
                  
 
 Re: Вопрос по СИ (не С++)
Сообщение18.04.2014, 15:14 


16/04/14
3
warlock66613 в сообщении #850716 писал(а):
Код валится потому что тот CR1, который вы объявили и проинициализировали, и тот CR1, который внутри US_1, никак не связаны. В результате указатель sCR оказывается нулём (поскольку глобальные переменные забиваются по дефолту нулями) и при попытке получить доступ к нему всё падает.

P.S. Упростил до "не могу" пример. И получается, скорее всего, как вы и сказали.
Код:
// Вначале описываю внутреннюю структуру с именем cr
struct cr {
   char flCR;
   char *sCR;
};
// Объявляю и инициализирую структурную переменную CR1
struct cr CR1 = {2, "string_1"};

// Затем описываю внешнюю структуру с именем us
struct us {
   char flInt1;
   char flGlobal;
   struct cr CR1;   // Вложенная структура
};
// Объявляю структурную переменную US_1
struct us US_1;
/************************************************/
int main(void)
{
   char ch;

   ch = US_1.CR1.flCR;   // Вот здесь результат - 0
   ch = CR1.flCR;        // А здесь правильный - 2

   return ch;
}

Компиляция идет. Отладка идет. Но возращает результат - 0 вместо 2.
Ну я полностью запутался. Логика моих рассуждений в комментах верна? Где же ошибка? Как задействовать внешнюю структуру?

 Профиль  
                  
 
 Re: Вопрос по СИ (не С++)
Сообщение18.04.2014, 15:29 
Заслуженный участник
Аватара пользователя


28/07/09
1238
Вы понимаете, что это ваше
Код:
struct cr CR1 = {2, "string_1"};
никак не связано с полем CR1 в структуре us? Компилятор позволяет им иметь одинаковые имена, потому что по контексту их невозможно перепутать.

-- Пт апр 18, 2014 16:43:32 --

hubble.tvv в сообщении #851325 писал(а):
Как задействовать внешнюю структуру?

Наконец взять и объявить US_1, о чем вам неоднократно уже сказали. Лучше нормально, но можно и просто так
Код:
US_1.CR1=CR1

Мне такой код решительно не нравится, но решать вам.

И ещё тут есть тонкость, которая всё может испортить. При таком присваивании вы скопируете указатель на строку "string_1", а не саму строку. Это не плохо и не хорошо - просто помните об этом.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 13 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group