Индексация массива начинается с числа не 0

Можно ли запустить массив с индексом без нуля... I.E. у вас есть массив [35], из 35 элементов, теперь я хочу индексировать, скажем, начиная 100, поэтому числа будут [100], [101],... a [134], это возможно?

Я пытаюсь создать "карту памяти" для платы, и у меня будет один массив, называемый SRAM [10000], а другой, например, BRAM [5000], но в "видимости памяти" они смежны, IE BRAM запускается сразу после SRAM, поэтому, если я попытаюсь указать на ячейку памяти 11000, я бы прочитал ее, увидев, что она превышает 10000, затем передайте ее в bram.

При вводе этого я понял, что могу предположить, что тогда вычтите 10K из числа и передайте это в BRAM, но, ради аргумента, можно ли индексировать передачу 11000 в BRAM?

Спасибо за любую помощь.

Обновлено, чтобы исправить a [34] до [134]

Обновлено для дополнительной информации: В реальной архитектуре я буду реализовывать, может быть/может быть разрыв между sram и bram, так что, например, адрес 11008 может не отображаться на карте памяти, таким образом, записывая гигантский массив, полный памяти, тогда "разбиение" будет работа, но мне все равно придется делать логику, чтобы определить, находится ли она в пределах диапазона "sram и bram". Это то, чего я хотел избежать в первую очередь.

Ответ 1

Можно ли запустить массив с индексом не ноль... I.E. у вас есть массив [35], из 35 элементов, теперь я хочу индексировать, скажем, начиная 100, поэтому числа будут [100], [101],... a [134], это возможно?

Нет, вы не можете сделать это в C. Массивы всегда начинаются с нуля. В С++ вы можете написать свой собственный класс, скажем OffsetArray и перегрузить оператор [] для доступа к базовому массиву, вычитая смещение от индекса.

Я пытаюсь создать "карту памяти" для платы, и у меня будет один массив с именем SRAM [10000], а другой - BRAM [5000], например, но в "видимости памяти" они смежный, IE BRAM запускается сразу после SRAM, поэтому, если я попытаюсь указать на ячейку памяти 11000, я бы ее прочитал, увидев, что она превышает 10000, затем передайте ее в bram.

Вы можете попробовать что-то вроде этого:

char memory[150000];
char *sram = &memory[0];
char *bram = &memory[100000];

Теперь, когда вы получаете доступ к sram[110000], вы получите доступ к чему-то, что "в bram"

Ответ 2

C++ дает немного больше, чем C в этом отношении. Вы можете перегрузить operator[] чтобы выполнить вычитание, и если вы хотите сообщить об ошибке (например, выбросить исключение), если индекс находится вне диапазона.

В качестве минимальной демонстрации рассмотрим следующее:

#include <iostream>
#include <stdexcept>

template <class T, int lower, int upper>
class array {
    T data[upper-lower];
public:
    T &operator[](int index) { 
        if (index < lower || index >= upper)
            throw std::range_error("Index out of range");
        return data[index-lower]; 
    }
    T *begin() { return data; }
    T *end() { return data + (upper-lower); }
};

int main() {
    array<int, -3, 5> data;

    for (int i=-3; i<5; i++)
        data[i] = i;

    for (auto const &i : data) 
        std::cout << i << "\t";
    std::cout << "\n";
}

Ответ 3

Я помню, как читал в книге "Программирование программистов-программистов - Deep C Secrets", Питер Ван дер Линден раскрывает трюк, чтобы обмануть компилятор в размышления смещения массива начинается с 1... теоретически трюк может быть выполнен, я не есть книга со мной, но небрежно, я помню, как читал ее... она не переносима и может привести к поведению undefined...

Изменить: См. здесь раздел 6.17 в C-FAQ. ПРЕДУПРЕЖДЕНИЕ: не Portable и undefined поведение! Процитировать здесь источник.

6.17: Here a neat trick: 
      if I write int realarray[10]; 
         int *array = &realarray[-1]; 
I can treat "array" as if it were a 1-based array. A: Although this technique 
is attractive (and was used in old editions of the book _Numerical Recipes in C_), 
it is not strictly conforming to the C Standard. Pointer arithmetic is defined 
only as long as the pointer points within the same allocated block of memory, 
or to the imaginary "terminating" element one past it; otherwise, the behavior 
is undefined, *even if the pointer is not dereferenced*. The code above could 
fail if, while subtracting the offset, an illegal address were generated 
(perhaps because the address tried to "wrap around" past the beginning of some 
memory segment). 

