C中的类型 – int *和int * 有什么区别?
有点像菜鸟所以不要在这里杀了我。
以下代码之间有什么区别?
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.
-
这是一个指向
int
的指针 :int *p;
┌────┐ │int*│ └────┘
它应该指向一个
int
,类似这样:┌────┐ │int*│ └─┃──┘ ▼ ┌───┐ │int│ └───┘
-
这是一个包含100个
int
指针的数组 :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
的数组:┌───────────┐ │int(*)[100]│ └─┃─────────┘ ▼ ┌───┬───┬───┬───┬───┬───┬┄ │int│int│int│int│int│int│ └───┴───┴───┴───┴───┴───┴┄
当您在数组名称上使用地址运算符(
&
)时,您将获得指向数组的指针。 例如:int arr[100] = { /* some initial values */ }; int (*p)[100] = &arr;
在这里,我采用了
arr
数组的地址,它给了我一个指向该数组的指针。 如果您想访问数组的元素,则必须首先取消引用指针:(*p)[3]
将访问元素3。
边注:
永远记住, 数组不是指针 。 正如我们刚才看到的,我们可以获取数组的地址来获取指向它的指针,就像C ++中的任何其他(非临时)对象一样。 数组和指针之间唯一的特殊连接是数组的名称可以隐式转换为指向数组第一个元素的指针。 这意味着以下内容有效:
int arr[100] = { /* some initial values */ }; int* p = arr;
指针p
将指向arr
中的第一个元素。 请注意, p
不是指向数组的指针,而是指向数组元素的指针。
(另请注意,不存在数组类型函数参数。如果您将类似int p[]
写为函数参数,则编译器将其转换为int*
。)
听起来你可以使用螺旋规则的介绍。
从变量开始,从左到右依次“螺旋”:
+-------+ | +--+ | // 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网站总是很有用,但是能够离线阅读代码也很重要,而且这条规则可以让您做到这一点。
有点像菜鸟所以不要在这里杀了我
即使对于专家来说,解决C中的类型意味着什么也很棘手。 别担心。
以下代码之间有什么区别?
其他答案都很好,我无意反驳。 相反,这是另一种思考它的方式。 我们需要定义三件事:
-
变量是支持三种操作的东西。 获取操作接受一个变量并产生其当前值。 获取操作没有表示法; 你只需使用变量。 存储操作采用变量和值,并将值存储在变量中。 地址操作接受一个变量并产生一个指针 。
-
指针是支持一个操作的东西。 作为前缀
*pointer
写入的取消引用操作接受指针并产生变量。 (指针支持算术和索引等其他操作 – 这是算术的一种forms – 但是不要去那里。) -
数组是支持一个操作的东西。 索引操作采用数组和整数并生成变量 。 它的语法是postfix:
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的指针。 怎么可能? 这必须是一个类型指针到int的变量的获取! 所以p[i]
是指向int的类型指针的变量。 由于这是一个索引操作,因此p
必须是指向int
的指针数组。
现在你做下一个。
int (*p)[100];
意味着什么?
int *p;
– >声明一个指向整数类型的指针。
int *p[100];
– >声明一个包含整数类型的100个指针的数组。
int (*p)[100];
– >声明一个指向100个整数数组的指针。
使用cdecl来翻译这些类型。