我刚刚在我的教科书中找到了指示,但它没有解释得足够好,所以我需要一些帮助。
我知道指针是什么以及他们做了什么。例如,我非常了解以下示例:
#include <stdio.h>
int main ()
{
int num = 5;
int *point;
point = #
*point = 8;
printf("%d %d", num, *point);
return 0;
}
指向num(将num&#39; s地址作为其值)。然后我解除引用点以更改num。的原始值
现在考虑相同示例的明显修改版本:
#include <stdio.h>
int main ()
{
int num = 5;
int *point;
point = 8;
printf("point: %d\n", point);
printf("sum (%d) = num (%d)+ point (%d)", num+point, num, point);
return 0;
}
我有几个问题:
1-为什么甚至可以为指针(点)分配正常值(8)?是不是应该只将地址存储到其他东西?第8行发生了什么?
2-我编译了代码,第二个printf显示: sum(28)= num(5)+ point(8) 为什么总和等于28? 5 + 8是13.发生了什么事?
答案 0 :(得分:6)
您可以将point
指向内存地址8(或0x00000008)。这相当于point = (int*)8;
我收到了一个友好的<Unable to read memory>
错误,因为我使用的是c ++而我认为它可以保护我免受愚蠢的侵害。
为什么5 + 8 = 28?如果向类型为T的指针添加数字n,则将此指针移动到类型为T的n个元素。您的机器正在处理32位整数,大小为4字节,因此8 +(5 * 4)= 28
答案 1 :(得分:3)
在第二个示例中,您为指针指定了8。我希望你的编译器得到一个很好的警告。但你可以分配8.只是不要取消引用它。您可能会遇到分段错误或更糟。 num + point的总和非常有意义。它叫做指针算术。 point是指向整数的指针。你机器上的int是4个字节。 num + point的总和是(5 * sizeof(int))+ 8,在你的系统上是28。
答案 2 :(得分:3)
因为几乎所有C编译器都将指针实现为整数以支持指针运算。
int arr[10];
int *ip = arr;
arr[2] = 42; // this is equivalent to:
*(ip + 2) = 42; // or
*(2 + ip) = 42;
让我们说,&arr[0]
(整数数组arr
的第一个元素的地址)是0xcafe0000
。假设一个int
值占用内存中的4个字节。然后&arr[1]
位于0xcafe0004
,&arr[2]
位于0xcafe0008
,依此类推,增量为4个字节。
编译器看到了这个:
int i = arr[5]; // which is equivalent to:
int j = *(arr + 5);
并获取地址0xcafee0000
,然后在解除引用之前添加(5 * sizeof(int))
0xcafee0028
。
这就是为什么当你施展任何一个ol&#39;指针类型的整数,例如:
int *p = (int*) 8;
然后添加它:
p = p + 5; // p := 28
编译器将获取p
的值,并将其添加到操作数5
乘以int
的大小。
答案 3 :(得分:3)
指针是一个数字,就像int
是一个数字一样。为指针分配硬编码值是合法的,但会发出警告
point = 8;
但除非您正在使用嵌入式系统并知道该地址的内容,否则无意义8。
虽然您的程序在内存访问限制中幸存下来,但您不知道内存地址8的值是什么。因此您无法理解计算结果。它是未定义的行为,因为程序没有在该地址设置值。
答案 4 :(得分:2)
1 - 为什么甚至可以为指针(点)分配正常值(8)?是不应该只将地址存储到其他东西的指针?第8行发生了什么?
指针存储内存地址是正确的,但这个内存地址只记录一个数字。通常,指针的值要大得多,但没有什么可以阻止你为指针分配内存地址(8)。不要指望使用这个地址。通常使用的一种方法是使用NULL pointers。
int *point = NULL;
与
相同int *point = 0;
2-我编译了代码,对于第二个printf,它显示:sum(28)= num(5)+ point(8)为什么sum等于28? 5 + 8是13.发生了什么?
指针算法不像您最初期望的那样工作,并且存储内存位置,指针也有一个内存类型:
int *point;
在这种情况下point
知道它指向int
。因此,当一个递增的指针不会使它的位置增加一个字节时,它会增加sizeof(int)
,在你的情况下是4个字节。这意味着point++
或point = point + 1
会将指针移动到它认为当前指向的任何大小,这样做的原因是可以轻松地沿着数组或内存块移动相同类型的物体。
要了解这个概念,请尝试使用这一段代码
#include <stdio.h>
int main()
{
int x;
int * ptr = &x;
for(int i = 0; i < 5; i++)
{
printf("pointer address: %p\n", ptr + i);
}
return 0;
}
具体来说,请尝试将x
和ptr
的类型从int
更改为char
或long long
并查看其所带来的差异!
答案 5 :(得分:1)
事情是计算机指针只是具有特殊含义的整数值,即内存地址值。因此,总是可以将整数值赋给指针,尽管最终可能会得到一个空指针。
num +指针为28的原因是因为您的计算机是因为您正在使用的计算机中的地址是32位。因此C具有称为指针算法的这一特性,这意味着向指针添加/减去任何值实际上会增加4 * num,因为机器具有的每个32位字中有4个字节。结果你得到了点+ num == 8 +(4 * 5)。
===编辑
另外,当你在C中进行指针运算时,机器实际上会向指针添加数据类型的字节数。例如,如果您声明:
div
然后当你做
ul
point + num == 8 + 5 == 13的结果,因为在大多数C实现中,char是单个字节。