Fortune
Feb 8 2007, 11:10
Я с ARM еще не работал, но у меня появились вопросы.
Если обьявить массив типа unsigned char в ОЗУ
сколько будет занимать один элемент в памяти?
Можно ли сделать так, чтобы он занимал 1 байт?
Если нет, то как легче всего это сделать программно.
SergeyDDD
Feb 8 2007, 11:22
все зависит от контроллера памяти и самой памяти где будет массив
Fortune
Feb 8 2007, 11:26
Цитата(SergeyDDD @ Feb 8 2007, 12:22)

все зависит от контроллера памяти и самой памяти где будет массив
Ну например для AT91SAM7S64, если разместить во внутреннем ОЗУ?
При компиляции программы можно указать ключи для выравнивания переменных на границу одного, двух или четырёх байт. Например, при использовании компилятора ICCV7 (Imagecraft) для процессоров ADuC702x и LPC21xx байтовые переменные занимают в памяти 1 байт.
SergeyDDD
Feb 8 2007, 11:57
Цитата(Fortune @ Feb 8 2007, 12:26)

Цитата(SergeyDDD @ Feb 8 2007, 12:22)

все зависит от контроллера памяти и самой памяти где будет массив
Ну например для AT91SAM7S64, если разместить во внутреннем ОЗУ?
Как правило внутреннее ОЗУ поддерживают операции с байтами
А вообще это справочная информация. См. документацию.
А еще проще сходу попробовать на железе
по-моему ерунду говорите. Массив всегда будет расположен ЛИНЕЙНО. Точка. И один char в массиве всегда занимает один байт
PS "по-моему" добавлено только для смягчения фразы, но никак не по причине наличия сомнений ;-)
SergeyDDD
Feb 8 2007, 12:15
Цитата(DASM @ Feb 8 2007, 13:00)

по-моему ерунду говорите. Массив всегда будет расположен ЛИНЕЙНО. Точка. И один char в массиве всегда занимает один байт
PS "по-моему" добавлено только для смягчения фразы, но никак не по причине наличия сомнений ;-)
Почему же ерунду? Проблема может возникнуть с железом, а не с компилятором.
Для примера возьмем EP7312:
ширина шины данных управляется линиями HALFWORD и WORD (думаю назначение понятно).
Для 32 разрядной шины используются линии адреса начиная с A2.
Так вот в такой конфигурации записать байт можно только по адресам 0, 4, 8, 12, 16...
А вот с SDRAM памятью и внутренней (в EP7312) такой проблемы нет.
Значит компилер будет считывать 32-битное значения и выдирать сам байиы, если я правильно Вас понял. Массив в любом случае по адресам будет лежать слитно, иначе вся арифметика указателей летит к чертовой матери вместе с Керниганом и этим.. как его.. Ритчи
SpiritDance
Feb 8 2007, 13:19
Цитата(DASM @ Feb 8 2007, 12:37)

Значит компилер будет считывать 32-битное значения и выдирать сам байиы,
Тут уж, наверно, не компилер, а сам процессор.
не важно кто, важно что для программисты массив линеен без разрывов, и заботиться не надо. Заботиться надо в union когда char или short в него входит и , одновременно, рассматривается как массиы. Тогда pragma pack(1) конечно
IgorKossak
Feb 8 2007, 13:38
Сколько текста!
Сколько времени потрачено!
Неужто в облом написать пример в четыре строки, собрать и посмотреть листинг?
Цитата(SpiritDance @ Feb 8 2007, 13:19)

Цитата(DASM @ Feb 8 2007, 12:37)

