2014-02-07 3 views
1

Так у меня есть структура выглядит следующим образом:массив структур указателей как первый элемент структуры

typedef struct tree tree; 

struct tree { 
    tree* child[10]; 
    int value; 
}; 

и функцию, чтобы добавить ребенка и вернуть его адрес следующим образом:

tree* tree_add_child(tree* parent, int index) 
{ 
    tree* p = *(parent->child + index); 

    if (p == NULL) 
    { 
      p = tree_new_tree(); //malloc new tree - init it - return its address 
      *(parent->child + index) = p; 
    } 
    return p; 
} 

Он работает как я хочу, чтобы он был так, как есть. Но я бы хотел заменить все parent->child s на parent, так как они указывают на тот же адрес, и я чувствую, что дополнительный доступ к памяти не нужен. Но когда я это делаю, у меня появляется ошибка, которую я пытаюсь назначить treetree*.

Как я могу это сделать, и есть ли какие-либо другие оптимизации, которые я мог бы сделать, чтобы сделать этот запуск быстрее?

+0

Ведущее * не надо там, потому что я ожидал бы родитель уже быть заостренный. Вы не хотите разыскивать свой контент, вы хотите указать p на адрес в parent + index. –

ответ

2

Если понять этот вопрос, вы хотите заменить

tree* p = *(parent->child + index); 

с

tree* p = *(parent + index); 

и также с другой экземпляр> ребенка родительский, чтобы оптимизировать свою программу за счет сокращения доступа к памяти.

В коде нет избыточных обращений к памяти.

parent->child 

и

parent 

сделать имеют один и тот же адрес, и компилятор знает, что это. Он не должен заглядывать в память, чтобы узнать, какой относительный адрес ребенка принадлежит родителям. Он знает смещение (ноль, в данном случае). Это не похоже на то, что в структуре есть таблица смещений для каждого из ее членов; они известны во время компиляции. Это является частью причины того, что полное определение структуры (а не только ее имени посредством форвардной декларации) должно быть известно для использования его членов.

Даже если это так, вы не можете просто заменить все выражения, которые могут быть разрешены на один и тот же адрес друг с другом. Тип безопасности заключается в том, чтобы защитить вас от тонких ошибок именно такой замены, и, гарантируя, что вы присваиваете значения «tree *» значениям «tree *» (и т. Д.), Компилятор помогает вам предотвращать ошибки.

+0

Спасибо. Но только из любопытства, если бы я хотел сделать что-то подобное, как бы я это сделал? –

+0

Извините, я не понимаю. Если бы вы хотели сделать что-то вроде того, что именно? –

+1

@vitakraft У вас нет. parent и parent-> child не имеют одного и того же типа, а для арифметики указателя требуется правильный тип (так как выполнение чего-то типа '+ child' перемещает' child' число _objects_, а не число _bytes_. – tabstop

0

Я имел это в комментариях, но это было слишком сложно, чтобы правильно форматировать текст ...

Что у вас сейчас выглядит хорошо, но не на самом деле показать, что вы пытались сделать. Например, вы говорите, что вы пробовали это:

tree *p = parent + index; 

Это то, что возвращает ошибку? Если да, то вы объявляя родителей быть

struct tree parent; 

или

struct tree *parent; 

Вы должны были бы объявить его как второй.

+0

'tree * p = * (parent + index);' звучало прямо на меня, но не строит. Я также пробовал ваш, он строит, но не работает. Я определил 'parent' как' tree * ', в аргументах. –

+0

На этом этапе я предлагаю вам либо сделать это, указав элемент или перейдя по структуре, используя void *, и распечатайте каждое значение в виде шестнадцатеричного значения. Возможно, что-то происходит в компиляторе, который создает отступы по мере выделения массива или других значений. –

0

Вы должны попробовать:

tree* p = parent + index; 
+0

Это не работает, Мне не нужен адрес указателя, мне нужен объект, на который указывает адрес. –

Смежные вопросы