Я пытаюсь убедиться, что понимаю, какие здесь скрытые предположения.
Этот код здесь дает правильные результаты.
#include <stdio.h>
#include <stdlib.h>
struct branch
{
char flag; //value
struct branch *l; //left child
struct branch *r; //right child
};
struct branch c={'c',NULL,NULL};
struct branch e={'e',NULL,NULL};
struct branch f={'f',NULL,NULL};
struct branch b={'b',&c,NULL};
struct branch d={'d',&e,&f};
struct branch a={'a',&b,&d};
void preorder(struct branch* t)
{
printf(&t->flag); //Seems ugly and errorprone
if(t->l) preorder(t->l);
if(t->r) preorder(t->r);
}
int main()
{
preorder(&a);
}
Результат, как и ожидалось, abcdef
Может ли кто-нибудь подтвердить мои подозрения, что это работает только потому, что две вещи:
- члены структуры выравниваются по n-байтовым границам (n! = 1) (n = 4, кажется, при запросе sizeof () - s)
- байты, не используемые первым членом (который является
char
) до n-байтовой границы, обнуляются.
Я не вижу другого объяснения правильной работы printf в противном случае, так как он ожидает символ char [] с завершающим нулем.
Кроме того, разумно ли делать подобные вещи (вне ситуации с одним целевым встроенным кодом, когда оптимизация может перевесить проблемы с удобочитаемостью и переносимостью), т.е. верны ли эти предположения более или менее повсеместно?
Первая неделя периодических возня с C, так что я довольно зеленый.
printf(&t->flag);
действительно уродлив. (Он полагается на то, что символ после поля .flag равен нулю; что не гарантируется)printf("%c", t->flag);
, вероятно, будет стандартным способом. - person wildplasser   schedule 05.10.2014printf
правильно (как предлагает Wildplasser) или использоватьputchar
. - person mafso   schedule 05.10.2014putchar
. Мой опыт показывает, что я не знал об этом. - person Jostikas   schedule 05.10.2014offsetof()
, чтобы определить возможное заполнение. - person 2501   schedule 07.10.2014