指向数组的指针数组?

4

我正在使用一个库,其中某个功能涉及变量的使用,如下所示:

extern const u8 foo[];
extern const u8 bar[];

我不被允许以任何方式重命名这些变量。

然而,我希望能够通过数组(或其他类似的方法)访问这些变量,这样我就不需要不断地将这些变量的新实例硬编码到我的主要代码中。

我创建数组的第一次尝试如下:

const u8* pl[] = {
    &foo,
    &bar
};

这导致我出现错误:无法将 'const u8 (*)[]' 转换为 'const u8*' ,在其他地方的帮助以及一些谷歌搜索的帮助下,我将我的数组更改为以下内容:

u8 (*pl)[] = {
    &foo,
    &bar
};

在编译时,我现在遇到了错误scalar object 'pl' requires one element in initializer
有人知道我做错了什么吗?谢谢。

不要取数组的地址 - 只需在初始化器中使用数组变量,它们就会衰变为指针。 - JoeG
你想要访问变量还是它们所代表的数组?这是一个微妙的差别,但却有着巨大的影响(参见Neil Butterworth的回答)。 - xtofl
两种可能都可以。说实话,我不确定。 - unrelativity
4个回答

7

只有在您的翻译单元中,foobar的大小完全相同,并且该大小在编译时已知,指向数组的指针数组才能正常工作。

const u8 (*pl[])[32] = {&foo, &bar};

如果不是这种情况,您必须使用一个指向字节的指针数组。
const u8 *pl[] = {foo, bar};

1
你可以在数组中拥有指向不完整类型(例如未知大小的数组)的指针,但是你不能拥有不完整类型的数组。 - CB Bailey
@Charles,如果没有出现“无法使用未指定边界的数组”错误,你如何有意义地使用它? - fredoverflow
@FredOverflow:我不确定你的意思是什么?与直接使用未指定边界的数组foobar的方式相同。就像仍然可以执行foo[x]一样,所以只要x实际上在范围内,就可以执行(*pl[0])[x]。你无法检查它,但如果它是有效的,它将起作用。 - CB Bailey
好的,我会将这个标记为已接受(第二段代码片段),但是我可以问一下吗——在这方面是否有任何关于指针和数组的理论需要学习? - unrelativity
@a2h:当然有理论需要学习;例如,即使这个答案说不是,拥有指向不完整类型的指针数组是合法的。基本原则是数组不是指针,但在大多数表达式上下文中,数组的名称会衰减为指向其第一个元素的指针(作为sizeof和一元&的参数是明显的例外)。这应该被任何好的基础C或C++教材所涵盖。我个人认为K&R中关于数组和指针的解释是最清晰的。 - CB Bailey
1
@a2h 这个教训告诉我们指向数组的指针很少有意义,但了解它们仍然是一个好主意!不幸的是,许多C程序员会因为错误的假设数组和指针是相同的而混淆二维数组、指针数组和数组指针。 - fredoverflow

2
由于在声明中数组没有大小,你是否可以只使用指向它们第一个元素的指针数组?
例如:
const u8* pl[] = { foo, bar };

如果你想要一个指向数组的指针数组,我认为你需要这样做:

const u8 (*pl[])[] = { &foo, &bar };

但我并没有看到它真正比以前的解决方案有任何优势。


原因?嗯,那就是我的知識不足。我會試著使用你的解決方案,看看效果如何... - unrelativity

1
extern const int a[];

const int *  aa[] = { a };

1

去掉 & 符号。数组会正常地衰变为指针。

typedef int u8;  // Using int as I don't know what a u8 is.

const u8 foo[] = { 1, 2, 3};
const u8 bar[] = { 1 };

const u8* pl[] = {
    foo,
    bar
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接