Значит компилер будет считывать 32-битное значения и выдирать сам байиы,
Тут уж, наверно, не компилер, а сам процессор.
Вы оба неправы, господа. Этим занимается аппаратно контроллер памяти (неважно какой, SDRAM, SRAM, DDR) - все эти дела совершенно прозрачны для программиста и для процессора, исполняющего команды программиста.
Обратите внимание - несмотря на то, что разрядность шины данных процессора увеличивается (от 8 битных 8088, далее через 16 битные 8086/80286, через 32 битные 80386/Pentium-ы, а теперь есть и 64 битные ...) - ПО КАЖДОМУ АДРЕСУ ПАМЯТИ ЛЕЖИТ РОВНО ОДИН БАЙТ !!!
С точки зрения любого процессора (и программиста) физическая память является линейной структурой байтов, адрес каждого байта уникален и отличается от адреса предыдущего и последующего ровно на единицу.
32 разрядный процессор "хочет" загрузить себе в регистр один байт из адреса 0x123456FF, и его совершенно не волнует, каким образом внешняя память "исполнит его желание". Более того, проц не обязан "знать", что за память расположена по этому адресу. Дальнейшие действия целиком и полностью возложены на контроллер памяти, который всё это "знает". Если память 32 разрядная - будет выполнено ДВА цикла чтения - один по адресу 0x123456FC, другой по адресу 0x12345700, а оставшиеся два младших бита в исходном адресе будут определять, как расположить считанные 8 байт на 32 разрядной шине так, чтобы процесоор "почувствовал", будто он и вправду считал двойное слово с адреса 0x123456FF.
ДВА цикла чтения заменятся на ОДИН цикл в одном случае - если адрес кратен 4. Поэтому у программиста (который, в отличие от процессора, знает свою архитектуру аппаратной части) есть выбор - указать компилятору, как предпочтительнее располагать данные в памяти (align). Хочется сэкономить память - указывай align=1, но тогда при доступе к 3 элементам из 4 будешь "попадать" по времени на ДВА цикла чтения; если памяти море - указывай align=4 (вроде как это по умолчанию), тогда каждый объект массива char будет лежать "как король" в адресах, кратных 4, чтобы не тратить лишнее время на доступ к нему.
Если контроллер памяти очень "умный" - он может сильно ускорять процесс считывания, например, вести кэш, и недавно считанное значение не считывать заново, или при доступе по определённым адресам на чтение/запись генерировать исключения и т. п. Часть этих функций современные процессоры типа Pentium взяли себе на борт (кэш первого уровня, защита памяти и генерация исключений и т п), часть оставили снаружи (кэш второго уровня, разделение RAM/ROM).
ну я собсно и сказал - по барабану кто будет делать, главное что программисту пофик. Зачем забивать себе голову лишними знаниями?
Цитата(DASM @ Feb 8 2007, 15:02)

ну я собсно и сказал - по барабану кто будет делать, главное что программисту пофик. Зачем забивать себе голову лишними знаниями?
А вот это кто сказал ?
Цитата(DASM @ Feb 8 2007, 12:37)

Массив в любом случае по адресам будет лежать слитно, иначе вся арифметика указателей летит к чертовой матери вместе с Керниганом и этим.. как его.. Ритчи
Массив char в физической памяти будет лежать так, как на это указывает #pragma pack, то бишь выравнивание, если 4, то каждый элемент массива будет расположен с адреса, кратного 4, то есть занимать 4 байта.
И Керниган с Ритчи тут ни при чем. И арифметика указателей в порядке. Если Вы прибавите к указателю единицу, прибавка к адресу в машинном коде составит много больше - это зависит от размера элемента, на который указывает этот указатель и от выравнивания. Это уже работа компилятора.
А вот преобразование некратных адресов в адреса памяти (то, о чем я писал в пред. посте) - это работа контроллера памяти.
Это разные и совершенно не связанные вещи.
SpiritDance
Feb 8 2007, 15:49
Ну я то под процессором имел ввиду сам мк, а не собсвенно алу, но за ликбез спасибо. ж)
"Массив char в физической памяти будет лежать так, как на это указывает #pragma pack, то бишь выравнивание, если 4, то каждый элемент массива будет расположен с адреса, кратного 4, то есть занимать 4 байта."
Давайте оставим впокое физическую память, будем говорить про память, адресуемую по скажем [R0] и пусть сама эта память лежит где хочет.
Так вот я утверждаю, что при инкременте R0 на единицу мы получаем доступ к следущему элементу массива. И никакие прагмы паки тут совершенно роли не играют. Не так ?
pragma pack является директивой выравнивания структур, она не имеет отношения к массивам. По крайней мере в части их размещения
Цитата(DASM @ Feb 8 2007, 15:51)

