数组索引从数字0开始

时间:2010-02-18 15:04:25

标签: c++ c arrays

是否可以在非零的索引处启动数组... I.E。 你有一个数组a [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”的范围内。这首先是我想要避免的。

13 个答案:

答案 0 :(得分:18)

是否可以在索引不为零的情况下启动数组... I.E。你有一个数组a [35],有35个元素,现在我想索引从100开始,所以数字是[100],[101],...... a [134],这可能吗?

不,你不能在C中做到这一点。数组总是从零开始。在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”中的内容

答案 1 :(得分:13)

在这方面,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";
}

答案 2 :(得分:9)

我记得在“专家C编程 - 深度C秘密”一书中读到,Peter Van der Linden公开了一个欺骗编译器认为数组偏移从1开始的技巧......理论上可以完成这个技巧,我不知道和我一起拿着这本书,但是随便回忆一下......它不便携,可能产生不明确的行为......

编辑:请参阅此处的C-FAQ第6.17节。警告:不可移植和未定义的行为! 引用此处的source

6.17: Here's 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

希望这有帮助。

答案 3 :(得分:8)

你可以欺骗宏:

int myarray[35];

#define a (myarray - 100)

a[100] = 0;

也可以使用指针。

答案 4 :(得分:6)

否 - 因为您无法像VB6那样修改声明中的下限。

是的 - 就像你可以做的那样的技巧

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

因为x[a]相当于*(x+a)。这是非常不推荐的。

答案 5 :(得分:4)

你不清楚你想要如何使用这些数组,但它很容易设置一个看似两个不同数组的连续数组:

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

我使用&amp; foo [xxx]符号只是为了明确你正在做什么。无论如何,你现在可以使用ram来索引整个数组的任何位置,或者使用sram和bram来索引到特定的部分。

答案 6 :(得分:2)

严格来说,这个解决方案不会让你定义一个从不同于0的索引开始的数组,但是你可以用这种方式声明你的记忆:

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

这确实表达了内存连续的意图,并且它分为两部分。请注意,您应该注意bramsram的对齐,#pragma pack(1)可能是必要的。

答案 7 :(得分:2)

正如其他人所说,你可以通过调用指针算法在技术上达到你想要的效果:

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

虽然这对-O0完美无缺,但从语言的角度来看,它是未定义的行为。然而,机器绝对没有异议,对于机器,所涉及的指针算法与uintptr_t的任何无符号整数运算相同。因此,这种方法的唯一危险是优化器。

现在,您可以通过将上面的代码拆分为两个不同的编译单元来轻松击败优化器,i。即有一个带有函数的“.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()的任何内容。

答案 8 :(得分:1)

不在C.你必须自己做算术。大多数时候可能有奇怪的解决方法,比如制作一个新的指针BRAM-11000并使用它。

答案 9 :(得分:1)

最简单的方法:

你有:

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

在c ++中,只需使用operator[]

创建类

答案 10 :(得分:0)

指针和数组在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

答案 11 :(得分:0)

只需要一个考虑到偏移量的变量。即使可能,使用不以常规0开始的阵列也是非常难以理解的。

答案 12 :(得分:0)

也许你可以使用联盟?

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

他们在身体上是连续的。如果您访问'array',它将根据偏移

进入bram或sram

你需要编译指示告诉编译器不要在字边界上对齐struct成员。这可以防止地图结构的两个部分之间存在大量字节空间。