#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
int x = 2;
int *pointer2 = &x;
int number = &x;
printf("%x\n",number );
printf("%x\n",number+1 );
printf("%x\n",pointer2 );
printf("%x\n",pointer2+1);
return EXIT_SUCCESS;
}
我从gcc得到一个警告,“初始化从指针生成整数,没有强制转换[默认情况下启用]”,但是当我编译时,得到以下输出:
5da24540
5da24541
5da24540
5da24544
显然,上面的事情并没有发生,因为我们可以在前两行输出中看到地址只增加1而第二种情况增加4。同时请解释&amp;返回可以分配给其他变量(如int)的地址,或者它是self中的指针,只能指定给指针类型。
答案 0 :(得分:7)
number
是一个int
,使用x
的地址初始化(从地址“生成int
而无需投放” - 警告告诉您,这可能不是你想要什么) - 如果你增加它,它将增加1。
pointer2
是指向int
的指针(使用x
的相同地址初始化),以int
的大小为增量递增(这种行为称为“指针算术”。
答案 1 :(得分:1)
警告是因为这项任务:
int number = &x;
您正在为int*
分配int
,这不是您应该做的。 (1)将x
的值分配给number
,或者(2)将number
的类型更改为int*
(链接pointer2
)并分配地址x
。
或者(3)如果您确实要将x
的地址分配给number
,请使用类型转换。
// (1)
int number = x; // Assign value of x.
// (2)
int* number = &x; // Assign address of x.
// (3)
int number = (int)&x; // Assign address of x and cast to int.
你的第二个问题与指针运算有关。
您的number
变量是int
,这意味着如果您将其递增(+ 1
),它实际上会增加1。
你的pointer2
变量是int*
,这意味着如果你递增它,它会增加int*
的大小(32位系统上4个字节,64位上8个字节)系统)。
这样做完了,这样你就可以通过简单地递增指针来迭代指针数组。
编译器发出警告有两个原因:
1)编译器不会隐式处理类型不匹配,因为标准是这样说的。而这反过来是因为从指针类型转换到另一种类型具有罕见的用例。大多数时间这样的作业都是偶然发生的,作者只是搞砸了间接的程度(*
的数量。)
2)标准禁止这个的另一个原因是int
是4个字节(在大多数实现中),int*
可以是4个或8个字节,具体取决于编译的平台。
答案 2 :(得分:0)
编译器不会将数字从int转换为指针。警告说“从指针生成整数”,而不是“从整数生成指针”,因此number
仍然是int
。它是指针(x
的地址)已被“转换”为普通整数。
答案 3 :(得分:0)
您收到警告,因为不能保证int
类型可以保存指针值(例如,您在int
为16位但指针值为32位的系统上) ;如果你添加一个演员,你告诉编译器你知道你在做什么(即使你不知道):
int number = (int) &x;
这告诉编译器是的,你真的想要取x
的地址并将其视为普通整数。请注意,存储到number
的值可能会被截断。
也不保证所有指针类型具有相同的大小和表示; IOW,指向int
的指针可能与指向char
的指针大小不同,指针可能与指向struct
的指针大小不同。在大多数现代桌面和服务器架构上,它们是相同的,但仍有一些奇怪的架构在那里它们不是。
至于为什么你在添加中得到不同的结果......
向指针添加1会给出指向类型的下一个对象的地址; IOW,如果你有一个指向int
的指针,添加1将为你提供下一个可用int
的地址,即当前地址的sizeof (int)
字节。如果你有一个指向10个元素int
数组的指针,那么加1会得到下一个10个元素数组int
的地址,它是当前10 * sizeof (int)
个字节地址。
这就是数组索引的工作原理。表达式a[i]
被解释为*(a + i)
;也就是说,计算i
之后的a
'元素的地址,并取消引用结果。
答案 4 :(得分:-1)
对“数字”赋值进行类型转换并尝试这样,
int x = 2;
int *pointer2 = &x;
int number = (int)&x;
这样可行。