"Массив char в физической памяти будет лежать так, как на это указывает #pragma pack, то бишь выравнивание, если 4, то каждый элемент массива будет расположен с адреса, кратного 4, то есть занимать 4 байта."
Давайте оставим впокое физическую память, будем говорить про память, адресуемую по скажем [R0] и пусть сама эта память лежит где хочет.
Так вот я утверждаю, что при инкременте R0 на единицу мы получаем доступ к следущему элементу массива. И никакие прагмы паки тут совершенно роли не играют. Не так ?
pragma pack является директивой выравнивания структур, она не имеет отношения к массивам. По крайней мере в части их размещения
Зависит от компилятора, размера элемента массива и установленного выравнивания !!!
Если мы говорим о массиве char, размер элемента равен 1.
Если мы установили выравнивание данных, равное 16, то, чтобы получить доступ к следующему элементу массива типа char, Вам в приведенном Вами примере придется увеличить R0 на 16.
В части различия компиляторов -- часть компиляторов применяет #pragma pack только к структурам, при этом для остальных типов у них есть что-то типа #pragma data_align. Это непринципиально. И обсуждалось уже
здесь
И что ? Вы хотите сказать, что вашим шаманством я могу сделать такое -
char data[256];
printf ("%d\r\n" (int) &data[1] - (int) &data[0]);
и получить на экране 16 ? Сообщите пожалуйста такой удивительный компилятор и я посыплю голову пеплом
RVDS на этот счет говорит ясно
"There are no packed array types. A packed array is an array of objects of
packed type. There is no padding in the array."
Цитата(Demeny @ Feb 8 2007, 16:56)

Вы оба неправы, господа. Этим занимается аппаратно контроллер памяти (неважно какой, SDRAM, SRAM, DDR) - все эти дела совершенно прозрачны для программиста и для процессора, исполняющего команды программиста.

ИМХО тут неправы Вы. Для программиста не так уж и всё прозрачно, если конечно он не на бейсике пишет.
Цитата
Обратите внимание - несмотря на то, что разрядность шины данных процессора увеличивается (от 8 битных 8088, далее через 16 битные 8086/80286, через 32 битные 80386/Pentium-ы, а теперь есть и 64 битные ...) - ПО КАЖДОМУ АДРЕСУ ПАМЯТИ ЛЕЖИТ РОВНО ОДИН БАЙТ !!!
На некотором подмножестве из всех имеющихся платформ.
Цитата
С точки зрения любого процессора (и программиста) физическая память является линейной структурой байтов, адрес каждого байта уникален и отличается от адреса предыдущего и последующего ровно на единицу.
Не всегда и не везде.
Цитата
32 разрядный процессор "хочет" загрузить себе в регистр один байт из адреса 0x123456FF, и его совершенно не волнует, каким образом внешняя память "исполнит его желание". Более того, проц не обязан "знать", что за память расположена по этому адресу. Дальнейшие действия целиком и полностью возложены на контроллер памяти, который всё это "знает". Если память 32 разрядная - будет выполнено ДВА цикла чтения - один по адресу 0x123456FC, другой по адресу 0x12345700, а оставшиеся два младших бита в исходном адресе будут определять, как расположить считанные 8 байт на 32 разрядной шине так, чтобы процесоор "почувствовал", будто он и вправду считал двойное слово с адреса 0x123456FF.
На x86 оно реализовано ради совместимости, на очень многих других платформах этого нет. А есть или исключения, или игнорирование младших битов (как в случае с ARM)
К томуже в тех же x86-расширениях (типа MMX/SSE/SSEx) есть команды допускающие только обращение к выравненным данным.
Цитата
Хочется сэкономить память - указывай align=1, но тогда при доступе к 3 элементам из 4 будешь "попадать" по времени на ДВА цикла чтения; если памяти море - указывай align=4 (вроде как это по умолчанию), тогда каждый объект массива char будет лежать "как король" в адресах, кратных 4, чтобы не тратить лишнее время на доступ к нему.
Применительно к char (на х86) чтение будет всегда одно.
PS а архитектуры всякие бывают, не надо всех под гребёнку x86 причёсывать.
SSE4 это хорошо... а что с моим вопросом ?
Цитата(DASM @ Feb 8 2007, 16:39)

