|
Использование offsetof, что то не получается. |
|
|
|
Jan 24 2016, 02:59
|

извечный пессимист
    
Группа: Свой
Сообщений: 1 113
Регистрация: 9-10-06
Из: Днепропетровск
Пользователь №: 21 125

|
Итак имеем структуру для теста: CODE struct { uint16_t data0; uint16_t data1; uint16_t data2; uint16_t data3; uint16_t data4; uint16_t data5; }Data_test;
static uint8_t number; Далее в программе пытаюсь посмотреть: CODE number = offsetof(Data_test, data0); Получаю в ответ: CODE Error[Pe029]: expected an expression C:\Project for ARM\LBR004_V1\Sources\main.c 69 Error[Pe028]: expression must have a constant value C:\Project for ARM\LBR004_V1\Sources\main.c 69 Error[Pe018]: expected a ")" C:\Project for ARM\LBR004_V1\Sources\main.c 69
Компилятор IAR ARM, статьи читал, что делаю не так, или я чего то не понял?
--------------------
Slaves are those of this world Given freedom to lay chains upon The Master The wolf is no longer free Release the chains and come for me
|
|
|
|
|
Jan 24 2016, 12:21
|

извечный пессимист
    
Группа: Свой
Сообщений: 1 113
Регистрация: 9-10-06
Из: Днепропетровск
Пользователь №: 21 125

|
Цитата(GetSmart @ Jan 24 2016, 08:33)  Можно попробовать написать number = offsetof(struct name1, data0);
Естественно, имя name1 лучше заменить на более подходящее.
Уточню, что в компиляторе не проверял. Может быть заругается, т.к. не реализовали. В хидере stddef.h макрос описан так: CODE #define offsetof(T, member) (__INTADDR__((&((T *)0)->member))) Пробовал и такой способ - number = offsetof(struct name1, data0); , то же ругается - Error[Pe393]: pointer to incomplete class type is not allowed. В статьях люди его используют, точно в так же как и я пытаюсь, но вот результат почему - то разный
--------------------
Slaves are those of this world Given freedom to lay chains upon The Master The wolf is no longer free Release the chains and come for me
|
|
|
|
|
Jan 24 2016, 13:16
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Вариант из первого поста этой ветки будет работать, но далеко не во всех компиляторах. например https://ru.wikipedia.org/wiki/Stddef.hЦитата Современные компиляторы реализуют макрос с помощью встроенных функций. Например, реализация gcc выглядит следующим образом[3]:
#define offsetof( st, m ) __builtin_offsetof( st, m ) Точнее может работать. Если в стандарте соответствующей ревизии или расширении, которое поддерживает компилятор внятно написано, что offsetof первым аргументом принимает не только типы, но и переменные.
Сообщение отредактировал GetSmart - Jan 24 2016, 13:26
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jan 24 2016, 13:28
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Полное объявление типа структуры выглядит так: Код typedef struct { здесь список членов } имя_типа; В плюсах есть более короткая запись Код struct имя_типа { здесь список членов }; После такого объявления компилятор знает имена, размеры и взаимное расположение членов и вы можете использовать offsetof: Код n = offsetof(имя_типа, имя_члена); Просто объявление struct имя_типа; - неполное (incomplete) объявление типа. После такого объявления компилятор знает, что где-то будет объявлен такой тип и что этот тип будет структурой. Что будет в этой структуре он не знает, максимум, что он может вам позволить после такого объявления - объявить указатель на эту структуру и присваивания с этим указателем. Ни содержания этой структуры, ни размера ее он не знает, поэтому даже инкремента или декремента такого указателя он сделать не может, не говоря уже о доступе к членам этой структуры. объявление struct { список членов } имя; объявляет структуру безымянного типа и переменную "имя" этого типа. Поэтому вы не можете использовать "имя" в offsetof, ибо это имя переменной, а не типа. В обычных Сях возможно объявление struct имя_типа { здесь список членов } имя_переменой; Здесь имя_типа - тоже неполное объявление типа, оно позволяет вставить в структуру указатель на нее же (используется для организации связанных списков), но не более того. В первом сообщении темы нужно было объявить тип структуры и переменную этого типа: Код typedef struct { uint16_t data0; uint16_t data1; uint16_t data2; uint16_t data3; uint16_t data4; uint16_t data5; }data_test;
data_test Data_test; struct data_test Data_test1; //можно и так, но тут ключевое слово struct избыточно И вот после этого можно было использовать offsetof(): Код number = offsetof(data_test, data0); // тут используется имя типа "data_test", а не имя переменной!
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 24 2016, 13:34
|

