Live data from Hacker News

Ask HN: Favorite pointer tricks in C?

news.ycombinator.com

41–50 of 81 posts

Re: Ask HN: Favorite pointer tricks in C?

#41
post #12

Earlier quoted context omitted.

char buf[1024]; /* should be enough */ I actually write this a lot in my code. Not code that I intend to share with others, of course. But I do find it amusing about the value I put in brackets. I find it amusing that I have an OCD-like predisposition to make it a power of two. And I find it amusing how the number between the brackets has increased over the last ten years, from a frugal 64 to an opulent 1024. This, t…

In fact, a lot of code does this to avoid mallocs. Just be sure to check the length before you put anything into the buffer. Also, making it a power of 2 is a good idea if you are concerned about alignment.

Also, making it a power of 2 is a good idea if you are concerned about alignment.

Actually, there are many reasons why this may not be the case. Remember back to when you implemented a user-space memory allocator. One of the most straightforward algorithms is to use power-of-two blocks with varying coalescing algorithms. The problem that you get with your style and this malloc implementation is that, since you need to store memalloc metadata in the block (probably), each block has just slightly less than a power of two space, which means a block request for a power of two will always waste an enormous amount of space by pushing up to the next power of two block size.

Now, this "power of two allocation is best" misconception is so widespread that many memory allocators actually purposefully account for the case where the memory allocation is a power of two and make their block sizes just slightly larger. Just goes to show you what minor things can do to performance.

Re: Ask HN: Favorite pointer tricks in C?

#42
post #40

Instead of using a while loop to iterate through a linked list, consider using a for loop. Node * iter; for (iter=root; iter != NULL; iter=iter->next) { /* iter->object; */ } A concise implementation of strlen size_t strlen(char * str) { char * cur; for(cur=str; *cur; ++cur); return (cur-str); } Reverse a string in-place. void reverse(char * str) { char *i,*j, tmp; for (i=str, j=(str+strlen(str)-1); i

You have a bug in strlen: for(cur=str; cur; ++cur); should be: for(cur=str; *cur; ++cur);

Right you are. Wrote all those in the comment block. Fixed in an edit.

Re: Ask HN: Favorite pointer tricks in C?

#43
post #18

Earlier quoted context omitted.

In fact, a lot of code does this to avoid mallocs. Just be sure to check the length before you put anything into the buffer. Also, making it a power of 2 is a good idea if you are concerned about alignment.

Just be sure to check the length before you put anything into the buffer. No need to check. The comment reassures both me and future maintainers that I have countenanced this potential pitfall! Assign away....

Smashing the Stack for Fun and Profit...

Re: Ask HN: Favorite pointer tricks in C?

#44
post #29
post #24

Earlier quoted context omitted.

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.

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));

Re: Ask HN: Favorite pointer tricks in C?

#45
post #36
post #25

* Using pointer offsets to get to the stack frame pointer, and then walking the frame pointer backwards to get the call stack. * Using && to take the address of a jump label. * Casting a u_int32_t over a 4-byte string (like an SMTP verb) to get a value you can switch() on.

> Casting a u_int32_t over a 4-byte string (like an SMTP verb) to get a value you can switch() on. This is awesome beyond words. If I stumbled across this in the wild I would flip flop between awe and disgust until my head exploded. Let me guess, "SMTP verb" is not a hypothetical example?

This is also the basis for the fourcc's used in multimedia. Checking them only requires an integer compare.

Re: Ask HN: Favorite pointer tricks in C?

#48

Instead of using a while loop to iterate through a linked list, consider using a for loop. Node * iter; for (iter=root; iter != NULL; iter=iter->next) { /* iter->object; */ } A concise implementation of strlen size_t strlen(char * str) { char * cur; for(cur=str; *cur; ++cur); return (cur-str); } Reverse a string in-place. void reverse(char * str) { char *i,*j, tmp; for (i=str, j=(str+strlen(str)-1); i

   size_t strlen(char *s)
   {
     size_t i = 0;
     while(*s++) i++;
     return i;
   }
Post reply on HN