Что такое прямая ссылка в C?

6 Manoj Doubts [2008-11-28 19:52:00]

Что такое прямая ссылка в C относительно указателей?

Можно ли привести пример?

c pointers


6 ответов


10 Решение strager [2008-11-28 19:54:00]

См. эту страницу пересылаемые ссылки. Я не вижу, как перекрестные ссылки будут отличаться от указателей и других типов PoD.

Обратите внимание, что вы можете перенаправлять типы объявлений и объявлять переменные, которые являются указателями на этот тип:

struct MyStruct;
struct MyStruct *ptr;
struct MyStruct var;  // ILLEGAL
ptr->member;  // ILLEGAL

struct MyStruct {
    // ...
};

// Or:

typedef struct MyStruct MyStruct;
MyStruct *ptr;
MyStruct var;  // ILLEGAL
ptr->member;  // ILLEGAL

struct MyStruct {
    // ...
};

Я думаю, что это то, о чем вы просите, когда имеете дело с указателями и декларацией вперед.


7 Arkadiy [2008-11-28 20:22:00]

Я думаю, что "прямая ссылка" относительно указателей означает что-то вроде этого:

struct MyStruct *ptr; // this is a forward reference.

struct MyStruct
{
  struct MyStruct *next; // another forward reference - this is much more useful
  // some data members
};

Указатель объявляется до того, как будет определена его структура.

Компилятор может уйти от этого, потому что указатель хранит адрес, и вам не нужно знать, что на этом адресе зарезервировать память для указателя.


5 Vincent Robert [2008-11-28 20:45:00]

Прямая ссылка - это когда вы объявляете тип, но не определяете его.

Он позволяет использовать тип по указателю (или ссылке для С++), но вы не можете объявить переменную.

Это способ сказать компилятору, что что-то существует

Скажите, что у вас есть структура Plop, определенная в Plop.h:

struct Plop
{
   int n;
   float f;
};

Теперь вы хотите добавить некоторые служебные функции, которые работают с этой структурой. Вы создаете еще один файл PlopUtils.h (скажем, вы не можете изменить Plop.h):

struct Plop; // Instead of including Plop.h, just use a forward declaration to speed up compile time

void doSomething(Plop* plop);
void doNothing(Plop* plop);

Теперь, когда вы реализуете эту функцию, вам понадобится определение структуры, поэтому вам нужно включить файл Plop.h в PlopUtils.cpp:

#include "PlopUtils.h"
#include "Plop.h" // now we need to include the header in order to work with the type

void doSomething(Plop* plop)
{
   plop->n ...
}

void doNothing(Plop* plop);
{
   plop->f ...
}

3 Mike Dunlavey [2008-11-28 23:36:00]

Я думаю, что у компилятора C изначально был проход, в котором он делал сборку таблиц символов и семантический анализ. Так, например:

    ....
    ... foo(a,b) + 1 ... // assumes foo returns int
    ....

    double foo(double x, double y){ ... } // violates earlier assumption

чтобы предотвратить это, вы говорите:

    double foo(double x, double y); // this is the forward declaration

    ....
    ... foo(a,b) + 1 ... // correct assumptions made
    ....

    double foo(double x, double y){ ... } // this is the real declaration

У Паскаля была та же концепция.


2 Federico A. Ramponi [2008-11-29 04:19:00]

Добавление к предыдущим ответам. Типичная ситуация, когда обязательная ссылка является обязательной, - это когда struct foo содержит указатель на панель структуры, а bar содержит указатель на foo (круговая зависимость между объявлениями). Единственный способ выразить эту ситуацию на C - использовать форвардное объявление, то есть:

struct foo;

struct bar
{
   struct foo *f;
};

struct foo
{
   struct bar *b;
};

-5 Din [2008-11-28 21:03:00]

Прямые ссылки позволяют компилятору C делать меньше проходов и значительно сокращать время компиляции. Вероятно, это было важно около 20 лет назад, когда компьютеры были намного медленнее и менее эффективны.