【问题标题】:What can a pointer do that a variable can't do?指针能做什么变量不能做什么?
【发布时间】:2015-09-27 08:43:43
【问题描述】:

我正在学习指针,并被告知:“指针的目的是允许您手动直接访问一块内存。”

假设我有int var = 5;。我不能使用变量“var”来访问存储值 5 的内存块,因为我可以随时更改变量的值var = 6;?当我可以通过使用变量而不是使用指向存储值的地址的指针来访问任何变量的值时,我真的需要一个指针吗?

【问题讨论】:

  • 重要的概念是pointer aliasing
  • "指针的目的是让你手动、直接访问一块内存。"有点奇怪的说法;我会说指针的主要用途是在您没有可用变量名称的情况下(例如,实现按引用传递,或访问动态分配的对象,或访问具有变化索引的数组成员)

标签: c pointers


【解决方案1】:

“指针的目的是让你手动、直接访问一块内存。”

这并不总是正确的。考虑

*(int*)(0x1234) = some_value;

这是“直接”内存访问。虽然

int a = some_value, *ptr = &a;
*ptr = some_other_value;

您现在正在访问a间接

我不能使用变量'var'来访问内存块吗? 存储值 5,因为我可以更改变量的值 每当我想要 var = 6; ?

当然;但语义不同。

当我可以通过使用变量来访问任何变量的值而不是使用指向存储值的地址的指针时,我真的需要一个指针吗?

不,你没有。考虑第一个例子:在声明a 的范围内,通过ptr 修改其值是毫无意义的! 但是,如果你不在a的范围内怎么办?那是

void foo(int x)
{
     x = 5;
}

int main(void)
{
    int x = 10;
    foo(x);
}

foo中,当你做x = 5时,有一个歧义:你想修改foo::x还是main::x?在后一种情况下,必须明确地“请求”,而通过指针(或者更好的是,通过间接)发生的事实是巧合和语言选择。其他语言有其他语言。

【讨论】:

    【解决方案2】:

    指针类型有一些特性让它们非常有用:

    1. 保证指针很大,可以容纳架构支持的任何地址(在 x86 上,即 32 位,即 4 字节,以及 x64 64 位,即 8 字节)。
    2. 对内存的引用和索引是按对象完成的,而不是按字节完成的。

      int buffer[10];
      char*x = buffer;
      int*y  = (int*)buffer;
      

    那样,x[1] 不是 y[1]

    如果您使用简单的ints 来保存您的值,则两者都无法保证。第一个特征至少由uintptr_t 保证(虽然不是size_t,尽管大多数时候它们具有相同的大小 - 除了size_t 在具有分段内存布局的系统上可以是2字节大小,而@ 987654326@ 的大小仍然是 4 个字节)。

    虽然起初使用ints 可能会奏效,但您总是:

    1. 必须将值转换为指针
    2. 必须取消引用指针
    3. 并且必须确保您的“指针”没有超出某些值。对于 16 位 int,您不能超过 0xFFFF,对于 32 位,它是 0xFFFF FFFF - 一旦您这样做了,您的指针可能会在您不注意的情况下溢出,直到为时已晚。

    这也是链接列表和指向不完整类型的指针起作用的原因 - 编译器已经知道您要指向的指针的大小,并且只是为它们分配内存。所有指针都具有相同的大小(在 32 位/64 位架构上为 4 或 8 个字节)——您分配给它们的类型只是告诉编译器如何取消引用该值。 char*s 占用与void*s 相同的空间,但不能取消引用void*s。编译器不会让你。

    另外,如果你只是处理简单的整数,很有可能你会显着减慢你的程序对所谓的“别名”所做的事情,这基本上会迫使编译器一直读取给定地址的值.虽然内存访问很慢,所以您需要优化这些内存访问。

    【讨论】:

    • 这似乎遗漏了一个更基本的问题,即指针允许您在不知道与该对象关联的变量名称的情况下访问一个对象。
    • 你已经超出了 OP 的要求。
    【解决方案3】:

    您可以将内存地址与街道地址进行比较:

    如果您订购商品,请告诉商店您的地址,以便他们将您购买的商品寄给您。 如果你不想使用你的地址,你必须把你的房子寄给他们,这样他们就可以把包裹放在里面。 后来他们把你的房子还给你。这比使用地址要麻烦一点!
    如果您不在家,如果您的邻居有您的地址,包裹可以递送给他们,但如果您不在家,则这是不可能的 你把你的房子寄给了他们。

    指针也是如此:它们很小,可以很容易地传输,而它们指向的对象 可能很大,而且不太容易运输。
    使用指针算法,指针也可以用于访问它们最初指向的对象以外的其他对象。

    【讨论】:

      【解决方案4】:

      你从 main() 或另一个函数调用一个函数,你调用的函数只能返回 1 个值。 假设您想要更改 3 个值,您将它们作为指针传递给被调用的函数。这样您就不必使用全局值。

      【讨论】:

      • 你也可以返回一个结构体。
      【解决方案5】:

      一个可能的优点是它可以使一个函数更容易修改一个变量,该变量将被许多其他函数使用。如果没有指针,最好的选择是让修改函数返回一个值给调用者,然后将该值传递给其他函数。这可能会导致大量的传递。相反,您可以给修改函数一个指针,它存储其输出,所有其他函数直接访问该内存地址。有点像全局变量。

      【讨论】:

        猜你喜欢
        • 2016-11-20
        • 2011-08-23
        • 2018-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多