有点像菜鸟所以不要在这里杀了我。
以下代码之间有什么区别?
int *p; //As i understand, it creates a pointer to an variable of size int.
int *p[100]; //Don't really know what this is.
int (*p)[100]; // I have come to understand that this is a pointer to an array.
答案 0 :(得分:38)
这是指向int
的指针:
int *p;
┌────┐
│int*│
└────┘
它应该指向int
,类似这样:
┌────┐
│int*│
└─┃──┘
▼
┌───┐
│int│
└───┘
这是一个包含int
的100个指针的数组:
int *p[100];
也就是说,它会给你100个指针。
┌────┬────┬────┬────┬────┬────┬┄
│int*│int*│int*│int*│int*│int*│
└────┴────┴────┴────┴────┴────┴┄
每个指针都应该指向int
,也许是这样的:
┌────┬────┬────┬────┬────┬────┬┄
│int*│int*│int*│int*│int*│int*│
└─┃──┴─┃──┴─┃──┴─┃──┴─┃──┴─┃──┴┄
▼ ▼ ▼ ▼ ▼ ▼
┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌┄
│int││int││int││int││int││int││
└───┘└───┘└───┘└───┘└───┘└───┘└┄
当然,没有理由他们不能指向同一个int
或其他什么。
如果你想要很多指针,你可能想要使用一个指针数组 迭代。例如,您可以动态分配对象,并使每个指针指向不同的对象:
p[0] = new int(0);
p[1] = new int(0);
// ...
也许动态分配int
并不是最好的例子,但我认为这一点很清楚。
这是指向100 int
数组的指针:
int (*p)[100];
也就是说,它只给你一个指针:
┌───────────┐
│int(*)[100]│
└───────────┘
它应指向包含100 int
s:
┌───────────┐
│int(*)[100]│
└─┃─────────┘
▼
┌───┬───┬───┬───┬───┬───┬┄
│int│int│int│int│int│int│
└───┴───┴───┴───┴───┴───┴┄
当您在数组名称上使用address-of运算符(&
)时,将获得指向数组的指针。例如:
int arr[100] = { /* some initial values */ };
int (*p)[100] = &arr;
在这里,我已经获取了arr
数组的地址,它给了我一个指向该数组的指针。如果您想访问数组的元素,则必须先取消引用指针:(*p)[3]
将访问元素3.
永远记住 arrays are not pointers 。正如我们刚才看到的,我们可以获取数组的地址来获取指向它的指针,就像C ++中的任何其他(非临时)对象一样。数组和指针之间唯一的特殊连接是数组的名称可以隐式转换为指向数组第一个元素的指针。这意味着以下内容有效:
int arr[100] = { /* some initial values */ };
int* p = arr;
指针p
将指向arr
中的第一个元素。请注意,p
不是指向数组的指针,而是指向数组元素的指针。
(另请注意,没有数组类型函数参数。如果您将类似int p[]
的内容写为函数参数,编译器会将其转换为int*
。)
答案 1 :(得分:18)
听起来你可以使用Spiral Rule的介绍。
从变量开始,从左到右依次“螺旋”:
+-------+
| +--+ | // So we have:
| | | | p // p
int * p | | * p // p is a pointer
^ ^ | | int * p // p is a pointer to an int
| +----+ |
+----------+
下一个:
+--------+
| +--+ | p // p
| | V | p[100] // p is an array of 100
int * p[100] | * p[100] // p is an array of 100 pointers
^ ^ | | int * p[100] // p is an array of 100 pointers to ints
| +----+ |
+-----------+
最后,规则的新部分首先在括号中做任何事情:
+-----+
| +-+ |
| ^ | | ( p) // p
int (* p) [100]; (*p) // p is a pointer
^ ^ | | (*p)[100] // p is a pointer to an array of 100
| +---+ | int (*p)[100] // p is a pointer to an array of 100 ints
+---------+
如果您在线/可以访问计算机,使用cdecl.org网站总是很有用,但是能够离线阅读代码也很重要,而这条规则可以让您做到这一点
答案 2 :(得分:9)
有点像菜鸟所以不要在这里杀了我
即使是专家,弄清楚C中的类型意味着什么也很棘手。不用担心。
以下代码之间有什么区别?
其他答案都很好,我无意反驳。相反,这是考虑它的另一种方式。我们需要定义三件事:
变量是支持三种操作的东西。 fetch 操作接受一个变量并产生其当前值。获取操作没有表示法;你只需使用变量。 store 操作接受变量和值,并将值存储在变量中。 地址操作接受一个变量并生成一个指针。
指针是支持一个操作的东西。 解除引用操作(写为前缀*pointer
)接受指针并生成变量。 (指针支持算术和索引等其他操作 - 这是算术的一种形式 - 但是不要去那里。)
数组是支持一个操作的东西。 index 操作采用数组和整数,并生成变量。它的语法是后缀:array[index]
好的,现在我们来回答您的问题。宣言是什么
int p;
意思?表达式p
是int
类型的变量。请注意,这是一个变量;您可以将商品存储到p
。宣言是什么
int *p;
意思?表达式*p
是int
类型的变量。现在我们知道我们可以推断出p
是什么。由于*p
是一个取消引用并生成变量,因此p
必须是指向int的指针。宣言是什么
int *p[100];
意思?这意味着*表达式*p[i]
是int
类型的变量,前提是i
是从0
到99
的整数值。我们得到了一个变量,但是我们可以从指针或数组中得到它,所以我们必须弄清楚哪个。我们查阅运算符优先级表,发现索引运算符比解除引用运算符绑定“更严格”。那就是:
*p[i]
与
相同*(p[i])
并记住,那个东西是int
类型的变量。 parens的内容解除引用以生成int
类型的变量,因此parens的内容必须是指向int
的指针。因此
p[i]
是指向int的指针。怎么可能?这必须是一个指向类型指针的变量的获取!所以p[i]
是指向int的类型指针的变量。由于这是一个索引操作,p
必须是指向int
的指针数组。
现在你做下一个。
int (*p)[100];
意味着什么?
答案 3 :(得分:4)
int *p;
- >声明一个指向整数类型的指针
int *p[100];
- >声明一个包含整数类型的100个指针的数组
int (*p)[100];
- >声明一个指向100个整数数组的指针。
使用cdecl翻译此类型。