References: K&R2 Sec. 5.3 p. 100, Sec. 5.4 pp. 102-3, Sec. A7.7 pp. 205-6; 
ISO Sec. 6.3.6; Rationale Sec. 3.2.2.3.

Read more: http://www.faqs.org/faqs/C-faq/faq/#ixzz0ftyqHOvm

Надеюсь, что это поможет.

Ответ 4

Вы можете обмануть макрос:

int myarray[35];

#define a (myarray - 100)

a[100] = 0;

Также можно использовать указатель.

Ответ 5

Нет - как вы не можете изменить нижнюю границу объявления, например, VB6.

Да - как вы можете делать трюки вроде

int a[35];
int* actual_a = a-100;
printf("%d", actual_a[101]);
...

потому что x[a] эквивалентно *(x+a). Это очень не рекомендуется.

Ответ 6

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

int   ram[15000]; 
int * sram=&ram[0];
int * bram=&ram[10000];

Я использовал нотацию & foo [xxx], чтобы сделать ее явной, что вы делаете. В любом случае, теперь вы можете использовать ram для индексирования в любом месте всего массива, или sram и bram для индексации на определенные части.

Ответ 7

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

typedef union
{
    unsigned char all[15000];
    struct
    {
        unsigned char sram[10000];
        unsigned char bram[5000];
    };
} memory;

это передает намерение, что память смежна, и что она разделена на 2 части. обратите внимание, что вы должны остерегаться выравнивания bram и sram, может понадобиться a #pragma pack(1).

Ответ 8

Как отмечали другие, вы можете технически достичь того, чего хотите, вызывая арифметику указателя следующим образом:

int* myArray = malloc((upperBound - lowerBound) * sizeof(*myArray));
myArray -= lowerBound;
...
for(int i = lowerBound; i < upperBound; i++) {
    myArray[i];
}

Пока это будет безупречно работать с -O0, это поведение undefined с точки зрения языка. У машины, однако, нет никаких возражений против этого, на машине задействована арифметика указателя такая же, как любая беззнаковая целочисленная арифметика с uintptr_t. Таким образом, единственная опасность для этого подхода - оптимизатор.

Теперь вы можете легко победить оптимизатор, разделив приведенный выше код на два разных блока компиляции, т.е. е. есть один файл ".c" с функцией

int* fancyIntArray(size_t lowerBound, size_t upperBound) {
    return intMalloc(upperBound - lowerBound) - lowerBound;
}

и поместите функцию intMalloc() в другой файл .c:

int* intMalloc(size_t size) {
    return malloc(size_t*sizeof(int));
}

Теперь вы в безопасности, потому что когда оптимизатор смотрит на арифметику указателя в fancyIntArray(), он не знает, что перед адресом, который возвращает intMalloc(), нет выделенной памяти, поскольку он ничего не знает о intMalloc(). Таким образом, он вынужден оставить ваш код неповрежденным.

И, конечно же, вы должны использовать независимые вызовы компилятора для компиляции разных ".c" файлов, чтобы оптимизатор действительно ничего не мог вывести о intMalloc().

Ответ 9

Не в C. Вы должны выполнить арифметику самостоятельно. Есть, вероятно, необычные работы, которые работают большую часть времени, например, создание нового указателя BRAM-11000 и использование этого.

Ответ 10

Самый простой способ сделать это:

у вас есть:

int *array = memory ; // starts with 0;
array-= 1000 ; // now array[1000] is 0

В С++ просто создайте класс с operator[]

Ответ 11

Указатели и массивы очень похожи на C, поэтому вы можете легко сделать что-то вроде

element SRAM_MEM[10000];
element BRAM_MEM[5000];

element* SRAM = SRAM_MEM;
element* BRAM = BRAM_MEM-10000;

BRAM[10001] = 0; // sets the first element of BRAM_MEM

Ответ 12

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

Ответ 13

Возможно, вы можете использовать union?

#pragma pack(0)
union 
{
  char array[15000];
  struct { char sram[10000]; char bram[5000];  } map;
} combination;

Они физически смежны. Если вы получите доступ к "массиву", тогда он войдет либо в bram, либо в sram на основе смещения

Вам нужна прагма, чтобы сообщить компилятору НЕ выровнять элементы структуры на границах слов. Это предотвращает количество байтов пространства между двумя частями структуры карты.