реклама на сайте
подробности

 
 
> Ламерской вопрос, массив unsigned char
Fortune
сообщение Feb 8 2007, 11:10
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 75
Регистрация: 1-02-07
Из: Украина
Пользователь №: 24 940



Я с ARM еще не работал, но у меня появились вопросы.
Если обьявить массив типа unsigned char в ОЗУ
сколько будет занимать один элемент в памяти?
Можно ли сделать так, чтобы он занимал 1 байт?
Если нет, то как легче всего это сделать программно.
Go to the top of the page
 
+Quote Post
4 страниц V  < 1 2 3 4 >  
Start new topic
Ответов (15 - 29)
DASM
сообщение Feb 8 2007, 15:51
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



"Массив char в физической памяти будет лежать так, как на это указывает #pragma pack, то бишь выравнивание, если 4, то каждый элемент массива будет расположен с адреса, кратного 4, то есть занимать 4 байта."
Давайте оставим впокое физическую память, будем говорить про память, адресуемую по скажем [R0] и пусть сама эта память лежит где хочет.
Так вот я утверждаю, что при инкременте R0 на единицу мы получаем доступ к следущему элементу массива. И никакие прагмы паки тут совершенно роли не играют. Не так ?
pragma pack является директивой выравнивания структур, она не имеет отношения к массивам. По крайней мере в части их размещения
Go to the top of the page
 
+Quote Post
Demeny
сообщение Feb 8 2007, 16:30
Сообщение #17


Знающий
****

Группа: Свой
Сообщений: 648
Регистрация: 11-02-06
Из: Санкт-Петербург
Пользователь №: 14 237



Цитата(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. Это непринципиально. И обсуждалось уже здесь


--------------------
Сделано в Китае. Упаковано в России.
Go to the top of the page
 
+Quote Post
DASM
сообщение Feb 8 2007, 16:39
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



И что ? Вы хотите сказать, что вашим шаманством я могу сделать такое -
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."
Go to the top of the page
 
+Quote Post
Alex03
сообщение Feb 8 2007, 17:02
Сообщение #19


Местный
***

Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034



Цитата(Demeny @ Feb 8 2007, 16:56) *
Вы оба неправы, господа. Этим занимается аппаратно контроллер памяти (неважно какой, SDRAM, SRAM, DDR) - все эти дела совершенно прозрачны для программиста и для процессора, исполняющего команды программиста. smile.gif

ИМХО тут неправы Вы. Для программиста не так уж и всё прозрачно, если конечно он не на бейсике пишет.
Цитата
Обратите внимание - несмотря на то, что разрядность шины данных процессора увеличивается (от 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 причёсывать.
Go to the top of the page
 
+Quote Post
DASM
сообщение Feb 8 2007, 17:05
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



SSE4 это хорошо... а что с моим вопросом ?
Go to the top of the page
 
+Quote Post
Demeny
сообщение Feb 8 2007, 17:09
Сообщение #21


Знающий
****

Группа: Свой
Сообщений: 648
Регистрация: 11-02-06
Из: Санкт-Петербург
Пользователь №: 14 237



Цитата(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 разрядной памяти при доступе к каждому элементу? Если, по Вашему, невозможно применить выравнивание к массивам ...


--------------------
Сделано в Китае. Упаковано в России.
Go to the top of the page
 
+Quote Post
DASM
сообщение Feb 8 2007, 17:12
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



мы по прежнему друг друга не понимаем. Не можете. Можно указать что начальный адрес массивы будет с адреса кратного 4, но все char - ы в нем будут идти ПОСЛЕДОВАТЕЛЬНО и адрес последнего элемента будет N + (200000-1)
Перефразирую так. Имеем линейную память. 0,1,2,3,4,5,6,7....
Вы можете вашими директивами расположить массив чаров так, что [0] лежал в 0-й ячейке, а [1] в 4-ой ячейке ? Я утверждаю что нет
Go to the top of the page
 
+Quote Post
Demeny
сообщение Feb 8 2007, 17:23
Сообщение #23


Знающий
****

Группа: Свой
Сообщений: 648
Регистрация: 11-02-06
Из: Санкт-Петербург
Пользователь №: 14 237



Цитата(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?


--------------------
Сделано в Китае. Упаковано в России.
Go to the top of the page
 
+Quote Post
DASM
сообщение Feb 8 2007, 17:25
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



через 13 байт. Слитно. Массива !
Будем продолжать спор, я пока что на RVDS и IAR проверил (вот дожил, очевидное проверять), и , естественно убедился, что в массиве структур никакого паддинга между элементами массива не будет
Go to the top of the page
 
+Quote Post
Demeny
сообщение Feb 8 2007, 17:31
Сообщение #25


Знающий
****

Группа: Свой
Сообщений: 648
Регистрация: 11-02-06
Из: Санкт-Петербург
Пользователь №: 14 237



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

Попробую.


--------------------
Сделано в Китае. Упаковано в России.
Go to the top of the page
 
+Quote Post
Kail
сообщение Feb 8 2007, 18:03
Сообщение #26


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 3-08-06
Пользователь №: 19 285



Цитата(DASM @ Feb 8 2007, 17:25) *
через 13 байт. Слитно. Массива !
Будем продолжать спор, я пока что на RVDS и IAR проверил (вот дожил, очевидное проверять), и , естественно убедился, что в массиве структур никакого паддинга между элементами массива не будет

А вы смотрели на расположение в ROM или после инициализации в RAM? Насколько я понимаю в RAM с выравниваем 4, паддинг будет.
Go to the top of the page
 
+Quote Post
DASM
сообщение Feb 8 2007, 18:07
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



я смотрел в RAM и вообще причем тут ROM-RAM. Удаляем, как не относящееся к делу
Go to the top of the page
 
+Quote Post
Andrew2000
сообщение Feb 8 2007, 19:16
Сообщение #28


Местный
***

Группа: Свой
Сообщений: 421
Регистрация: 25-12-04
Пользователь №: 1 675



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.
....
"
и т.д.
Go to the top of the page
 
+Quote Post
DASM
сообщение Feb 8 2007, 19:20
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



И чего ??? где тут слово array ? Я только structures вижу. Люди, кончайте дурку валять пудрить мозги говорить на разных языках, назовите мне компилятор, который решетом массив разместит
Go to the top of the page
 
+Quote Post
Alex03
сообщение Feb 8 2007, 19:22
Сообщение #30


Местный
***

Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034



По поводу игноригования младших битов адреса в 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 бита адреса слова используются как количество байт на которое циклически сдвигается прочитанное слово.


А с точки зрения голых Сей результат должен быть одинаковый.
Т.ч. ИМХО программер должен много чего знать по части платформы, компилятора и т.д.
Go to the top of the page
 
+Quote Post

4 страниц V  < 1 2 3 4 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 00:43
Рейтинг@Mail.ru


Страница сгенерированна за 0.01514 секунд с 7
ELECTRONIX ©2004-2016