И что ? Вы хотите сказать, что вашим шаманством я могу сделать такое -
char data[256];
printf ("%d\r\n" (int) &data[1] - (int) &data[0]);
и получить на экране 16 ? Сообщите пожалуйста такой удивительный компилятор и я посыплю голову пеплом
RVDS на этот счет говорит ясно
"There are no packed array types. A packed array is an array of objects of
packed type. There is no padding in the array."
Ага, я понял. Мы говорим о разных вещах. Вы в приведенном примере путаете УКАЗАТЕЛЬ на элемент и АДРЕС элемента в памяти. Это разные вещи.
Операция & возвращает указатель на элемент, и результат будет равен 1. По сути, указатель - это всего лишь ИНДЕКС элемента в сегменте данных программы. Именно поэтому указатель всегда указывает на вполне ОПРЕДЕЛЁННЫЙ тип данных, чтобы компилятор мог правильным образом обслуживать арифметику указателей. Например,
Код
double * pDouble;
double data[100];
pDouble = &(data[45]);
pDouble = pDouble + 1;
Вас же не удивляет такая операция - указатель увеличился на 1, а указывает уже на 46 элемент массива double (что говорит о том, что адрес сместился на 8). Если Вы отпечатаете pDouble, то увидите, что он действительно увеличился всего на 1.
А изначально Ваш пример содержал регистр процессора R0, на уровне машинных кодов регистр косвенной адресации действительно увеличится на число, зависящее от размера элемента и от выравнивания данных.
Чтобы не продолжать спор, я готов его завершить, если Вы мне скажете, как я могу разместить массив char data[200000] с адресов, кратных 4, чтобы не делать лишнюю работу контроллеру 32 разрядной памяти при доступе к каждому элементу? Если, по Вашему, невозможно применить выравнивание к массивам ...
мы по прежнему друг друга не понимаем. Не можете. Можно указать что начальный адрес массивы будет с адреса кратного 4, но все char - ы в нем будут идти ПОСЛЕДОВАТЕЛЬНО и адрес последнего элемента будет N + (200000-1)
Перефразирую так. Имеем линейную память. 0,1,2,3,4,5,6,7....
Вы можете вашими директивами расположить массив чаров так, что [0] лежал в 0-й ячейке, а [1] в 4-ой ячейке ? Я утверждаю что нет
Цитата(DASM @ Feb 8 2007, 17:12)

мы по прежнему друг друга не понимаем. Не можете. Можно указать что начальный адрес массивы будет с адреса кратного 4, но все char - ы в нем будут идти ПОСЛЕДОВАТЕЛЬНО и адрес последнего элемента будет N + (200000-1)
Перефразирую так. Имеем линейную память. 0,1,2,3,4,5,6,7....
Вы можете вашими директивами расположить массив чаров так, что [0] лежал в 0-й ячейке, а [1] в 4-ой ячейке ? Я утверждаю что нет
Как же , по Вашему, будут идти элементы массива, если размер каждого элемента равен 13, при установленном выравнивании (не важно какой директивой) 16?
через 13 байт. Слитно. Массива !
Будем продолжать спор, я пока что на RVDS и IAR проверил (вот дожил, очевидное проверять), и , естественно убедился, что в массиве структур никакого паддинга между элементами массива не будет
Цитата(DASM @ Feb 8 2007, 17:25)

через 13 байт. Слитно. Массива !
Попробую.
Цитата(DASM @ Feb 8 2007, 17:25)

