Are there any null bytes after the `char` in the structure?
I'm trying to make sure I understand what the hidden assumptions are here.
This code gives correct results.
#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);
}
The output, as expected, is abcdef
Can someone confirm my suspicions that this only works because two things:
- structure members are aligned on n-byte boundaries (n! = 1) (n = 4 seems to be when requesting sizeof () - s)
- bytes not used by the first member (which is
char
) before the n-byte boundary are zeroed out.
I see no other explanation for printf to work correctly otherwise, since it expects a null terminated char [].
Also, is it reasonable to do things like this (outside of a unit-code situation where optimizations might outweigh readability and portability concerns), i.e. Are these assumptions more or less universal?
First week of intermittent messing with C, so I'm pretty green.
source to share
To test your assumptions, you can test the code at runtime with a debugger or with some printf.
For example using
char *ptr=(char *)&t;
printf("%02X %02X %02X %02X\n",ptr[0],ptr[1],ptr[2],ptr[3]);
Indeed, the assumptions you have identified are very often correct, but you cannot rely on them. I would definitely say that
printf(&t->flag);
clearly incorrect as it relies on assumptions that are not guaranteed by the .tt standard
source to share
You can prove 1 and 2 yourself (I am using x64 so all 8bytes are aligned in structs)
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 ..`.....
source to share