Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Непонятное значение
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
tolik1
Есть функция:
//====================================================
void LoadLastByte(Xuint8 Data)
{
Xuint32 d=0xFFFFFD00 + Data;
xil_printf("LoadLastByte - %x; Data - %x\r\n",d,Data);
GENERAL_SIMPLE_IO_32_mWriteSlaveReg3(XPAR_CTRLTEMAC_BASEADDR,0,d);
}
//====================================================

Есть вызов этой функции:
//====================================================
Xuint8 i;

LoadLastByte(i);
Переменная не инициализирована...
Результат следующий:

LoadLastByte - FFFF2444; Data - FFFF2744

Вопрос: Если переменная Xuint8 Data - один байт, то почеу значение - FFFF2744?
заранее спасибо.
Rst7
Цитата
Переменная не инициализирована...


Проинициализируйте и не занимайтесь буйней, простите за грубость, иначе Вас могут поджидать еще и не такие перлы. Если же Вас интересует точное поведение компилятора в этом случае, то курите асмовский листинг.
AHTOXA
Сдаётся мне, надо написать
xil_printf("LoadLastByte - %x; Data - %x\r\n",d,(int)Data);
Rst7
Цитата
Сдаётся мне, надо написать


Это компилятор сам приведет. А вот что творится из-за отсутствия инициализации переменной - это никому не известно.
AHTOXA
Цитата(Rst7 @ Jul 24 2009, 15:44) *
Это компилятор сам приведет. А вот что творится из-за отсутствия инициализации переменной - это никому не известно.


Для printf - нет. Ну и всяко в байт, пусть даже трижды неинициализированный, FFFF2744 не влезетsmile.gif

---
Поправка. Надо писать (Xuint32)Data. Потому что %x.
Rst7
Цитата
Для printf - нет.


Во-первых, будет приведен к int'у. Курите передачу параметров в функции с (...) в параметрах.

Цитата
Ну и всяко в байт, пусть даже трижды неинициализированный, FFFF2744 не влезет


Вы на тему посмотрели? Там тип проца указан. Регистры там 32хбитные. А вот в какой момент избавляться от мусора (т.е. вставлять расширение знака или просто and) - это уже компилятор сам решать должен. И в данном контексте смысла компилятору вставлять какое-либо приведение нету.
AHTOXA
Цитата(Rst7 @ Jul 24 2009, 16:05) *
И в данном контексте смысла компилятору вставлять какое-либо приведение нету.


Вы хотите сказать, что при вызове LoadLastByte(Xuint8 Data) компилятор имеет право передавать в старших байтах аргумента всякий мусор?
Rst7
Цитата
Вы хотите сказать, что при вызове LoadLastByte(Xuint8 Data) компилятор имеет право передавать в старших байтах аргумента всякий мусор?


Неа. Он передает там нолики (т.к. это unsigned). Но, т.к. переменная неинициализированна, то он имеет полное право забить болт на этот and. Например, считая, что в регистр уже загруженно правильное значение, не превышающее 256 (если бы перед этим была загрузка непосредственного значения или LBZ из озу).
alx2
Цитата(tolik1 @ Jul 24 2009, 13:33) *
Xuint32 d=0xFFFFFD00 + Data;
xil_printf("LoadLastByte - %x; Data - %x\r\n",d,Data);

Вопрос: Если переменная Xuint8 Data - один байт, то почеу значение - FFFF2744?
Как определен тип Xuint32? Очень похоже на несоответствие типа, требуемого строкой формата, реальному типу переменной d.
AHTOXA
Цитата(Rst7 @ Jul 24 2009, 16:32) *
Неа. Он передает там нолики (т.к. это unsigned). Но, т.к. переменная неинициализированна, то он имеет полное право забить болт на этот and. Например, считая, что в регистр уже загруженно правильное значение, не превышающее 256 (если бы перед этим была загрузка непосредственного значения или LBZ из озу).


При компиляции функции неизвестно, инициализированное будет передано значение или нет. Поэтому, по крайней мере при

Xuint32 d=0xFFFFFD00 + Data;

компилятор должен провести расширение Data до Xuint32. Я так думаю.

А то, что вы пишете, очень напоминает работу IAR с bool из вот этой ветки. За единственным исключением - там программист применил хитрый финт ушами, чтобы добиться подобного.

Поэтому я всё же версию с неправильной интерпретацией параметра printf. Ждём топикстартераsmile.gif

ЗЫ. И интересно на всякий случай посмотреть на объявление Xuint8. Вдруг это пресловутый uint_least8_t? smile.gif
Rst7
Цитата
Я так думаю.


