Перейти к содержанию
    

Обращение к элементу двухмерного массива используя адрес массива

В Си массивы и указатели почти эквивалентные понятия. Используется одна и та же адресная арифметика

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Я согласен с вашими словами, однако, массив обрабатывается обычно именно по его адресу и индексу. Т.е., например, в каждом шаге цикла, обрабатывающего массив, вычисляется адрес элемента массива, с использованием адреса начала массива и индекса.

Если указатель можно просто перемещать по элементам массива (адресная арифметика), то при индексной арифметике адрес элемента массива нужно вычислить по адресу начала массива и индексу элемента, для этого задействовать некую временную переменную (регистр микропроцессора). Для ARM, к примеру, эта операция выполняется в одной команде, а для PIC16 команд потребуется несколько.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В Си массивы и указатели почти эквивалентные понятия. Используется одна и та же адресная арифметика
Это справедливо только для случая массива и указателя на элемент массива. Различие заключается в том, что массив состоит из элементов одинаковой размерности, а указатель можно использовать для обращения и к элементам объектов с более сложным устройством - структуры, например. Элементы структуры могут иметь совершенно разную размерность и в т.ч. включать в себя те же массивы. Для обращения к структуре недостаточно знать только лишь ее базовый адрес, нужно знать и ее внутреннее устройство, чтобы правильно вычислять значение указателя.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какая разница? Массив тоже может состоять из структур.
Разница проявляется при вычислении значения указателя. Массив структур формально ничем не отличается от массива байт или слов - в массиве все элементы одинаковые по размеру. Если бы массивы и структуры были суть одно и то же, но какой смысл было вводить новые абстракции? ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Найдите мне теперь любое действие, которое я могу выполнить с ptr и не могу выполнить с array. Или наоборот.

Если бы имя массива было эквивалентно адресу на его первый элемент, то компилятор не ругался бы на это

 

u08 massiv[100];
u08 *ptr = massiv;

 

однако компилятор ругается и требует так

u08 massiv[100];
u08 *ptr = &massiv[0];

 

========

upd

Проверил, ИАР не ругается.

Изменено пользователем GetSmart

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

однако компилятор ругается и требует так

Теоретически, компилятор ругаться не должен. Потому что в книжках написано, что имя массива есть адрес его первого элемента. Так же, как имя функции есть адрес входа в эту функцию.

Сергей Борщ прав, когда говорит, что операции с ptr и array одинаково допустимы. Разница в том, как это будет реализовано при обработке всего массива.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Я удивляюсь, что вы подвергаете сомнению азбучные истины :) О, заметил, вы уже исправились :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По поводу массив/указатель уже где то тут выясняли. Для компилятора они НЕ ЯВЛЯЮТСЯ одинаковыми сущностями. Пример:

1й С файл

char msg[]="Hello, world!";

1й С файл

extern char* msg;
main()
{
  puts(msg);
}

Скомпилите, слинкуйте, запустите и наслаждайтесь :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Разница проявляется при вычислении значения указателя. Массив структур формально ничем не отличается от массива байт или слов - в массиве все элементы одинаковые по размеру. Если бы массивы и структуры были суть одно и то же, но какой смысл было вводить новые абстракции? ;)
Я вас не понимаю. В массиве все элементы одинаковые по размеру. Бесспорно. Но точно также одинаковы по размеру и *ptr и *(ptr + 1) и *(ptr + n). Указатель указывает на данные совершенно определенного и всегда одного и того же типа типа независимо от того, куда именно он указывает. Более того, увеличивая указатель на 1 содержащийся в нем адрес увеличивается ровно на столько же, насколько отличаются адреса соседних элементов массива из данных того же типа. И в обоих случаях с учетом выравнивания. Нету разницы в вычислении адреса. Или приведите пример.

 

Для компилятора они НЕ ЯВЛЯЮТСЯ одинаковыми сущностями. Пример:
По поводу объявления/инициализации была оговорка.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

 

По поводу объявления/инициализации была оговорка.
В случает ТС разница между *** и **[] будет катастрофическая

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ВСЕ ОСТАЛЬНЫЕ операции на самом деле производятся именно с этим указателем.
Совершенно верно. Вот цитата из стандарта, желающие могут поспорить с ним:
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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Решил сравнить адресную и индексную арифметику на приведенном выше своем примере.

;;;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.

В любом случае, эти два способа работают по-разному.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...