Question

I have a working hexdump function but it seems to be overkill for printing a single variable. So I am trying to make a macro for it. So far this works almost perfectly:

#define PRINT_FMT2(val,des,fmt) printf(#des" = "fmt": "SRC_STRN,val)
// SRC_STRN is a macro that evals to string literal containing file and line# 

#include <stdint.h>
#define PRINT_HEX(x) PRINT_FMT2((*((uint32_t*)(&(x)))),x,"%x") 
// the lack of parens around 2nd arg to PRINT_FMT2 is okay cause it gets #'d

The only issue with this is that I cannot use it with the return value of a function. I get the error lvalue required as unary '&' operand. I think this means that I can't use this method of casting ptr to uint-ptr. Is there another efficient way to do this?

Edit: I'd like to mention that what most people glossed over is that I wanted to see my value bit-preserved and converted to an unsigned int hexadecimal format. Note that you may use my macro with an l-value float and it spits out the correct big-endian representation. Most regular hex-dump routines will print out the bits as it is written in memory, which clearly is dependent on endianness. My bad for not being clear about what I meant.

Anyway, I ended up writing a set of overloaded functions which can be used with an r-value. In the end I only really just wanted to use it on 32-bit floats.

inline uint32_t tohex(float f) { 
  uint32_t* u = (uint32_t *)&f; return *u; 
}
Was it helpful?

Solution

Macros should be used sparingly because they are highly bug prone, and difficult to debug.

In this case, you won't get any performance gain from using a macro, because a short function like this is probably going to get inlined.

You will get a readability gain by using a function. There are also many language features you get from functions, such as overloading, type safety, and potential to pass it as a function pointer. You may not need them now, but you might in the future.

It will also be easier to write.

All in all, a function is a much much better choice in this case.

Plus there are already functions built into the language to do what you're trying to do, both in C++, and in C (if you need the speed).

Edit

If you really want to figure out how to make it a macro, and want to know why this doesn't work, see dappawit's answer.

OTHER TIPS

The error message is saying you cannot take the address of the return value because it is not an L-value. To take the address, you need an object that actually has an address. Such objects can appear on the left size of an assignment, hence the term L-value.

A function call cannot appear to the left of an assignment--the return value is not an L-value. This is why you get the error. In C, it makes no sense to take the address of the return value. (In C++, you can return references. In that case, you can take the address of the return value. However, other returned values have the same restrictions as in C--they are not L-values.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top