C++ 数组索引从非 0 的数字开始

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2289548/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:54:54  来源:igfitidea点击:

Array indexing starting at a number not 0

c++carrays

提问by onaclov2000

Is it possible to start an array at an index not zero...I.E. you have an array a[35], of 35 elements, now I want to index at say starting 100, so the numbers would be a[100], a[101], ... a[134], is that possible?

是否可以在不为零的索引处开始一个数组...IE 你有一个数组 a[35],有 35 个元素,现在我想索引从 100 开始,所以数字将是 a[100],a [101], ... a[134],这可能吗?

I'm attempting to generate a "memory map" for a board and I'll have one array called SRAM[10000] and another called BRAM[5000] for example, but in the "memory" visiblity they're contiguous, I.E. BRAM starts right after SRAM, so therefore if I try to point to memory location 11000 I would read it see that it's over 10000 then pass it to bram.

我正在尝试为电路板生成“内存映射”,例如,我将有一个名为 SRAM[10000] 的数组和另一个名为 BRAM[5000] 的数组,但在“内存”可见性中它们是连续的,IE BRAM在 SRAM 之后立即开始,因此如果我尝试指向内存位置 11000,我会读取它,看到它超过 10000,然后将其传递给 bram。

While typing this I realized I could I suppose then subtract the 10K from the number and pass that into BRAM, but for the sake of argument, is this possible to index passing 11000 to BRAM?

在输入这个时,我意识到我可以假设然后从数字中减去 10K 并将其传递到 BRAM,但是为了论证,这是否可以索引传递 11000 到 BRAM?

Thank you for any help.

感谢您的任何帮助。

Updated to fix the a[34] to a[134]

更新以将 a[34] 修复为 a[134]

Updated for additional information: In the actual architecture I will be implementing, there can/may be a gap between the sram and bram so for example the address 11008 might not be visible in the memory map, thus writing a giant array full of memory then "partitioning" it will work, but I'll still have to do logic to determine if it's within the ranges of "sram and bram". Which is what I wanted to avoid in the first place.

更新附加信息:在我将实现的实际架构中,sram 和 bram 之间可能/可能存在差距,例如地址 11008 在内存映射中可能不可见,因此写入一个巨大的内存数组然后“分区”它会起作用,但我仍然需要做逻辑来确定它是否在“sram和bram”的范围内。这是我首先想要避免的。

回答by Hans W

Is it possible to start an array at an index not zero...I.E. you have an array a[35], of 35 elements, now I want to index at say starting 100, so the numbers would be a[100], a[101], ... a[134], is that possible?
是否可以在不为零的索引处开始一个数组...IE 你有一个数组 a[35],有 35 个元素,现在我想索引从 100 开始,所以数字将是 a[100],a [101], ... a[134],这可能吗?

No, you cannot do this in C. Arrays always start at zero. In C++, you could write your own class, say OffsetArrayand overload the []operator to access the underlying array while subtracting an offset from the index.

不,你不能在 C 中这样做。数组总是从零开始。在 C++ 中,您可以编写自己的类,比如OffsetArray重载[]运算符以访问底层数组,同时从索引中减去偏移量。

I'm attempting to generate a "memory map" for a board and I'll have one array called SRAM[10000] and another called BRAM[5000] for example, but in the "memory" visiblity they're contiguous, I.E. BRAM starts right after SRAM, so therefore if I try to point to memory location 11000 I would read it see that it's over 10000 then pass it to bram.
我正在尝试为电路板生成“内存映射”,例如,我将有一个名为 SRAM[10000] 的数组和另一个名为 BRAM[5000] 的数组,但在“内存”可见性中它们是连续的,IE BRAM在 SRAM 之后立即开始,因此如果我尝试指向内存位置 11000,我会读取它,看到它超过 10000,然后将其传递给 bram。

You could try something like this:

你可以尝试这样的事情:

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

Now, when you access sram[110000]you'll be accessing something that's "in bram"

现在,当您访问时,sram[110000]您将访问“在bram”中的内容

回答by Jerry Coffin

C++ provides quite a bit more than C in this respect. You can overload operator[]to do the subtraction, and if you want report an error (e.g., throw an exception) if the subscript is out of range.

在这方面,C++ 比 C 提供了更多的东西。你可以重载operator[]做减法,如果你想在下标超出范围时报告错误(例如,抛出异常)。

As a minimal demo, consider the following:

