3

我试图确保我理解这里隐藏的假设是什么。

这里的代码给出了正确的结果。

#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

有人可以证实我的怀疑,这仅是因为两件事:

  1. struct 成员在 n 字节边界处对齐(n != 1)(n = 4,似乎,在询问 sizeof()-s 时)
  2. 第一个成员(即 a char)在 n 字节边界之前未使用的字节被归零。

我看不到 printf 正常工作的其他解释,因为它需要一个以零结尾的 char[]。

此外,这样做是否明智(在单目标嵌入式代码情况之外,优化可能超过可读性和可移植性问题),即。这些假设或多或少普遍正确吗?

第一周间歇性地弄乱 C,所以我很绿。

4

2 回答 2

2

您可以自己证明 1 和 2(我使用 x64,这就是为什么所有结构都是 8 字节对齐的)

objdump ./main -s -j .data

Contents of section .data:
 601030 00000000 00000000 00000000 00000000  ................
 601040 63000000 00000000 00000000 00000000  c...............
 601050 00000000 00000000 00000000 00000000  ................
 601060 65000000 00000000 00000000 00000000  e...............
 601070 00000000 00000000 00000000 00000000  ................
 601080 66000000 00000000 00000000 00000000  f...............
 601090 00000000 00000000 00000000 00000000  ................
 6010a0 62000000 00000000 40106000 00000000  b.......@.`.....
 6010b0 00000000 00000000 00000000 00000000  ................
 6010c0 64000000 00000000 60106000 00000000  d.......`.`.....
 6010d0 80106000 00000000 00000000 00000000  ..`.............
 6010e0 61000000 00000000 a0106000 00000000  a.........`.....
 6010f0 c0106000 00000000                    ..`.....   
于 2014-10-05T11:38:15.017 回答
2

为了验证您的假设,您可以在运行时使用调试器或使用一些 printf 检查代码。

例如,使用:

  char *ptr=(char *)&t;
  printf("%02X %02X %02X %02X\n",ptr[0],ptr[1],ptr[2],ptr[3]);

确实,您确定的假设通常是正确的,但您不能依赖它们。我肯定会这么说

  printf(&t->flag);

显然是错误的,因为它依赖于标准不保证的假设。tt

于 2014-10-05T11:50:30.293 回答