указатель на массив

Я задаюсь вопросом, можно ли сделать указатель на группу переменных в массиве? как это

array[20]{'a','b','c',...}
pointer = array[6 through 10];

таким образом Вы могли сказать...

*pointer[0] == array[6];

и

*pointer[5] == array[10];

и длина *указатель

5 == sizeof(*pointer) \ sizeof(type);

Хорошо

Позвольте мне объяснить, что я пытаюсь выполнить, возможно, который разрешит меня немного. Я хочу считать полный файл в буфер, но я хочу сделать это часть частью. при передаче небольшого массива в чтение () и затем цикличное выполнение это в больший массив побеждает цель. Я надеялся, что мог непосредственно 'указать' на область в буфере, я хочу заполнить, и передать это чтению () функция.

Я НЕ хочу использовать потоки или что-либо, что буферизует за моей спиной

это было бы контрпродуктивно, поскольку я пробую, читает целый файл в память сразу. Максимально быстро.

Мне нужна скорость!!!

5
задан Kelly Elton 15 December 2009 в 10:30
поделиться

10 ответов

Despite what everyone has said, this is possible, with one small caveat - unless you have a C99 compiler, you have to know the size of the "slice" that you want at compile time.

To declare and use the pointer correctly, you also have to know that the subscript operator [] binds before the * dereference operator, so parantheses are needed.

Behold:

int array[20] = {'a','b','c','d','e','f','g','h','i','j','k','l'};
int (*pointer)[10 - 6 + 1] = (int (*)[10 - 6 + 1])&array[6];    /* = array[6 through 10] */

printf("(*pointer)[0] = %c\n", (*pointer)[0]);
printf("(*pointer)[4] = %c\n", (*pointer)[4]);
printf("sizeof *pointer / sizeof **pointer = %lu\n", (unsigned long)(sizeof *pointer / sizeof **pointer));

Addendum:

For the answer to your actual problem that you've put in, that's a lot easier. Just use a pointer that is set to an offset from the buffer array, eg:

unsigned char buffer[102400];
unsigned char *ptr;

/* ... */
ptr = buffer + 500;
read(fd, ptr, 1024); /* Try and read up to 1024 bytes at position buffer[500] */
12
ответ дан 18 December 2019 в 05:26
поделиться

Если я прочитал ваш вопрос, вы хотите адресовать диапазон элементов в исходном массиве, так сказать срез.

В C ++ вы можете сделать это легко - при условии, что вы реализуете свой собственный класс массива (сохраняя указатель + числовые элементы). Затем вы можете определить функции-члены, которые вернут вам срез: указатель на исходный массив и ряд элементов, которые вы не будете обращаться за пределами исходного массива.

В Plain-Old-C вам не нужно определять размер массивов совместное использование хранилища и указателя не ограничено по определению: он просто указывает на один элемент. Вы не можете позволить C-коду «повторно интерпретировать» размерный массив, поскольку имя массива (символ) является адресом хранилища, которую вы не можете изменить.

Вы хотите следующее:

int  array1[10];
int  array2[3];

// reference 3 elements from array1, starting at element 5 in array1
array2 = array1[5];

, но это не разрешено. Имя "array2" переводится компилятором в фиксированный адрес, который вы не можете переопределить во время выполнения - вот почему есть указатели: из них вы можете изменить все, на что они указывают, по желанию во время выполнения.

1
ответ дан 18 December 2019 в 05:26
поделиться

Конечно, вы можете.

int a[4] = {1,2,3,4};
int *b = &a[2];
cout << b[0] << "-" << b[1] << endl;

На выходе будет 3-4.

6
ответ дан 18 December 2019 в 05:26
поделиться

В приведенном ниже примере я объявил статический массив из 10 целых чисел. Я создал 2 указателя на его элементы, определив таким образом диапазон. Что я сделал дальше: я объявил указатель в цикле for, начиная с указателя p1, который проходил через каждый элемент в массиве, пока не достиг указателя p2 - вывод значения элемента.

Это то, что вы искали?

#include <iostream>
using namespace std;

int main()
{ 
    int a[10] = { 0, 4, 5, 7, 4, 3, 1, 6, 2, 9 };

    int *p1 = &a[3];
    int *p2 = &a[7];

    for(int *p = p1; p != p2; ++p)
    {
        cout << *p << endl;
    }

    return 0;
}
4
ответ дан 18 December 2019 в 05:26
поделиться

