指针可以做什么,变量不能做?

时间:2015-09-27 08:43:43

标签: c pointers

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

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

4 个答案:

答案 0 :(得分:1)

指针类型有一些特性使它们真正有用:

  1. 保证指针会如此之大,以至于它可以容纳架构支持的任何地址(在x86上,即32位a.k.a.4字节,x64 64位a.k.a. 8字节)。
  2. 对每个对象进行取消引用和索引内存,而不是每个字节。

    int buffer[10];
    char*x = buffer;
    int*y  = (int*)buffer;
    
  3. 那样,x [1]不是y [1]

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

    虽然首先使用int可能会有效,但您总是:

    1. 必须将值转换为指针
    2. 必须取消引用指针
    3. 并且必须确保您的“指针”不超出某些值。对于一个16位的int,你不能超过0xFFFF,因为32位它是0xFFFF FFFF - 一旦你这样做,你的指针可能会溢出而你没有注意到它为时已太晚。
    4. 这也是链接列表和指向不完整类型的指针的原因 - 编译器已经知道你要指向的指针的大小,并且只为它们分配内存。所有指针都具有相同的大小(在32位/ 64位体系结构上为4或8个字节) - 您分配它们的类型只是告诉编译器如何取消引用该值。 char*占用与void* s相同的空格,但您不能取消引用void* s。编译器不会让你。

      另外,如果你只是处理简单的整数,你很可能会大大减慢你的程序对“别名”的影响,这基本上迫使编译器一直读取给定地址的值。但内存访问速度很慢,因此您希望优化这些内存访问。

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

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

答案 3 :(得分: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?在后一种情况下,必须明确地“请求”,并且通过指针发生的事实 - 或者更好,通过间接 - 是巧合和语言选择。其他语言也有其他语言。