I have an integer log2 function in my c-libutl library (hosted on googlecode if anyone is interested)
/*
** Integer log base 2 of a 32 bits integer values.
**   llog2(0) == llog2(1) == 0
*/
unsigned short llog2(unsigned long x)
{
  long l = 0;
  x &= 0xFFFFFFFF /* just in case 'long' is more than 32bit */
  if (x==0) return 0;
  #ifndef UTL_NOASM
    #if defined(__POCC__) || defined(_MSC_VER) || defined (__WATCOMC__)
        /* Pelles C            MS Visual C++         OpenWatcom */
      __asm { mov eax, [x]
              bsr ecx, eax
              mov  l, ecx
      }
    #elif defined(__GNUC__)
      l = (unsigned short) ((sizeof(long)*8 -1) - __builtin_clzl(x));
    #else
      #define UTL_NOASM
    #endif  
  #endif
  #ifdef UTL_NOASM  /* Make a binary search.*/
    if (x & 0xFFFF0000) {l += 16; x >>= 16;} /* 11111111111111110000000000000000 */
    if (x & 0xFF00)     {l += 8;  x >>= 8 ;} /* 1111111100000000*/
    if (x & 0xF0)       {l += 4;  x >>= 4 ;} /* 11110000*/
    if (x & 0xC)        {l += 2;  x >>= 2 ;} /* 1100 */
    if (x & 2)          {l += 1;  }          /* 10 */
    return l;
  #endif
  return (unsigned short)l;
}
Then you can simply compute
 (1 << llog2(x))
to compute the greatest power of two that is less than x. Beware 0! You should handle it separately.
It uses assembler code but can also be forced to plain C code by defining the UTL_NOASM symbol.
The code has been tested at the time but it's quite some time I don't use it and I can't say if it behaves in a 64-bit environment.