【发布时间】:2010-11-25 04:58:08
【问题描述】:
如果我写
int *columns[32];
我是否定义了一个包含 32 个指向 ints 的指针的数组?
还是一个指向 32 个ints 数组的指针?
如何区分这两者?有区别吗?
【问题讨论】:
标签: c arrays pointers multidimensional-array
如果我写
int *columns[32];
我是否定义了一个包含 32 个指向 ints 的指针的数组?
还是一个指向 32 个ints 数组的指针?
如何区分这两者?有区别吗?
【问题讨论】:
标签: c arrays pointers multidimensional-array
将评论扩展到另一个答案:
阅读 C 声明有一个相当简单的过程。从声明器中最左边的标识符开始,然后逐步退出,记住[] 和() 绑定在* 之前。鉴于声明
int *columns[32];
把它分解为
columns -- columns
columns[32] -- is a 32-element array
*columns[32] -- of pointers
int *columns[32] -- to int.
如果声明是
int (*columns)[32];
然后它会分解为
columns -- columns
(*columns) -- is a pointer
(*columns)[32] -- to a 32-element array
int (*columns)[32] -- of int.
这也将帮助您建立复杂的声明。假设您要声明一个指向函数的指针数组,该函数返回指向 char 数组的指针:
f -- f
f[N] -- is an N-element array
*f[N] -- of pointers
(*f[N])() -- to functions
*(*f[N])() -- returning pointers
(*(*f[N])())[M] -- to M-element arrays
*(*(*f[N])())[M] -- of pointers
char *(*(*f[N])())[M]; -- to char
cdecl 是一个不错的工具,但是在您完成了几次此练习之后,您就不需要它了。
【讨论】:
如有疑问 - 询问cdecl
$> cdecl
Type `help' or `?' for help
cdecl> explain int *columns[32]
declare columns as array 32 of pointer to int
编辑 回复 cmets:我在 Google Code Search 上找到了 cdecl 源。它需要GNU readline 库。我认为在 Mac OS X 或 Windows 上编译应该没有问题。
【讨论】:
cdecl 吗? Apple 的资本主义猪并没有提供他们的开发工具。
您正在定义一个包含 32 个指针的数组。
要定义一个指向 32 个整数数组的指针,您必须这样做
int (*columns)[32];
前一个声明实例化了一个空间为 32 * sizeof(int) 的数组。另一方面,后者实例化了一个未初始化的指针,然后您可以按如下方式使用它:
int myintegers[32] = {0, 1, 2, ..., 31};
int (*columns)[32];
columns = &myintegers;
printf("%d\n", (*columns)[2]);
我希望我能把区别说清楚一点。
【讨论】:
这是一个由 32 个指向 int 的指针组成的数组,是的,这很重要。
C 语法规则指定数组访问 ([]) 比解引用 (*) 绑定更紧密,声明镜像使用。
声明int *columns[32]; 表示表达式*columns[n](其中n 是0 到31 之间的数字)是int。此表达式与*(columns[n]) 相同。该声明为 32 个指针分配空间,但没有分配 ints 并且(假设这是一个函数局部声明)没有一个指针被初始化。
如果声明为int (*columns)[32];,那么表达式(*columns)[n] 将是int,这意味着* 取消引用发生在数组访问之前,因此列将是指向32 @ 数组的指针987654334@s。声明将分配一个指针,但没有ints 的数组。
【讨论】:
int *x 意味着被读取*x 是int。这只是描述语言的一种方式。我发现当你有二维数组时它真的很有帮助。如果您有int x[2][4],则意味着x[0][3] 是有效的int。必须颠倒声明和使用之间的索引限制会导致另一种混乱。
int *x; 读取为“*x 是int”,不是“x 是int *”。以正常顺序将所有“运算符”应用于标签,最终得到给定的基本类型。
测试程序是说明性的,尤其是对于我们这些不是语言律师的人:
$ gcc -x c -
#include <stdio.h>
int main(void)
{
int *columns[32];
printf("%lu\n%lu\n", sizeof(columns), sizeof(columns[0]));
return 0;
}
$ ./a.out
128
4
$
它似乎是一个指针数组。
【讨论】:
cdecl 版本。
cdecl 或 geordi 或其他作弊手段,大多数非律师将无法告诉您 void (*(*(*p)[N][M])[O])(char c) = 0; 声明的内容。
(*p) 指向一个 N 元素数组 (*p)[N] 的 M 元素数组 (*p)[N][M] 的指针 (*(*p)[N][M]) 到 O 元素数组 (*(*p)[N][M])[O] 的指针 (*(*(*p)[N][M])[O])函数采用 char 参数 (*(*(*p)[N][M])[O])(char c) 并返回 void void (*(*(*p)[N][M])[O])(char c)
这里有一些有趣的声明:
int *arrayOfIntP[32];
int (*pointerToArrayOf32)[32];
要获得更多关于多维数组的乐趣,请查看以下帖子:
【讨论】:
一个技巧是从右到左阅读。
给定 int* cols[32];
数组左边是数组中元素的类型。因此,我们将其读取为指向 int 的指针数组(计数为 32)。
【讨论】:
请参阅 Nigel Jones 的 A 'C' Test: The 0x10 Best Questions for Would-be Embedded Programmers 中的问题 #5*
a) int a; // 一个整数
b) 整数 *a; // 指向整数的指针
c) int **a; // 一个指向整数的指针
d) int a[10]; // 10 个整数的数组
e) int *a[10]; // 一个包含 10 个整数指针的数组
f) int (*a)[10]; // 指向 10 个整数数组的指针
g) int (*a)(int); // 一个指向函数 a 的指针,它接受一个整数参数并返回一个整数
h) int (*a[10])(int); // 一个包含 10 个指针的数组,指向接受整数参数并返回整数的函数
*唉,embedded.com 上的原始文章无法在他们的网站上找到。
【讨论】: