|
|
  |
Обращение к элементу двухмерного массива используя адрес массива |
|
|
|
Dec 28 2010, 08:47
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(Сергей Борщ @ Dec 28 2010, 13:00)  Для массива имеется одна переменная - адрес начала. И он фактически имеет тип "указатель на тип элемента массива". Индекс появляется при обращении к элементу. При обращении по указателю точно так же можно использовать нотацию обращения к элементу массива как и при обращении к элементу массива можно использовать нотацию указателей. Пример подобных обращений в предыдущем сообщении. Вы можете написать как *b, так и b[0], эти записи совершенно эквивалентны в C. Массив и константный указатель отличаются только на этапе объявления/инициализации. http://www.fredosaurus.com/notes-cpp/array...aspointers.htmlЯ согласен с вашими словами, однако, массив обрабатывается обычно именно по его адресу и индексу. Т.е., например, в каждом шаге цикла, обрабатывающего массив, вычисляется адрес элемента массива, с использованием адреса начала массива и индекса. Если указатель можно просто перемещать по элементам массива (адресная арифметика), то при индексной арифметике адрес элемента массива нужно вычислить по адресу начала массива и индексу элемента, для этого задействовать некую временную переменную (регистр микропроцессора). Для ARM, к примеру, эта операция выполняется в одной команде, а для PIC16 команд потребуется несколько.
|
|
|
|
|
Dec 28 2010, 14:43
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(Сергей Борщ @ Dec 28 2010, 20:56)  Найдите мне теперь любое действие, которое я могу выполнить с ptr и не могу выполнить с array. Или наоборот. Если бы имя массива было эквивалентно адресу на его первый элемент, то компилятор не ругался бы на это Код u08 massiv[100]; u08 *ptr = massiv; однако компилятор ругается и требует так Код u08 massiv[100]; u08 *ptr = &massiv[0]; ======== upd Проверил, ИАР не ругается.
Сообщение отредактировал GetSmart - Dec 28 2010, 15:19
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Dec 28 2010, 16:26
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(GetSmart @ Dec 28 2010, 20:21)  В книжках так же пишут, что детей находят в капусте  Ну, вот пример специально для вас. Keil, STM32. Код static const uint8_t Digit[10] = {'0','1','2','3','4','5','6','7','8','9'}; const uint8_t *pDig = Digit; for (uint32_t i=10; i--; ) GPIOA->ODR = *(pDig++); вот часть листинга после компиляции Код ;;;202 static const uint8_t Digit[10] = {'0','1','2','3','4','5','6','7','8','9'}; ;;;203 const uint8_t *pDig = Digit; 000092 486d LDR r0,|L1.584| ;;;204 for (uint32_t i=10; i--; ) GPIOA->ODR = *(pDig++); 000094 210a MOVS r1,#0xa 000096 4b6d LDR r3,|L1.588| 000098 e003 B |L1.162| |L1.154| 00009a f8102b01 LDRB r2,[r0],#1 00009e f8c3280c STR r2,[r3,#0x80c] |L1.162| 0000a2 1e49 SUBS r1,r1,#1 0000a4 d2f9 BCS |L1.154| Я удивляюсь, что вы подвергаете сомнению азбучные истины  О, заметил, вы уже исправились
|
|
|
|
|
Dec 28 2010, 16:51
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
По поводу массив/указатель уже где то тут выясняли. Для компилятора они НЕ ЯВЛЯЮТСЯ одинаковыми сущностями. Пример: 1й С файл Код char msg[]="Hello, world!"; 1й С файл Код extern char* msg; main() { puts(msg); } Скомпилите, слинкуйте, запустите и наслаждайтесь
|
|
|
|
|
Dec 28 2010, 17:14
|

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

|
QUOTE (rezident @ Dec 28 2010, 18:10)  Разница проявляется при вычислении значения указателя. Массив структур формально ничем не отличается от массива байт или слов - в массиве все элементы одинаковые по размеру. Если бы массивы и структуры были суть одно и то же, но какой смысл было вводить новые абстракции?  Я вас не понимаю. В массиве все элементы одинаковые по размеру. Бесспорно. Но точно также одинаковы по размеру и *ptr и *(ptr + 1) и *(ptr + n). Указатель указывает на данные совершенно определенного и всегда одного и того же типа типа независимо от того, куда именно он указывает. Более того, увеличивая указатель на 1 содержащийся в нем адрес увеличивается ровно на столько же, насколько отличаются адреса соседних элементов массива из данных того же типа. И в обоих случаях с учетом выравнивания. Нету разницы в вычислении адреса. Или приведите пример. QUOTE (XVR @ Dec 28 2010, 21:51)  Для компилятора они НЕ ЯВЛЯЮТСЯ одинаковыми сущностями. Пример: По поводу объявления/инициализации была оговорка.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 28 2010, 17:25
|

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

|
QUOTE (XVR @ Dec 28 2010, 22:22)  ВСЕ ОСТАЛЬНЫЕ операции на самом деле производятся именно с этим указателем. Совершенно верно. Вот цитата из стандарта, желающие могут поспорить с ним: QUOTE 6.3.2.1 Lvalues, arrays, and function designators 3. Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 28 2010, 17:55
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Решил сравнить адресную и индексную арифметику на приведенном выше своем примере. Код ;;;202 static const uint8_t Digit[10] = {'0','1','2','3','4','5','6','7','8','9'}; ;;;203 const uint8_t *pDig = Digit; 000092 4870 LDR r0,|L1.596| ;;;204 for (uint32_t i=10; i; i--) GPIOA->ODR = *(pDig++); 000094 4a70 LDR r2,|L1.600| 000096 210a MOVS r1,#0xa |L1.152| 000098 f8103b01 LDRB r3,[r0],#1 00009c f8c2380c STR r3,[r2,#0x80c] 0000a0 1e49 SUBS r1,r1,#1 0000a2 d1f9 BNE |L1.152| 0000a4 496b LDR r1,|L1.596| ;;;205 for (int32_t j=9; j>=0; j--) GPIOA->ODR = Digit[j]; 0000a6 2009 MOVS r0,#9 |L1.168| 0000a8 5c0b LDRB r3,[r1,r0] 0000aa f8c2380c STR r3,[r2,#0x80c] 0000ae 1e40 SUBS r0,r0,#1 0000b0 d5fa BPL |L1.168| Результат слегка обескуражил. Обращение к элементу массива с помощью индекса занимает меньше байтов. Особенность системы команд ARM. Сравните строки 98 и a8. В любом случае, эти два способа работают по-разному.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|