繁体   English   中英

与C中的指针混淆了

[英]Got confused with pointers in C

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

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

#include <stdio.h>

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

    point = &num;

    *point = 8;

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

    return 0;
}

point指向num(将num的地址存储为其值)。 然后我解除引用点来改变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- i编译了代码,对于第二个printf,它显示:sum(28)= num(5)+ point(8)为什么sum等于28? 5 + 8是13.发生了什么?

你可以点point ,在内存地址8(或0x00000008)。 它相当于point = (int*)8; 我得到一个友好的<Unable to read memory>错误,因为我正在使用c ++,我认为它保护我免受我的愚蠢。

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

在第二个示例中,您为指针指定了8。 我希望你的编译器得到一个很好的警告。 但你可以分配8.只是不要取消引用它。 您可能会遇到分段错误或更糟。 num + point的总和非常有意义。 它叫做指针算术。 point是指向整数的指针。 你机器上的int是4个字节。 num + point的总和是(5 * sizeof(int))+ 8,在您的系统上是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]位于0xcafe0004&arr[2]位于0xcafe0008 ,依此类推,增量为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的大小

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

point = 8;

但除非你正在使用嵌入式系统并知道该地址是什么,否则无意义8。

尽管您的程序在内存访问限制中幸存,但您不知道内存地址8的值是什么。因此您无法理解计算结果。 这是未定义的行为,因为程序没有在该地址设置值。

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

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

int *point = NULL;

是相同的

int *point = 0;

2- i编译了代码,对于第二个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并查看它所产生的差异!

问题是计算机指针只是具有特殊含义的整数值,即内存地址值。 因此,总是可以将整数值赋给指针,尽管最终可能会得到一个空指针。

num +指针为28的原因是因为您的计算机是因为您正在使用的计算机中的地址是32位。 因此C具有称为指针算法的这一特性,这意味着向指针添加/减去任何值实际上会增加4 * num,因为机器具有的每个32位字中有4个字节。 结果你得到了点+ num == 8 +(4 * 5)。

===编辑

同样,当你在C中进行指针运算时,机器实际上会向指针添加数据类型的字节数。 例如,如果您声明:

int num = 5;
char * point;

然后当你这样做

point = 8;

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM