被C中的指针弄糊涂了

被C中的指针弄糊涂了,c,pointers,C,Pointers,我刚讲到课本上的要点,但解释得不够好,所以我需要一些帮助 我知道指针是什么,它们做什么。例如,我非常理解以下示例: #include <stdio.h> int main () { int num = 5; int *point; point = &num; *point = 8; printf("%d %d", num, *point); return 0; } #包括 int main() { int num=5

我刚讲到课本上的要点,但解释得不够好,所以我需要一些帮助

我知道指针是什么,它们做什么。例如,我非常理解以下示例:

#include <stdio.h>

int main ()
{
    int num = 5;
    int *point;

    point = &num;

    *point = 8;

    printf("%d %d", num, *point);

    return 0;
}
#包括
int main()
{
int num=5;
整数*点;
点=&num;
*点=8;
printf(“%d%d”,num,*点);
返回0;
}
点指向num(将num的地址存储为其值)。然后我解引用point来改变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;
}
#包括
int main()
{
int num=5;
整数*点;
点=8;
printf(“点:%d\n”,点);
printf(“总和(%d)=num(%d)+点(%d)”,num+点,num,点);
返回0;
}
我有几个问题:

1-为什么甚至可以将正常值(8)指定给指针(点)?指针不应该只存储指向其他东西的地址吗?8号线发生了什么

2-我编译了代码,第二次打印显示: 总和(28)=数量(5)+点数(8)
为什么总和等于28?5+8等于13。发生了什么?

在第二个示例中,您为指针指定了8。我希望你从你的编译器那里得到一个很好的警告。但是你可以指定8。只是不要去引用它。您可能会遇到分段错误或更糟的情况。num+point的总和非常合理。这叫做指针算术。点是指向整数的指针。计算机上的int是4字节。num+point的总和是(5*sizeof(int))+8,在您的系统上是28。

您可以将
指向内存地址8(或0x00000008)。它相当于
point=(int*)8我得到了友好的<代码> <代码>错误,因为我使用C++,我想它可以保护我免于愚蠢。

为什么5+8=28?如果向T类型的指针添加一个数字n,则将该指针移动n个T类型的元素。您的计算机正在处理32位整数,大小为4字节,因此8+(5*4)=28。

因为几乎所有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]
位于
0xCAFE004
&arr[2]
位于
0xCAFE008
,以此类推,以4字节为增量

编译器会看到:

int i = arr[5];       // which is equivalent to:
int j = *(arr + 5);
并获取地址
0xcafee0000
,然后添加
(5*sizeof(int))
,在取消引用之前,该地址将显示为
0xcafee0028

这就是为什么当您将任何ol'整数转换为指针类型时,请说:

int *p = (int*) 8;
然后加上:

p = p + 5;    // p := 28

编译器将获取
p
的值,并将其添加到操作数
5
乘以
int

的大小。对于计算机而言,指针只是具有特殊含义的整数值,即内存地址值。因此,将整数值分配给指针始终是可能的,尽管最终可能会得到一个空指针

num+指针为28的原因是您的计算机是因为您使用的计算机中的地址是32位。所以C有一个叫做指针算术的特性,这意味着对指针加上/减去任何值实际上会增加4*num,因为机器上的每个32位字中有4个字节。结果得到point+num==8+(4*5)

==编辑

另外,当您在C中执行指针算术时,计算机实际上会向指针添加数据类型的字节数。例如,如果您声明:

int num = 5;
char * point;
那么当你这么做的时候

point = 8;

point+num==8+5==13的结果,因为在大多数C实现中,char是一个单字节。

指针是一个数字,就像int
是一个数字一样。为指针指定硬编码值是合法的,但会发出警告

point = 8;
但是没有意义,除非你使用的是嵌入式系统,并且知道地址是什么


虽然您的程序经受住了内存访问限制,但您不知道内存地址8的值是多少。所以你不会理解计算的结果。这是未定义的行为,因为程序没有在该地址设置值。

1-为什么甚至可以将正常值(8)分配给指针(点)?指针不应该只存储指向其他东西的地址吗?第8行发生了什么?

指针存储内存地址是正确的,但该内存地址仅记录为一个数字。通常,指针的值要大得多,但没有什么可以阻止您将内存地址分配给指针(8)。但不要期望使用此地址。一种常用的方法是使用

int *point = 0;
2-我编译了代码,第二次打印显示:sum(28)=num(5)+point(8)为什么sum等于28?5+8等于13。发生了什么事?

指针算法的工作方式与您最初预期的不同,除了存储内存位置外,指针还具有内存类型:

int *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;
}
#包括
int main()
{
int x;
int*ptr=&x;
对于(int i=0;i<5;i++)
{
P
#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;
}