La función TIENE LA INTENCIÓN de devolver el número de bits en la representación de n. Lo que se pierde en las otras respuestas es que la función invoca un comportamiento indefinido para los argumentos n < 0. Esto se debe a que la función quita el número un bit cada vez, comenzando desde el bit más bajo hasta el más alto. Para un número negativo, esto significa que el último valor de n antes de que termine el bucle (para enteros de 32 bits en 2-complemento) es 0x8000000. Este número es INT_MIN y ahora se utiliza en el bucle por última vez:
n = n&(n-1)
Desafortunadamente, INT_MIN-1 es un desbordamiento y desbordamientos de invocar un comportamiento indefinido. No se requiere una implementación conforme para "abarcar" enteros, por ejemplo, puede emitir una trampa de desbordamiento o dejar todo tipo de resultados extraños.
Lo que demuestra que 'f' es un nombre terrible para esta función. –
Un comentario o dos no habría dolido, tampoco. –
El código se ve mal, pero después de 30 segundos parece bastante elegante. Y eficiente. Un buen ejemplo de "¿por qué los programadores C no ponen más intenciones en sus identificadores? Porque les encanta ser lo suficientemente crípticos para parecer poderosos cuando no lo son". – TheBlastOne