извечный пессимист
    
Группа: Свой
Сообщений: 1 113
Регистрация: 9-10-06
Из: Днепропетровск
Пользователь №: 21 125

|
Цитата(GetSmart @ Jan 24 2016, 18:16)  Вариант из первого поста этой ветки будет работать, но далеко не во всех компиляторах. например https://ru.wikipedia.org/wiki/Stddef.hТочнее может работать. Если в стандарте соответствующей ревизии или расширении, которое поддерживает компилятор внятно написано, что offsetof первым аргументом принимает не только типы, но и переменные. Спасибо что пнули в нужном направлении, никак не мог понять, что действительно нужен тип объекта, а не его реалзация, вот нормально получилось: CODE typedef struct { uint16_t data0; uint16_t data1; uint16_t data2; uint16_t data3; uint16_t data4; uint16_t data5; }Data_test_t;
Data_test_t Data_test; Далее - CODE number = offsetof(Data_test_t, data5); number = 10, как и должно быть, проверил еще на целевом union (для которого все затевалось), то же работает. Спасибо! Но опять же получается это именно фишка IARа?
--------------------
Slaves are those of this world Given freedom to lay chains upon The Master The wolf is no longer free Release the chains and come for me
|
|
|
|
|
Jan 24 2016, 13:40
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(Сергей Борщ @ Jan 24 2016, 17:28)  Полное объявление типа структуры выглядит так: Код typedef struct { здесь список членов } имя_типа; В плюсах есть более короткая запись Код struct имя_типа { здесь список членов }; Полное объявление как раз состоит из двух имён. И после такого полного объявления хоть типа, хоть сразу переменной можно ниже по тексту создавать такие же переменные. То есть после такого полного объявления выше по коду можно объявлять так Код struct name1 var1,var2; Смысл первого имени в объявлении структур, юнионов и энумов, а так же здесь указанных переменных, интересно, как иначе можно толковать. упд Цитата В обычных Сях возможно объявление struct имя_типа { здесь список членов } имя_переменой; Здесь имя_типа - тоже неполное объявление типа, оно позволяет вставить в структуру указатель на нее же (используется для организации связанных списков), но не более того. Возможно более. Т.к. и вне структуры можно создавать через первое имя переменные с типом этой структуры. А это значит, что пара struct name1 должна означать (преобразовываться в) тип структуры и по логике должна съедаться во всех местах, принимающих тип. В т.ч. в type-cast. Иначе это какая-то необоснованная кастрация.
Сообщение отредактировал GetSmart - Jan 24 2016, 13:50
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jan 24 2016, 13:50
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(GetSmart @ Jan 24 2016, 15:40)  Полное объявление как раз состоит из двух имён. И после такого полного объявления хоть типа, хоть сразу переменной можно ниже по тексту создавать такие же переменные. Не совсем понял, а может и я неточно выразился. Да, после такого объявления можно писать struct name1 var1,var2;, а вот писать name1 var1,var2; нельзя, то есть name1 как бы еще не совсем тип. Полным типом он станет в сочетании с ключевым словом struct и мне кажется проще написать один раз typedef, чем засорять потом весь остальной исходник дополнительным struct в каждом месте, где нужно упомянуть тип.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 24 2016, 13:55
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(Сергей Борщ @ Jan 24 2016, 17:50)  Полным типом он станет в сочетании с ключевым словом struct... Станет. Должен становиться. Но у ИАРа видимо своё мнение на этот счёт. упд То есть логичнее всего считать первое имя типом структуры из области видимости слова struct. И пара struct name1 должна преобразовываться в полноценный тип, съедаемый везде.
Сообщение отредактировал GetSmart - Jan 24 2016, 14:11
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jan 24 2016, 14:02
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(GetSmart @ Jan 24 2016, 15:55)  Станет. Должен становиться. Но у ИАРа видимо своё мнение на этот счёт. ГЦЦ согласен с ИАРом. Точнее они оба согласны со стандатром, но вам виднее: Код // test.c: struct a { int A; } A;
a B; Код Compiling: test.c test.c:7:1: error: unknown type name 'a' a B; ^ P.S. поправил, для полного совпадения
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|