【问题标题】:Does C always have to use pointers to handle addresses?C 是否总是必须使用指针来处理地址?
【发布时间】:2019-02-12 23:08:37
【问题描述】:

据我了解,C 必须处理地址的所有情况都涉及使用指针。例如,& 操作数创建了一个指向程序的指针,而不是仅仅给出裸地址作为数据(即它在不先使用指针的情况下永远不会给出地址):

scanf("%d", &foo)

或者当使用 & 操作数时

int i; //a variable
int *p; //a variable that store adress
p = &i; //The & operator returns a pointer to its operand, and equals p to that pointer.

我的问题是:C 程序总是必须使用指针来管理地址有什么原因吗?是否存在 C 可以自己或使用其他方法处理裸地址(地址的数值)的情况?或者这完全不可能? (由于系统架构,内存分配在每个运行时期间和期间发生变化等)。最后,如果地址因内存管理而改变,那会有用吗?如果是这样的话,这就是为什么总是需要指针的原因。

我试图弄清楚在 C 标准化语言中是否必须使用使用指针。不是因为我想使用其他东西,而是因为我想确定使用地址的唯一方法是使用指针,而忘记其他一切。

编辑:由于部分问题已在 Eric Postpischil、Michał Marszałek、user3386109、Mike Holt 和 Gecko 的 cmets 中得到解答;我将在此处对这些位进行分组:是的,由于不同的因素,使用裸地址几乎没有用处(指针允许许多操作,每次运行程序时地址可能会改变,等等)。正如 Michał Marszałek 所指出的(没有双关语),scanf() 使用指针,因为 C 只能处理副本,因此需要一个指针来更改所使用的变量。即

int foo;
scanf("%d", foo) //Does nothing, since value can't be changed
scanf("%d", &foo) //Now foo can be changed, since we use it's address.

最后,正如 Gecko 所说,指针是用来表示间接的,以便编译器可以区分数据和地址。

John Bode 在它的答案中涵盖了大部分这些主题,所以我会标记那个。

【问题讨论】:

  • 指针是 C 表示地址的方式,所以,是的,你总是必须使用指针来处理地址。
  • 我认为没有“裸地址”之类的东西。例如,在您的示例中,foo(可能)是一个整数值,而不是整数值的“裸地址”。 & 运算符将该整数的地址作为指针产生。 (在 C 中有一个 void * 这样的东西,但这只是一个类型信息被剥离的指针——尽可能避免使用它,它很容易用错,因为编译器将无法帮助您发现错误)
  • 地址是一个数值,你可以使用 unsigned int 来保存一个地址,只要地址适合这个值。点在那里表示间接,以便编译器可以在数据和地址之间做出区别
  • 我没有看到你所做的区分——“只是地址”会是什么样子? “只是地址”与指针有何不同?
  • @Chabon 对象的地址不会因为“内存管理”而改变。 C 没有垃圾收集器或类似的东西。对象不会像某些语言那样在内存中移动。指针只是一个整数,它保存一些其他对象的地址。它的值不会改变,除非你改变它。它们允许一些不同的语言级别操作(即下标、不同的加法语义),但在汇编级别没有区别(在大多数现代架构上)。

标签: c pointers memory-address


【解决方案1】:

指针一个地址(或者,更准确地说,它是一个地址的抽象)。指针是我们在 C 中处理地址值的方式。

在少数域之外,“裸地址”值本身根本没有用。我们对地址的兴趣不如该地址的对象。 C 要求我们在两种情况下使用指针:

  • 当我们希望函数写入参数时
  • 当我们需要跟踪动态分配的内存时

在这些情况下,我们并不真正关心地址值实际上是什么;我们只需要它来访问我们感兴趣的对象。

是的,在嵌入式世界中,特定地址值是有意义的。但是您仍然使用指针来访问这些位置。就像我上面所说的,指针我们的目的的地址。

【讨论】:

    【解决方案2】:

    C 允许您将指针转换为整数。 <stdint.h> 标头提供了一个uintptr_t 类型,其属性是任何指向void 的指针都可以转换为uintptr_t 并返回,结果将与原始指针进行比较。

    根据 C 2018 6.3.2.3 6,将指针转换为整数的结果是实现定义的。非规范注释 69 说“将指针转换为整数或将整数转换为指针的映射函数旨在与执行环境的寻址结构保持一致。”

    因此,在地址是简单编号方案的机器上,将指针转换为uintptr_t 应该为您提供自然机器地址,即使标准不需要它。但是,在某些环境中,地址更复杂,将指针转换为整数的结果可能并不简单。

    【讨论】:

    • @Chabon:这取决于您要使用它的任务。如果要在 C 中存储或检索某个对象的内容,则必须使用指针。但是,如果您想为特殊目的对齐地址(例如,实现快速 SIMD 代码),您可能需要将地址作为整数处理,然后将它们转换回来。
    【解决方案3】:
    int i; //a variable
    int *p; //a variable that store adres
    i = 10; //now i is set to 10
    p = &i; //now p is set to i address
    *p = 20; //we set to 20 the given address
    int tab[10]; // a table
    p = tab; //set address
    p++; //operate on address and move it to next element tab[1]
    

    我们可以通过指针向前或向后移动来操作地址。我们可以设置和读取给定的地址。

    在 C 语言中,如果我们想从函数中获取返回值,我们必须使用指针。或者使用函数的返回值,但这样我们只能得到一个值。

    在 C 中我们没有引用,因此我们必须使用指针。

    void fun(int j){
    j = 10;
    }
    void fun2(int *j){
    *j = 10;
    }
    int i;
    i = 5; // now I is set to 5
    fun(i);
    //printf i will print 5
    fun2(&i);
    //printf I will print 10
    

    【讨论】:

    • 这似乎是一个很好的理由。对不起,如果我一直重复这个问题,但这是否意味着以实际方式使用地址的唯一(我的意思是 only)方法是创建一个指针变量,而不是别的?
    • 指针本身是可变的。在 C 中,当我们调用函数时,编译器会复制我们传递给函数的变量。因此,我们无法通过该方法获得任何返回值。但是如果我们将地址传递给它,它可以更改设置地址的变量。我将编辑我的答案以更好地回答它。
    • 我知道这是在参数传递中使用指针的原因。但是,这是否意味着 & 运算符是一个函数,这就是为什么使用指针 var 而不是 unsigned int 的原因?
    • 否 & 不是函数。 & 是一个对变量起作用并返回地址或变量的运算符。 (我不明白这个问题)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    • 2015-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多