К сожалению, гнуся, да еще и под PPC под рукой нет. Могу показать, как компилит аналогичный код IAR под ARM.

Код
void foo1(const char *, ...);

#pragma optimize=no_inline
void foo2(char c)
{
  unsigned int d=123;
  d=d-c;
  foo1("blabla",d,c);
}


Код
        SECTION `.text`:CODE:NOROOT(2)
        ARM
//  135 void foo2(char c)
//  136 {
//  137   unsigned int d=123;
//  138   d=d-c;
//  139   foo1("blabla",d,c);
foo2:
        MOV      R2,R0
        RSB      R1,R0,#+123
        LDR      R0,??foo2_0    ;; `?<Constant "blabla">`
        B        foo1        ;; tailcall
        DATA
??foo2_0:
        DC32     `?<Constant "blabla">`
//  140 }


Обратите внимание, несмотря на размер переменной 8 бит (char c), компилятор не собирается прочищать какие-либо битики. Просто так договоренно, что этим занимается вызывающая функция.

Правда вот получить из IAR'а такое-же поведения, как и ожидаемое мной у гнуся, не получается - тот хоть и матом орет на неинициализированную переменную, но ноликом ее прочищает. Правда, на малых уровнях оптимизации он этого не делает, но зато втыкает and с мусорным регистром.

В общем, тут все зависит от поведения компилятора при вызове функции с неинициализированным аргументом. Рубль за сто, что там гнусь с регистром, в котором происходит передача параметра, ничего не делает, что летит только мусор...

Более точно нам может ответить топикстартер, показав асмовский листинг своего творения.

Цитата
ЗЫ. И интересно на всякий случай посмотреть на объявление Xuint8. Вдруг это пресловутый uint_least8_t?


Кстати, тоже вариант smile.gif
AHTOXA
Цитата(Rst7 @ Jul 24 2009, 17:40) *
К сожалению, гнуся, да еще и под PPC под рукой нет.

У меня есть под арм (cortex-m3):

Код
uint32_t test2(unsigned char ch)
{
    uint32_t d = 0x00DEAD00 + ch;
    return d;
}

8000594:    b2c3          uxtb    r3, r0
8000596:    4801          ldr    r0, [pc, #4]    (800059c <test2+0x8>)
8000598:    1818          adds    r0, r3, r0
800059a:    4770          bx    lr
800059c:    00dead00     .word    0x00dead00


Гнусь таки чистит лишние битики.

Цитата
Правда вот получить из IAR'а такое-же поведения, как и ожидаемое мной у гнуся, не получается - тот хоть и матом орет на неинициализированную переменную, но ноликом ее прочищает. Правда, на малых уровнях оптимизации он этого не делает, но зато втыкает and с мусорным регистром.

Ну это тоже вариант. Компилятор гарантирует, что в переменной char старшие биты нулевые. Это уже чёткая аналогия с тем bool. Но чтобы и не гарантировал и не чистил - это как-то коряво, имхо.
Цитата
Более точно нам может ответить топикстартер, показав асмовский листинг своего творения.


Да, будем ждатьsmile.gif
Rst7
Цитата
У меня есть под арм (cortex-m3):
...
Гнусь таки чистит лишние битики.


Познавательно. Но еще не факт, чего он там на PPC накомпилит. Походу идея с uint_least8_t/uint_fast8_t не лишена смысла. Топикстартер, ауууу!
scifi
Цитата(AHTOXA @ Jul 24 2009, 15:16) *
При компиляции функции неизвестно, инициализированное будет передано значение или нет. Поэтому, по крайней мере при

Xuint32 d=0xFFFFFD00 + Data;

компилятор должен провести расширение Data до Xuint32. Я так думаю.

А я думаю иначе :-) В стандарте написано: "If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate." Понять это можно по-разному. Но если это понимать так, что у однобайтовых аргументов функции при входе в функцию обязательно надо отсекать лишние биты, то это приведёт к менее компактному и более медленному коду. Кому это надо? Тому разгильдяю, который не хочет инициализировать переменные? Я думаю, не следует идти у него на поводу.
Rst7
Цитата
Кому это надо? Тому разгильдяю, который не хочет инициализировать переменные? Я думаю, не следует идти у него на поводу.


Я именно так и написал. Потом, правда, зачеркнул, решил, что сильно грубо wink.gif
AHTOXA
Цитата(scifi @ Jul 24 2009, 18:54) *
А я думаю иначе :-) В стандарте написано: "If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate." Понять это можно по-разному. Но если это понимать так, что у однобайтовых аргументов функции при входе в функцию обязательно надо отсекать лишние биты, то это приведёт к менее компактному и более медленному коду. Кому это надо? Тому разгильдяю, который не хочет инициализировать переменные? Я думаю, не следует идти у него на поводу.


