与C

时间:2015-05-18 23:29:38

标签: c pointers

我刚刚在我的教科书中找到了指示,但它没有解释得足够好,所以我需要一些帮助。

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

#include <stdio.h>

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

    point = &num;

    *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.发生了什么事?

6 个答案:

答案 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;
}

具体来说,请尝试将xptr的类型从int更改为charlong 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是单个字节。