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

 
 
5 страниц V  < 1 2 3 4 5 >  
Reply to this topicStart new topic
> Обращение к элементу двухмерного массива используя адрес массива
ViKo
сообщение Dec 28 2010, 07:26
Сообщение #31


Универсальный солдатик
******

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



Цитата(Сергей Борщ @ Dec 27 2010, 23:58) *
В Си массивы и указатели почти эквивалентные понятия. Используется одна и та же адресная арифметика

Только для массивов имеется две переменные - адрес начала массива и индекс, которые складываются согласно типу переменных массива. А для указателей имеется всего одна переменная - адрес, соответствующий типу переменной, на которую указывает указатель.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 28 2010, 08:00
Сообщение #32


Гуру
******

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



QUOTE (ViKo @ Dec 28 2010, 12:26) *
Только для массивов имеется две переменные - адрес начала массива и индекс, которые складываются согласно типу переменных массива. А для указателей имеется всего одна переменная - адрес, соответствующий типу переменной, на которую указывает указатель.
Для массива имеется одна переменная - адрес начала. И он фактически имеет тип "указатель на тип элемента массива". Индекс появляется при обращении к элементу. При обращении по указателю точно так же можно использовать нотацию обращения к элементу массива как и при обращении к элементу массива можно использовать нотацию указателей. Пример подобных обращений в предыдущем сообщении. Вы можете написать как *b, так и b[0], эти записи совершенно эквивалентны в C. Массив и константный указатель отличаются только на этапе объявления/инициализации. http://www.fredosaurus.com/notes-cpp/array...aspointers.html


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 28 2010, 08:47
Сообщение #33


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 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 команд потребуется несколько.
Go to the top of the page
 
+Quote Post
rezident
сообщение Dec 28 2010, 11:43
Сообщение #34


Гуру
******

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



Цитата(Сергей Борщ @ Dec 28 2010, 02:58) *
В Си массивы и указатели почти эквивалентные понятия. Используется одна и та же адресная арифметика
Это справедливо только для случая массива и указателя на элемент массива. Различие заключается в том, что массив состоит из элементов одинаковой размерности, а указатель можно использовать для обращения и к элементам объектов с более сложным устройством - структуры, например. Элементы структуры могут иметь совершенно разную размерность и в т.ч. включать в себя те же массивы. Для обращения к структуре недостаточно знать только лишь ее базовый адрес, нужно знать и ее внутреннее устройство, чтобы правильно вычислять значение указателя.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 28 2010, 12:56
Сообщение #35


Гуру
******

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



QUOTE (rezident @ Dec 28 2010, 16:43) *
Различие заключается в том, что массив состоит из элементов одинаковой размерности, а указатель можно использовать для обращения и к элементам объектов с более сложным устройством - структуры, например.
Какая разница? Массив тоже может состоять из структур. Теперь я беру константный указатель на эту структуру и присваиваю ему адрес начала этого массива (пишу mystruct * const ptr = array;). Найдите мне теперь любое действие, которое я могу выполнить с ptr и не могу выполнить с array. Или наоборот.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
rezident
сообщение Dec 28 2010, 13:10
Сообщение #36


Гуру
******

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



Цитата(Сергей Борщ @ Dec 28 2010, 20:56) *
Какая разница? Массив тоже может состоять из структур.
Разница проявляется при вычислении значения указателя. Массив структур формально ничем не отличается от массива байт или слов - в массиве все элементы одинаковые по размеру. Если бы массивы и структуры были суть одно и то же, но какой смысл было вводить новые абстракции? wink.gif
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Dec 28 2010, 14:43
Сообщение #37


.
******

Группа: Участник
Сообщений: 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


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 28 2010, 15:08
Сообщение #38


Универсальный солдатик
******

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



Цитата(GetSmart @ Dec 28 2010, 19:43) *
однако компилятор ругается и требует так

Теоретически, компилятор ругаться не должен. Потому что в книжках написано, что имя массива есть адрес его первого элемента. Так же, как имя функции есть адрес входа в эту функцию.
Сергей Борщ прав, когда говорит, что операции с ptr и array одинаково допустимы. Разница в том, как это будет реализовано при обработке всего массива.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Dec 28 2010, 15:21
Сообщение #39


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



В книжках так же пишут, что детей находят в капусте sm.gif


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 28 2010, 16:26
Сообщение #40


Универсальный солдатик
******

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



Цитата(GetSmart @ Dec 28 2010, 20:21) *
В книжках так же пишут, что детей находят в капусте sm.gif

Ну, вот пример специально для вас. 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|

Я удивляюсь, что вы подвергаете сомнению азбучные истины sm.gif О, заметил, вы уже исправились sm.gif
Go to the top of the page
 
+Quote Post
XVR
сообщение Dec 28 2010, 16:51
Сообщение #41


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



По поводу массив/указатель уже где то тут выясняли. Для компилятора они НЕ ЯВЛЯЮТСЯ одинаковыми сущностями. Пример:
1й С файл
Код
char msg[]="Hello, world!";

1й С файл
Код
extern char* msg;
main()
{
  puts(msg);
}
Скомпилите, слинкуйте, запустите и наслаждайтесь sm.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 28 2010, 17:14
Сообщение #42


Гуру
******

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



QUOTE (rezident @ Dec 28 2010, 18:10) *
Разница проявляется при вычислении значения указателя. Массив структур формально ничем не отличается от массива байт или слов - в массиве все элементы одинаковые по размеру. Если бы массивы и структуры были суть одно и то же, но какой смысл было вводить новые абстракции? wink.gif
Я вас не понимаю. В массиве все элементы одинаковые по размеру. Бесспорно. Но точно также одинаковы по размеру и *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)
Go to the top of the page
 
+Quote Post
XVR
сообщение Dec 28 2010, 17:23
Сообщение #43


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Если подходить строго, то с массивом в С определены всего 2 операции - sizeof от него, и автоматическое преобразование имени массива в указатель на его нулевой элемент. ВСЕ ОСТАЛЬНЫЕ операции на самом деле производятся именно с этим указателем.


Цитата(Сергей Борщ @ Dec 28 2010, 23:14) *
По поводу объявления/инициализации была оговорка.
В случает ТС разница между *** и **[] будет катастрофическая

Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 28 2010, 17:25
Сообщение #44


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 28 2010, 17:55
Сообщение #45


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 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.
В любом случае, эти два способа работают по-разному.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 18th July 2025 - 05:10
Рейтинг@Mail.ru


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