Понимать это надо так, как написано. Значение неопределено. Но в том же стандарте гарантируется, что значения переменной char находятся в диапазоне CHAR_MIN...CHAR_MAX. Если компилятор, вне зависимости от инициализированности переменной, этого не обеспечивает, это - кривой компилятор.
Как он это делает - это его личное дело. Но делать это он обязан.

Цитата(Rst7 @ Jul 24 2009, 18:59) *
Я именно так и написал. Потом, правда, зачеркнул, решил, что сильно грубо wink.gif


Кстати, подход IAR-а не всегда выиграет. По идее, он должен отсекать лишние биты при каждой записи в переменную. Можно представить ситуации, когда такой подход проиграет отсечению при чтении. Не говоря уж о том, что отсечение при чтении надёжнее.
Rst7
Цитата
Кстати, подход IAR-а не всегда выиграет. По идее, он должен отсекать лишние биты при каждой записи в переменную. Можно представить ситуации, когда такой подход проиграет отсечению при чтении.


При записи в ОЗУ отсечение происходит автоматически. Кстати, как и при чтении. При регистровых операциях оптимизатор точно выбросит лишние отсечения, которые "не пляшут рояли".

Цитата
Можно представить ситуации, когда такой подход проиграет отсечению при чтении.


Очень гипотетическая ситуация, в связи с тем, что количество записей обычно меньше количества чтений.

Цитата
Не говоря уж о том, что отсечение при чтении надёжнее.


Не надо уподобляться Дохтуру. Он тоже тут измышлял, в каких битах надежнее данные хранятся... Забанили нафиг wink.gif
AHTOXA
Цитата(Rst7 @ Jul 24 2009, 19:36) *
При записи в ОЗУ отсечение происходит автоматически. Кстати, как и при чтении. При регистровых операциях оптимизатор точно выбросит лишние отсечения, которые "не пляшут рояли".


Лишь на тех архитектурах, где есть побайтовый доступ к ОЗУ, не правда ли? smile.gif

Цитата
Очень гипотетическая ситуация, в связи с тем, что количество записей обычно меньше количества чтений.


Согласен, потому и написал "можно представить", а не "часто встречаются" smile.gif


Цитата
Не надо уподобляться Дохтуру. Он тоже тут измышлял, в каких битах надежнее данные хранятся... Забанили нафиг wink.gif


Ну, я надеюсь, что я немного более вменяемsmile.gif Я имею в виду, что отсечение при чтении защитит от ситуаций, когда хитрый программист записал что-то в переменную через указатель.
Что до меня лично, я бы не прочь иметь в ГЦЦ ключик, включающий такую оптимизациюsmile.gif
_Pasha
Цитата(AHTOXA @ Jul 24 2009, 16:52) *
когда хитрый программист записал что-то в переменную через указатель. 

Дык и записал в положенный этой переменной младший байт smile.gif
AHTOXA
Цитата(_Pasha @ Jul 25 2009, 05:33) *
Дык и записал в положенный этой переменной младший байт smile.gif


Дык! Но и в неположенные старшие мальца попалоsmile.gif И если компилятор работает исходя из предположения, что там нули, то будет ойsmile.gif

ЗЫ. Я естественно имел в виду не запись через char*, а некий хак, как в теме про bool.
Rst7
Цитата
Лишь на тех архитектурах, где есть побайтовый доступ к ОЗУ, не правда ли?


Вы много знаете архитектур с отсутствием такового?

Цитата
Я имею в виду, что отсечение при чтении защитит от ситуаций, когда хитрый программист записал что-то в переменную через указатель.


Посмотрите, каким образом компилятор извлекает, скажем, байтовую переменную из ОЗУ в 32хбитных архитектурах. Например, для ARM он пользуется LDRB, что приводит к автоматическом маскированию старших бит. На PPC есть аналогичная команда LBZ.

Вот я уже правда не помню (давно не брал я в руки шашек), на большом индейце всех времен и народов (680x0) команда загрузки байта из ОЗУ в регистр типа move.b (Ax),Dy кажется не приводит к прочистке старших бит, посему там надо использовать ext.b Dy после загрузки.

Цитата
Дык! Но и в неположенные старшие мальца попало И если компилятор работает исходя из предположения, что там нули, то будет ой


Да откуда же возьмутся после загрузки с расширением (одной командой в ARM или PPC, или парой в 680x0) там не нули?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.