【问题标题】:Confusion regarding Handling of Different Pointers by Compiler关于编译器处理不同指针的困惑
【发布时间】:2012-03-27 16:26:08
【问题描述】:

我对指针有一些困惑。

我将所有这些都以问题的形式提出。

1) 编译器如何处理各种指针?
2) 编译器如何判断编译时传递的指针的数据类型?

据我所知,指针以无符号整数的形式存储在内存中,用于保存它所指向的对象的基地址。
现在,起关键作用的是符号表吗?

【问题讨论】:

  • 什么告诉你编译器在运行时确定指针的数据类型?
  • 这个问题有点混乱,但它表现出对正确事物的好奇心。为了帮助您集中问题,请考虑编译器,根据定义,在运行时不会解决任何问题,而只会在编译时解决。在已编译的 C 程序中,通常不可能确定运行时指向的对象的类型。相反,类型必须在编译时已知。在 C++ 中,有动态类型识别,但从你的问题的基调来看,我怀疑这就是你想要的。
  • @thb,好吧,实际上我认为,在词法分析阶段符号表形成期间的编译时,编译器会找出指针并写出有关类型的足够信息指针。我想知道这个的正确性。
  • 小心假设指针是“真正的”无符号整数。它们通常以类似的方式表示,但最好将指针和 pointers 视为指针。例如,在某些系统中,指针在内部表示为基址和偏移量,两个不同的基址+偏移量对可以指向同一个内存位置。

标签: pointers compiler-construction compiler-theory


【解决方案1】:

也许一个具体的例子会有所帮助。试试这个:

#include <stdio.h>

const double step_size = 5.0; // degrees of arc

struct Location {
    double latitude;
    double longitude;
};

void go_north(struct Location *const loc) {
    loc->latitude += step_size;
}

int main() {
    struct Location there;
    there.latitude  =   41.0;
    there.longitude = -101.5;
    go_north(&there);
    printf("Lat. %6.1f, long. %6.1f.\n", there.latitude, there.longitude);
    return 0;
}

编译器怎么知道 *go_north()* 接收到的地址是 struct Location 的地址? 答:程序员已经说过了,通过写函数控制 *void go_north(struct位置 *const loc).*

关于你对词法分析的评论,不管你信不信,链接器不需要知道所指向对象的大小或布局,即使指向这些对象的指针在各种*之间传递。 o 个对象。这就是使用头文件的原因:以便预链接编译器在预链接编译时正确了解布局。在特殊情况下,符号表中可能会出现很多奇怪的东西,所以我不会如此大胆地断言,没有任何符号表包含您建议的信息;但在正常使用中,符号表会省略这些信息,因为链接器不需要它。

有人怀疑这并不能完全回答您的问题,但该示例可能有助于集中问题,使其足够具体以至于可以回答。所以,如果一个具体的例子有帮助,再加上这个部分答案,那就是。

(如果您碰巧在 Linux 平台上,您可能会发现 readelf 命令非常有趣。)

【讨论】:

  • 我实际上无法弄清楚您所说的“没有符号表包含您建议的信息”是什么意思。如果没有存储这些变量,那么语义分析怎么可能?您的意思是说它们不是作为指针而是作为普通变量存储的?对不起,如果我误解了。
  • 哦,我明白了。你和我使用的术语符号表不同。是的你是对的。在编译器内部,在编译时,暂时存在一个包含您所查找信息的表。但是,并非此表中的所有信息都导出到链接器。例如,在示例中,没有关于自动变量 there 的信息被导出到链接器(可能作为调试符号除外,如果您已指示编译器发出此类信息)。
  • 现在我的查询对你来说有点清楚了,你能告诉我临时表(在编译器的词法分析阶段创建的符号表)中的指针是如何处理的吗?它们被视为正常变量吗?如果是这样并且如果我理解正确,例如,loc(即struct location)的数据类型将存储在符号表中;但它不一定传递给链接器。经过词法、语法、语义分析和代码优化后,它只会保存内存中某个其他位置的地址。如果我错了,请纠正我。
  • @sarthak:我对优化知之甚少,所以让我不要对此发表评论;但是,否则,你是对的。
【解决方案2】:

1) 编译器如何处理各种指针?

它们被作为内存地址处理。通常是 16 或 32 或 64 位无符号整数。

2) 编译器如何判断运行时传递的指针的数据类型?

C 编译器不会在运行时找出任何数据类型。指针类型是在编译时计算出来的。在运行时,指针只是指向未知类型的愚蠢内存地址。

【讨论】:

    【解决方案3】:

    C 语言中没有内置功能可以在运行时确定指针的类型。你总是在编译时就知道类型。

    void(char * x)
    {
      // x points to a char
    }
    

    【讨论】:

    • 好的。但是,如果我从总体上考虑,不是特定于语言?
    • @sarthak:当您询问特定语言的问题时,您不能成为语言激动者。
    • @Als,这不是语言激动,我想知道编译器遇到指针时会处理的过程。
    • @sarthak 我建议您检查编译器的汇编输出,以了解指针的使用方式,并尝试在下次提出更具体的问题。
    猜你喜欢
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    相关资源
    最近更新 更多