У вас может быть указатель, указывающий на любой элемент массива C. Поскольку массивы C не «знают» свою длину, идея «диапазона» массива C не может быть выражена напрямую. Поскольку вам нужно сохранить длину самого массива, вы должны сохранить длину диапазона, на который указывает указатель.

3
ответ дан 18 December 2019 в 05:26
поделиться

Как уже говорили другие, вы легко можете сделать первую часть. Просто сделайте указатель = массив + 6 . Но что такое указатель ? Он не может быть объявлен как:

char pointer[5];

или аналогичный. Это должен быть указатель :

char *pointer = array + 6;

Это потому, что вы можете ' t присвоить массиву какое-то другое имя (массив не является изменяемым l-значением). Нет смысла говорить:

char a[10];
char b[10];
b = a;

Теперь, в C, размер указателя - это просто размер указателя, поскольку указатель не имеет понятия «количество единиц» данного типа, на которое указывает . С другой стороны, массивы точно знают, сколько в них элементов, и вы можете получить этот размер, используя соответствующий оператор sizeof .

Итак, sizeof array в ваш пример будет 10 (если он имеет 10 элементов), тогда как указатель размера будет числом байтов, занятых указателем char . Следовательно, то, что вы задаете во второй части вашего вопроса, невозможно в C . В C ++ у вас есть доступ к типам данных, которые должны позволить вам делать то, что вы хотите.

Изменить : Чтобы прочитать файл по частям:

Допустим, у вас большой буфер, в который вы уверены, что можете прочитать весь файл:

unsigned char bigbuf[1UL << 24]; /* or whatever you want */
unsigned char *ptr = bigbuf;
size_t chunk = BUFSIZ;
FILE *fp = fopen("foo.txt", "rb"); /* no error checking */
size_t nread;
size_t total = 0;
while ((nread = fread(ptr, 1, chunk, fp)) > 0) {
    ptr += nread;
    total += nread;
    if (total + chunk > sizeof bigbuf) {
        /* oops, not enough space */
    }
}
if (ferror(fp)) {
    /* read error */
} else {
    /* bigbuf now has data, total has the number of bytes */
}

Для небуферизованного ввода-вывода посмотрите на setvbuf () . Но проверьте буферизованные и небуферизованные входы, чтобы увидеть, какой из них быстрее. Также проверьте разные размеры чтения.

Теперь отступление, которое я вставил раньше, и я думаю, что все равно оставлю его здесь:

Ответив на этот вопрос, более интересно сделать это другим способом , т. Е. Задано:

T a[10];

для любого типа T , можете ли вы объявить указатель так, чтобы:

pointer[1] == a[0]
pointer[2] == a[1]
...
pointer[11] == a[10]

(или, если вы любите приключения, замените 1 на большее положительное число на левой стороне первого утверждения)

Ответ, согласно стандарту C, - нет . Как упоминалось в ссылке, Числовые рецепты на C использовали этот «трюк».

4
ответ дан 18 December 2019 в 05:26
поделиться

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

char *p = array + 6;

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

, вероятно, стоит указать, что

array[i] 

идентичен

*(array + i)
3
ответ дан 18 December 2019 в 05:26
поделиться

Да, если вы правильно используете адреса:

int* ptr = new int[10];
int* ptrSub = &ptr[5];
2
ответ дан 18 December 2019 в 05:26
поделиться

указатель = & массив [6] . указатель [0] теперь будет ссылаться на то же значение, что и массив [6] . Невозможно напрямую извлечь ссылку на фрагмент массива и сохранить для него семантику sizeof . Вы можете эмулировать это примерно так:

template <class T>
class Slice {
public:
 Slice(T* elements, int begin, int end) : m_elements(elements + begin), m_size(end - begin) {}
 T& operator[] (int index) {return m_elements[index];}
 int size() const {return m_size;}
private:
 T* m_elements;
 int m_size; 
};

int values[10];
Slice<int> slice(values, 5, 10);
values[5] = 3;
assert(slice[0] == values[5]);
assert(slice.size() == 5);
2
ответ дан 18 December 2019 в 05:26
поделиться

Указатели «указывают» только на первый элемент в любой структуре или переменной. Это всего лишь адрес. Вы можете подразумевать диапазон, сделав их указателем на определенный тип, который определяет диапазон.

-1
ответ дан 18 December 2019 в 05:26
поделиться