作为一个最小的演示,请考虑以下内容:

#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";
}

回答by t0mm13b

I remember reading in the book 'Expert C Programming - Deep C Secrets', Peter Van der Linden discloses a trick to fool the compiler into thinking array offsets starts at 1...theoretically the trick can be accomplished, I do not have the book with me, but offhand, I recall reading it...it is not portable and may produce undefined behavior...

我记得在“Expert C Programming - Deep C Secrets”一书中读过,Peter Van der Linden 公开了一个技巧来欺骗编译器让编译器认为数组偏移量从 1 开始......理论上这个技巧可以实现,我没有这本书和我在一起,但随手,我记得读过它......它不是便携式的,可能会产生未定义的行为......

Edit:See here section 6.17 on the C-FAQ. WARNING: Not Portable and Undefined behavior! To quote from the sourcehere.

编辑:请参阅 C-FAQ 上的第 6.17 节。警告:不可移植和未定义的行为!引用这里的来源

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

Hope this helps.

希望这可以帮助。

回答by Richard Pennington

You could cheat with macro:

你可以用宏作弊:

int myarray[35];

#define a (myarray - 100)

a[100] = 0;

A pointer could also be used.

也可以使用指针。

回答by kennytm

No — as in you can't modify the lower bound in declaration like VB6.

不 - 因为你不能像 VB6 一样修改声明中的下限。

Yes — as in you can do tricks like

是的 - 因为你可以做一些技巧,比如

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

because x[a]is equivalent to *(x+a). This is highly unrecommended.

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

回答by swestrup

You're not very clear on exactly how you want to use these arrays, but its easy enough to set up a single contiguous array that can appear to be two different arrays:

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

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

I used the &foo[xxx] notation just to make it explicit what you're doing. Anyway, you can now use ram to index anywhere into the entire array, or sram and bram to index into particular parts.

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

回答by Adrien Plisson

strictly speaking, this solution does not loet you define an array starting at an index different from 0, but you may declare your memory this way:

严格来说,这个解决方案不会让你定义一个从不同于 0 的索引开始的数组,但你可以这样声明你的内存:

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

this does convey the intent that the memory is contiguous, and that it is split in 2 parts. note that you should beware of the alignment of bramand sram, a #pragma pack(1)may be necessary.

这确实传达了内存是连续的,并且它被分成两部分的意图。请注意,您应该提防的对准bramsram,一个#pragma pack(1)可能是必要的。

回答by cmaster - reinstate monica

As others have noted, you can technically achieve what you want by invoking pointer arithmetic like this:

正如其他人所指出的,您可以通过像这样调用指针算法在技术上实现您想要的:

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

While this will work flawlessly with -O0, it is undefined behaviour from a language point of view. The machine, however, has absolutely no objections to this, to the machine the pointer arithmetic involved is the same as any unsigned integer arithmetic with uintptr_t. Thus, the only danger to this approach is the optimizer.

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

Now, you can easily defeat the optimizer by splitting the code above into two different compilation units, i. e. have one ".c" file with the function

现在,您可以通过将上面的代码分成两个不同的编译单元来轻松击败优化器,即有一个带有该函数的“.c”文件

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

and put the function intMalloc()into a different".c" file:

并将函数intMalloc()放入不同的“.c”文件中:

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

Now, you are safe, because when the optimizer looks at the pointer arithmetic in fancyIntArray(), it does not know that there is no allocated memory in front of the address that intMalloc()returns, as it does not know anything about intMalloc()itself. As such, it is forced to leave your code intact.

现在,您是安全的,因为当优化器查看 中的指针算术时fancyIntArray(),它不知道在intMalloc()返回的地址前面没有分配的内存,因为它对intMalloc()自身一无所知。因此,它被迫保持您的代码完整无缺。

And, of course, you should use independent compiler calls to compile the different ".c" files, so that the optimizer really cannot deduce anything about intMalloc().

而且,当然,您应该使用独立的编译器调用来编译不同的“.c”文件,这样优化器真的无法推断出任何关于 .c 的信息intMalloc()

回答by Paul Tomblin

Not in C. You have to do the arithmetic yourself. There are probably bizarre work-arounds that work most of the time, like making a new pointer that is BRAM-11000 and using that instead.

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

回答by Artyom

The simplest way to do this:

执行此操作的最简单方法:

you have:

你有:

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

In c++ just create class with operator[]

在 C++ 中,只需创建类 operator[]