Skip to content

Comment on Ask HN: Favorite pointer tricks in C?

Comments

pointers to structs for things like network protocols...

struct packet_header { uint from_addr; uint to_addr; ushort flags; ... }

packet *p;

read(socket, somebuf, sizeof(packet));

p = &somebuf;

printf("from = %u to = %u flags = %u\n",p->from_addr, p->to_addr, p->flags);

Don't use structures as lenses over unchecked input data.

Won't this leave all multi-byte values in network endianness?

Yes, but so do the OS socket data structures, which is why htons() and htonl() are in the first chapter of any book on network programming.

The bigger problem with this scheme is alignment, although we appear to have outgrown architectures that will blow up when you get this wrong.

You do have to be careful, it can be annoying on ARM chips certainly. If you're using GCC, __attribute__ ((packed)) fixes alignment issues.

This method is so much less error prone than pulling stuff out a byte at a time. Plus you can use unions for network addresses, etc.

It's a simplified example to show what you can do.

It's a good trick, but I disagree that it's the right way to do it. My preferred idiom looks something like:

  s->field1 = ld32(&cp, ep); 
  s->field2 = ld16(&cp, ep); 
  s->field3 = ld16(&cp, ep); 
  s->field4 = ld8(&cp, ep); 
  s->field5 = ld8(&cp, ep); 
  s->field6 = ld32(&cp, ep); 
 
You can just about automate this with a macro (you need to macro out the structure fields and use them both for the structure declaration and the field expansion), but the extra function call there gives you an opportunity to be defensive about e.g. buffer sizes, never blows up alignment, and isn't appreciably slower.

If you're willing to use packed structs, here's a neat one when you're dealing with e.g., the entry controls in VMX.

From my virtual machine work:

  struct vmx_entry_ctrls {
      union {
          uint32_t value;
          struct {
              uint_t rsvd1                : 2;
              uint_t ld_dbg_ctrls         : 1;
              uint_t rsvd2                : 6;
              uint_t guest_ia32e          : 1;
              uint_t smm_entry            : 1;
              uint_t no_dual_monitor      : 1;
              uint_t rsvd3                : 1;
              uint_t ld_perf_glbl_ctrl    : 1;
              uint_t ld_pat               : 1;
              uint_t ld_efer              : 1;
              uint_t rsvd4                : 16;
          } __attribute__((packed));
      } __attribute__((packed));
  } __attribute__((packed));
AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.