через 13 байт. Слитно. Массива !
Будем продолжать спор, я пока что на RVDS и IAR проверил (вот дожил, очевидное проверять), и , естественно убедился, что в массиве структур никакого паддинга между элементами массива не будет
А вы смотрели на расположение в ROM или после инициализации в RAM? Насколько я понимаю в RAM с выравниваем 4, паддинг будет.
я смотрел в RAM и вообще причем тут ROM-RAM. Удаляем, как не относящееся к делу
Andrew2000
Feb 8 2007, 19:16
Help на Borland C++ Bulder:
"The Data Alignment options let you choose how the compiler aligns data in stored memory. Word, double word, and quad word alignment force integer-size and larger items to be aligned on memory addresses that are multiples of the type chosen. Extra bytes are inserted in structures to ensure that members align correctly.
...
Byte alignment
When byte alignment is on, the compiler does not force alignment of variables or data fields to any specific memory boundaries. The compiler aligns data at even or odd addresses, depending on the next available address.
While byte alignment produces more compact programs, the programs tend to run slower. The other data alignment options increase the speed at which 80x86 processors fetch and store data.
Word alignment (2-byte)
When word alignment is on, the compiler aligns non-character data at even addresses. Automatic and global variables are aligned properly. char and unsigned char variables and fields can be placed at any address; all others are placed at even-numbered addresses.
Double word (4-byte)
Double word alignment aligns non-character data at 32-bit word (4-byte) boundaries. Data with type sizes of less than four bytes are aligned on their type size.
....
"
и т.д.
И чего ??? где тут слово array ? Я только structures вижу. Люди, кончайте дурку валять пудрить мозги говорить на разных языках, назовите мне компилятор, который решетом массив разместит
По поводу игноригования младших битов адреса в ARM-е я пожалуй погорячился. Всё немного хитрее.
хитрый пример (GCC и LPC2292)
Код
typedef struct __attribute__ ((__packed__))
{
uchar uc;
uint ui;
} test_struct_t;
test_struct_t data[5] =
{
{'A', 0x00010203},
{'B', 0x04050607},
{'C', 0x08090A0B},
{'D', 0x0C0D0E0F},
{'E', 0x10111213}
};
void test()
{
int n;
uint* pui;
uchar* puc;
printf("sizeof(test_struct_t)=%d\n", sizeof(test_struct_t));
printf("sizeof(data)=%d\n", sizeof(data));
printf("sizeof(data[0])=%d\n", sizeof(data[0]));
printf("Loop 1\n");
for(n=0; n<5; n++)
{
printf("%d: %c 0x%08X %p\n", n, data[n].uc, data[n].ui, &data[n].ui);
}
printf("Loop 2\n");
for(n=0; n<5; n++)
{
pui = &data[n].ui;
puc = &data[n].uc;
printf("%d: %c 0x%08X %p\n", n, *puc, *pui, pui);
}
}
Выдаёт:
Код
sizeof(test_struct_t)=5
sizeof(data)=25
sizeof(data[0])=5
А теперь угадайте что выдают на печать первый и второй циклы?
Одно и тоже? Какбы не так:
Код
Loop 1
0: A 0x00010203 4000003d
1: B 0x04050607 40000042
2: C 0x08090A0B 40000047
3: D 0x0C0D0E0F 4000004c
4: E 0x10111213 40000051
Loop 2
0: A 0x41010203 4000003d
1: B 0x42000607 40000042
2: C 0x4304050B 40000047
3: D 0x0C0D0E0F 4000004c
4: E 0x45111213 40000051
В первом случае компилятор знает что элемент data[n].ui не (всегда) выровнен на границу слова, поэтому читает слово ЧЕТЫРМЯ!!! инструкциями ldrb, и из этих 4-х байт "собирает" слово.
Во втором случае компилятор предполагает что pui - указатель на выровненное слово и читает сразу слово командой ldr. И вот тут вылазит особенности ARMа по работе с невыравненными данными. По сути младшие 2 бита адреса слова используются как количество байт на которое циклически сдвигается прочитанное слово.
А с точки зрения голых Сей результат должен быть одинаковый.
Т.ч. ИМХО программер должен много чего знать по части платформы, компилятора и т.д.
"А с точки зрения голых Сей результат должен быть одинаковый."
кто такое сказал ? Ссылку плиз
Andrew2000
Feb 8 2007, 19:30
Цитата(DASM @ Feb 8 2007, 19:20)

И чего ??? где тут слово array ? ... назовите мне компилятор, который решетом массив разместит
При чем тут array? тут даже болише написано:
Word alignment (2-byte)
When word alignment is on, ..... char and unsigned char variables and fields can be placed at _any_ address
ну а вот теперь сделайте из этих variables ARRAY - на каждый элемент будете allign писать ?? Мы говорили про ARRRAY, не надо проблемы половой жизни сусликов в условиях крайнего Севера сюда приплюсовывать уходить от темы
Цитата(DASM @ Feb 8 2007, 21:25)

"А с точки зрения голых Сей результат должен быть одинаковый."
кто такое сказал ? Ссылку плиз
А почему нет то?
Пойдём от противного! Где написано что разименованный указатель на элемент структуры не обязательно равен этому элементу структуры?
да и на x86 или без __attribute__ ((__packed__)) результат вывода циклов будет одинаковый.
ладно, возможно тут и промахнулся, и тем не менее к нашим баранам вернемся, массивам то есть
Цитата(DASM @ Feb 8 2007, 21:53)

