Как я могу перейти в положение указателя непосредственно без использования оператора++?
Я работаю с указателем на структуру. Я хочу знать, возможно ли перемещение непосредственно в определенную позицию без использования оператора ++
.
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_SIZE 10
struct dummy{
int id;
char buffer[10];
};
typedef struct dummy dummy_struct;
int main()
{
int i=0;
dummy_struct *ds = malloc(sizeof(dummy_struct)*ARRAY_SIZE);
dummy_struct *iterator = ds;
for(i=0;i<ARRAY_SIZE;i++)
{
iterator->id = i;
sprintf(iterator->buffer,"%d",i);
iterator++;
}
iterator = ds;
for(i=0;i<ARRAY_SIZE;i++)
{
printf("%d:%s:%pn",iterator->id,iterator->buffer,iterator);
iterator++;
}
// I want to access directly to 5th position
iterator = ds + (sizeof(dummy_struct)*5);
printf("5th position %d:%s:%pn",iterator->id,iterator->buffer,iterator);
return 0;
}
Это утверждение
iterator = ds + (sizeof(dummy_struct)*5);
Не работает. Я буду признателен за любое предложение.
3 ответа:
Ну, арифметика указателей чтит тип данных!!
iterator = ds + 5;
Сделает свою работу.
Чтобы уточнить, приведенное выше выражение создаст указатель, переместив его 5 раз, умноженный на размер типа для
ds
, в байтах. Это то же самое, что&(ds[5])
.Для полноты объяснения, почему
iterator = ds + (sizeof(dummy_struct)*5);
неверно, здесь, по сути, вы пытаетесь переместить указатель на элемент с индексом как(sizeof(dummy_struct)*5
, который находится далеко за пределами границ. Примечание пожалуйста, это вызывает неопределенное поведение !! Примечание нижеЦитирование
C11
, Глава §6.5.6/P8Когда выражение, имеющее целочисленный тип, добавляется к указателю или вычитается из него, то результат имеет тип операнда указателя. Если операнд указателя указывает на элемент объект массива, и массив достаточно велик, результат указывает на смещение элемента от исходный элемент такой, что разность индексов результирующего и исходного элементы массива равны целочисленному выражению. Другими словами, если выражение
P
указывает наi
- й элемент объекта массива, выражения(P)+N
(эквивалентно,N+(P)
) и(P)-N
(гдеN
имеет значениеn
) указывают соответственно наi+n
- й иi−n
-й элементы объект array, при условии, что они существуют. [....]И затем, относительно неопределенного поведения, упомянутого выше,
[....] Если оба указателя операнд и тот результат указывает на элементы одного и того же объекта массива или на один из последних объектов массива. элемент массива объекта, оценка не должна производить переполнение; в противном случае, поведение не определено. Если результат указывает на один из последних элементов объекта массива, то не должен использоваться в качестве операнда унарного оператора
*
, который вычисляется.
При этом утверждение
printf()
также ошибочно. У вас есть два спецификатора преобразования, но вы предоставили три аргумента. Это невредный , но бесполезный/бессмысленный.Связанные, из главы §7.21.6.1 / P2,
[...] Если формат исчерпан, а аргументы остаются, то избыточные аргументы являются оцениваются (как всегда), но в остальном игнорируются. [...]
Исходя из этого случая, вы можете непосредственно использовать
printf("5th position %d:%s:\n",ds[5].id,ds[5].buffer);
Поведение
iterator = ds + (sizeof(dummy_struct) * 5);
Является неопределенным, Если вы устанавливаете указатель за один после конечного элемента массива. Вы на самом деле устанавливаете
iterator
на большее количество элементов в массиве, чем вы думаете, с коэффициентомsizeof(dummy_struct)
! Не делай этого.Язык позволяет использовать нотацию
Наконец, обратите внимание, чтоiterator = ds + 5;
. Эта идиоматическая арифметика указателя добавляет5
множествоsizeof(dummy_struct)
к адресуiterator
. Другими словами, компилятор выполняет настройкуsizeof
за вас. Это одна из причин, почему указательная арифметика настолько мощна.*(ds + 5)
эквивалентноds[5]
. Я нахожу, что последнее дает больше ясности при работе с массивами.
Похоже, что вы пытаетесь сделать указатель
iterator
, указывающий на5th
элемент массиваds
. Но это утверждение даст вам неверный результат:Результатомiterator = ds + (sizeof(dummy_struct)*5);
Будет суммарный размер всех элементов структуры
dummy_struct
, умноженный на 5, который будет добавлен к адресу, на который ссылаетсяds
и присвоенiterator
. Таким образом,iterator
может указывать на место в памяти, которое не принадлежит вашей программе. Вам нужно сделать:iterator = ds + 5;
Или вы также можете сделайте:
iterator = &ds[5];