ViKo 1 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба В Си массивы и указатели почти эквивалентные понятия. Используется одна и та же адресная арифметика Только для массивов имеется две переменные - адрес начала массива и индекс, которые складываются согласно типу переменных массива. А для указателей имеется всего одна переменная - адрес, соответствующий типу переменной, на которую указывает указатель. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Только для массивов имеется две переменные - адрес начала массива и индекс, которые складываются согласно типу переменных массива. А для указателей имеется всего одна переменная - адрес, соответствующий типу переменной, на которую указывает указатель.Для массива имеется одна переменная - адрес начала. И он фактически имеет тип "указатель на тип элемента массива". Индекс появляется при обращении к элементу. При обращении по указателю точно так же можно использовать нотацию обращения к элементу массива как и при обращении к элементу массива можно использовать нотацию указателей. Пример подобных обращений в предыдущем сообщении. Вы можете написать как *b, так и b[0], эти записи совершенно эквивалентны в C. Массив и константный указатель отличаются только на этапе объявления/инициализации. http://www.fredosaurus.com/notes-cpp/array...aspointers.html Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Для массива имеется одна переменная - адрес начала. И он фактически имеет тип "указатель на тип элемента массива". Индекс появляется при обращении к элементу. При обращении по указателю точно так же можно использовать нотацию обращения к элементу массива как и при обращении к элементу массива можно использовать нотацию указателей. Пример подобных обращений в предыдущем сообщении. Вы можете написать как *b, так и b[0], эти записи совершенно эквивалентны в C. Массив и константный указатель отличаются только на этапе объявления/инициализации. http://www.fredosaurus.com/notes-cpp/array...aspointers.html Я согласен с вашими словами, однако, массив обрабатывается обычно именно по его адресу и индексу. Т.е., например, в каждом шаге цикла, обрабатывающего массив, вычисляется адрес элемента массива, с использованием адреса начала массива и индекса. Если указатель можно просто перемещать по элементам массива (адресная арифметика), то при индексной арифметике адрес элемента массива нужно вычислить по адресу начала массива и индексу элемента, для этого задействовать некую временную переменную (регистр микропроцессора). Для ARM, к примеру, эта операция выполняется в одной команде, а для PIC16 команд потребуется несколько. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба В Си массивы и указатели почти эквивалентные понятия. Используется одна и та же адресная арифметикаЭто справедливо только для случая массива и указателя на элемент массива. Различие заключается в том, что массив состоит из элементов одинаковой размерности, а указатель можно использовать для обращения и к элементам объектов с более сложным устройством - структуры, например. Элементы структуры могут иметь совершенно разную размерность и в т.ч. включать в себя те же массивы. Для обращения к структуре недостаточно знать только лишь ее базовый адрес, нужно знать и ее внутреннее устройство, чтобы правильно вычислять значение указателя. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Различие заключается в том, что массив состоит из элементов одинаковой размерности, а указатель можно использовать для обращения и к элементам объектов с более сложным устройством - структуры, например.Какая разница? Массив тоже может состоять из структур. Теперь я беру константный указатель на эту структуру и присваиваю ему адрес начала этого массива (пишу mystruct * const ptr = array;). Найдите мне теперь любое действие, которое я могу выполнить с ptr и не могу выполнить с array. Или наоборот. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Какая разница? Массив тоже может состоять из структур.Разница проявляется при вычислении значения указателя. Массив структур формально ничем не отличается от массива байт или слов - в массиве все элементы одинаковые по размеру. Если бы массивы и структуры были суть одно и то же, но какой смысл было вводить новые абстракции? ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 (изменено) · Жалоба Найдите мне теперь любое действие, которое я могу выполнить с ptr и не могу выполнить с array. Или наоборот. Если бы имя массива было эквивалентно адресу на его первый элемент, то компилятор не ругался бы на это u08 massiv[100]; u08 *ptr = massiv; однако компилятор ругается и требует так u08 massiv[100]; u08 *ptr = &massiv[0]; ======== upd Проверил, ИАР не ругается. Изменено 28 декабря, 2010 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба однако компилятор ругается и требует так Теоретически, компилятор ругаться не должен. Потому что в книжках написано, что имя массива есть адрес его первого элемента. Так же, как имя функции есть адрес входа в эту функцию. Сергей Борщ прав, когда говорит, что операции с ptr и array одинаково допустимы. Разница в том, как это будет реализовано при обработке всего массива. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба В книжках так же пишут, что детей находят в капусте :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба В книжках так же пишут, что детей находят в капусте :) Ну, вот пример специально для вас. 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| Я удивляюсь, что вы подвергаете сомнению азбучные истины :) О, заметил, вы уже исправились :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба По поводу массив/указатель уже где то тут выясняли. Для компилятора они НЕ ЯВЛЯЮТСЯ одинаковыми сущностями. Пример: 1й С файл char msg[]="Hello, world!"; 1й С файл extern char* msg; main() { puts(msg); } Скомпилите, слинкуйте, запустите и наслаждайтесь :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Разница проявляется при вычислении значения указателя. Массив структур формально ничем не отличается от массива байт или слов - в массиве все элементы одинаковые по размеру. Если бы массивы и структуры были суть одно и то же, но какой смысл было вводить новые абстракции? ;)Я вас не понимаю. В массиве все элементы одинаковые по размеру. Бесспорно. Но точно также одинаковы по размеру и *ptr и *(ptr + 1) и *(ptr + n). Указатель указывает на данные совершенно определенного и всегда одного и того же типа типа независимо от того, куда именно он указывает. Более того, увеличивая указатель на 1 содержащийся в нем адрес увеличивается ровно на столько же, насколько отличаются адреса соседних элементов массива из данных того же типа. И в обоих случаях с учетом выравнивания. Нету разницы в вычислении адреса. Или приведите пример. Для компилятора они НЕ ЯВЛЯЮТСЯ одинаковыми сущностями. Пример:По поводу объявления/инициализации была оговорка. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Если подходить строго, то с массивом в С определены всего 2 операции - sizeof от него, и автоматическое преобразование имени массива в указатель на его нулевой элемент. ВСЕ ОСТАЛЬНЫЕ операции на самом деле производятся именно с этим указателем. По поводу объявления/инициализации была оговорка.В случает ТС разница между *** и **[] будет катастрофическая Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба ВСЕ ОСТАЛЬНЫЕ операции на самом деле производятся именно с этим указателем.Совершенно верно. Вот цитата из стандарта, желающие могут поспорить с ним: 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Решил сравнить адресную и индексную арифметику на приведенном выше своем примере. ;;;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. В любом случае, эти два способа работают по-разному. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться