Я реализовал дерево в C, и теперь я хочу определить набор деревьев-оболочек.У меня есть итератор для моего дерева в tree.h:
typedef struct tree_iter_t {
void *current;
tree_t *tree;
unsigned char info : 2;
} tree_iter_t;
и функция для получения итератора в tree.c:
tree_iter_t titerator(tree_t *t) {
tree_iter_t it;
it.current = t->min;
if (t->min) it.info = 0;
else it.info = 3;
it.tree = t;
return it;
}
Я могу скомпилировать это с помощью -Wall -O2
без предупреждений.Для моего набора деревьев я определил свой итератор набора деревьев в tset.h следующим образом:
typedef struct tset_t tset_t;
typedef struct tset_iter_t {
tree_iter_t iter;
} tset_iter_t;
и функцию для получения его в tset.c.
struct tset_t {
tree_t *tree;
};
tset_iter_t tsiterator(tset_t *ts) {
tset_iter_t it;
it.iter = titerator(ts->tree);
return it;
}
Когда я компилируюс gcc -Wall -c -combine tset.c tree.c
у меня нет проблем, но когда я добавляю -O2
, я получаю предупреждение о выражении возврата: warning: ‘it.iter.tree’ is used uninitialized in this function
.Почему у GCC есть проблема с этим?Я что-то упускаю из виду?Это выглядит инициализированным для меня.Я запустил gcc -S -O2 tset.c
, чтобы попытаться понять, что происходит, GCC не дал предупреждения и выдал следующее:
tsiterator:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $36, %esp
movl 12(%ebp), %edx
movl 8(%ebp), %ebx
leal -20(%ebp), %eax
movl (%edx), %edx
movl %eax, (%esp)
movl %edx, 4(%esp)
call titerator
movzbl -12(%ebp), %edx
movzbl 8(%ebx), %eax
andl $3, %edx
andl $-4, %eax
orl %edx, %eax
subl $4, %esp
movb %al, 8(%ebx)
movl -16(%ebp), %eax
movl %eax, 4(%ebx)
movl -20(%ebp), %eax
movl %eax, (%ebx)
movl %ebx, %eax
movl -4(%ebp), %ebx
leave
ret $4
Я знаю, оптимизация может генерировать какой-то странно выглядящий код, но, черт возьми, этоздесь происходит?Все мои другие (оптимизированные) функции-обертки представляют собой 10-ти строчные строки сборки (обычные накладные расходы на вызовы функций для вызова функций дерева).gcc -O2 -S -combine tset.c tree.c
дал мне предупреждение, встроенный титратор и произвел это:
tsiterator:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %edx
pushl %ebx
movl 8(%ebp), %eax
movl (%edx), %ecx
movl 4(%ecx), %edx
movl %ecx, 4(%eax)
cmpl $1, %edx
movl %edx, (%eax)
movzbl 8(%eax), %edx
sbbl %ebx, %ebx
andl $3, %ebx
andl $-4, %edx
orl %ebx, %edx
movb %dl, 8(%eax)
popl %ebx
popl %ebp
ret $4
Когда я изменил реализацию на:
tset_iter_t tsiterator(tset_t *ts) {
tset_iter_t it;
tree_iter_t i = titerator(ts->tree);
it.iter = i;
return it;
}
, у него не было проблем.Что GCC оптимизирует (или анализирует) в первом случае и почему он дает мне предупреждение?
Спасибо.