ладно, возможно тут и промахнулся, и тем не менее к нашим баранам вернемся, массивам то есть
Про массивы я более придерживаюсь твоей точки зрения, т.е. выравнивание должно распрастраняться только на первый элемент массива.
Но я не буду столь категоричен, ибо ....
tegumay
Feb 8 2007, 20:12
насчет хранения и форматирования данных в памяти это хорошо что затронули тему
только не надо наезжать на святое на контроллер памяти. он работает на кэш. и чем сетка шире тем лучше
данные гонятся пакетами. контроллеру наплевать кто и как положит его задача как положили так и выдать и все. ему си не си наплевать. его задача из микрухи до проца. далше его проца дело
так... еще лучше.. кто глубже копнет :-D
DASM полностью прав!!! НЕ МОЖЕТ компилятор положить массив в памяти с дырками! Это противоречит всем законам языка. Я имею полное право сделать так:
Код
uchar test[10];
void test {
char *ptr;
//Классический вариант:
ptr = test + 5;
//А теперь так:
ptr = (uchar*)((void*)test + 5 * sizeof(uchar));
//И вот так:
ptr = (uchar*)((int)test + 5 * sizeof(uchar));
Кто покажет мне (и DASM'у) хоть один компилятор, у которого эти три варианта будут не одинаковы???
Хочу сказать отдельное спасибо Alex03 за правильное предупреждение, т.к. доступ через указатель к переменной, не выровненной по умолчанию на архитектуре АРМ может работать некорректно. Я с этим еще не сталкивался, но словив такой глюк, можно долго проблемы разгребать
Andrew2000
Feb 9 2007, 01:36
Цитата(DASM @ Feb 8 2007, 19:38)

ну а вот теперь сделайте из этих variables ARRAY - .... не надо .... уходить от темы
Как раз не ухожу, а наоборот: если уж при "Word alignment" компилятор будет "char variables and fields can be placed at _any_ address", то о каких дырах в массиве может идти речь.
(но это конкретный компилятор, допускаю, что есть специфические, может для DSP каких, где компилятору "удасться" сделать дыры, но я таких не знаю).
Цитата(gladov @ Feb 9 2007, 00:18)

Хочу сказать отдельное спасибо Alex03 за правильное предупреждение, т.к. доступ через указатель к переменной, не выровненной по умолчанию на архитектуре АРМ может работать некорректно. Я с этим еще не сталкивался, но словив такой глюк, можно долго проблемы разгребать

Угу,

Мне вот интересно что выдаёт первый цикл из моего примера на других компиляторах?
Кому не лень попробуйте на всяких IAR/Keil/RVDS? Только упаковку (например pragm pack(1) вместо __attribute__ ((__packed__))) надо подправить чтобы sizeof(test_struct_t)=5 было.
Интуиция мне говорит что возможно не все компиллеры такие разборчивые в этом плане как GCC.
SpiritDance
Feb 9 2007, 10:08
Блин, сразу видно - DASM вернулся на форум. Ж) Из ничего флейма на 3 странички. С возвращением! Ж))
Цитата(Alex03 @ Feb 9 2007, 07:05)

Мне вот интересно что выдаёт первый цикл из моего примера на других компиляторах?
Кому не лень попробуйте на всяких IAR/Keil/RVDS? Только упаковку (например pragm pack(1) вместо __attribute__ ((__packed__))) надо подправить чтобы sizeof(test_struct_t)=5 было.
Интуиция мне говорит что возможно не все компиллеры такие разборчивые в этом плане как GCC.

Проверил на ИАР 4.40а. На строки
Код
printf("%d: %c 0x%08X %p\n", n, data[n].uc, data[n].ui, &data[n].ui);
pui = &data[n].ui;
ругается так:
Warning[Pa039]: use of address of unaligned structure member
При работе, первый цикл проходит как положено, а во втором из printf вываливается в обработчик ABORT DATA. Почему тогда в первом случае работает я не понимаю
да вы доки читайте ! тама написано, что это не рулез и так делать и ничего вам не гарантируется !
Сергей Борщ
Feb 9 2007, 11:23
Цитата(gladov @ Feb 9 2007, 09:42)

Почему тогда в первом случае работает я не понимаю

Здесь как раз никакого чуда. Посмотрите в листинг. Компилятор, зная, что поле структуры не выровнено, обращается к полю побайтно и из считанных байтов "склеивает" содержимое поля.
Цитата(gladov @ Feb 9 2007, 12:42)

ругается так:
Warning[Pa039]: use of address of unaligned structure member
При работе, первый цикл проходит как положено, а во втором из printf вываливается в обработчик ABORT DATA. Почему тогда в первом случае работает я не понимаю

Вооо. Какой процик, я так понимаю всяко не LPC.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.