2014 dxdy logo

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

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




 
 Вопрос по СИ (не С++)
Сообщение16.04.2014, 16:19 
Такой код:
Код:
#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 
Аватара пользователя
Вам не кажется, что US_1 неинициализирована?

 
 
 
 Re: Вопрос по СИ (не С++)
Сообщение16.04.2014, 17:51 
Аватара пользователя
hubble.tvv в сообщении #850493 писал(а):
Код:
typedef struct cr {
   char flCR;
   char *sCR;
};

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


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

 
 
 
 Re: Вопрос по СИ (не С++)
Сообщение16.04.2014, 18:09 
Аватара пользователя
Legioner93 в сообщении #850520 писал(а):
Что? Так нельзя. Спецификатор typedef имеет не такой синтаксис.
Компилятор не ругается. Некрасиво, но можно.

 
 
 
 Re: Вопрос по СИ (не С++)
Сообщение16.04.2014, 18:21 
Аватара пользователя
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 
Legioner93 в сообщении #850530 писал(а):
Переменную вы можете объявить типа cr?
Типа cr не можем (поскольку компиляторы расценивают такую конструкцию как простое объявление структуры cr). Типа struct cr $\text{---}$ можем. Со словом struct Ваш код у меня не компилируется только на clang с флагом -pedantic-errors (gcc и vc код проглатывают).

 
 
 
 Re: Вопрос по СИ (не С++)
Сообщение16.04.2014, 18:50 
Аватара пользователя
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 
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 
Аватара пользователя

(Оффтоп)

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

 
 
 
 Re: Вопрос по СИ (не С++)
Сообщение17.04.2014, 07:30 
Код валится потому что тот CR1, который вы объявили и проинициализировали, и тот CR1, который внутри US_1, никак не связаны. В результате указатель sCR оказывается нулём (поскольку глобальные переменные забиваются по дефолту нулями) и при попытке получить доступ к нему всё падает.

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

 
 
 
 Re: Вопрос по СИ (не С++)
Сообщение18.04.2014, 13:42 
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 
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 
Аватара пользователя
Вы понимаете, что это ваше
Код:
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 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group