1

I'm trying to improve my coding practice for embedded. The code below writes the value 0 to the memory location 0x80001000.

#define MemoryWrite(A,V) *(volatile unsigned long*)(A)=(V)
#define FLAG 2147487744 //0x80001000

uint32_t reset_value = 0;

int main(void)
{
    MemoryWrite(FLAG, reset_value);
    return 0;
}

I have two questions:

  1. In order to use the MemoryWrite macro I had to convert 0x80001000 to 2147487744. I think this makes the code unclear. Is there a way that I could do this just using the hex value?

  2. I defined reset_value as a uint32_t. What would it change if I used #define instead ?

10
  • 4
    Using macros like this is ugly, unnecessary and error-prone. Use an inline function and do it properly. Commented Aug 26, 2016 at 11:00
  • 2
    Why can't you use the hex representation? Commented Aug 26, 2016 at 11:00
  • 4
    "In order to use the MemoryWrite macro I had to convert 0x80001000 to 2147487744" Huh? That's nonsense. The only difference is the format used in the source code file, it will make no difference in the actual binary. Commented Aug 26, 2016 at 11:00
  • 1
    What's certianly not good is the type mixing. MemoryWrite expects an unsigned long, not a uint32_t. I don't know which of the two is correct, I have no idea what your embedded system has at offset 0x80001000 Commented Aug 26, 2016 at 11:01
  • 2
    You said you had to use 2147487744 instead of 0x80001000. Why? What happened when you used 0x80001000 ? Commented Aug 26, 2016 at 11:24

2 Answers 2

5
  1. In order to use the MemoryWrite macro I had to convert 0x80001000 to 2147487744. I think this is bad practice and unclear. Is there a way that I could do this just using the hex value?
#define FLAG 0x80001000u

When the u for unsigned is not present and because you have 4 bytes on a 32bit machine, the compiler assumes that the value is signed and 0x80001000 = -2147479552

  1. I'm not sure if defining reset_value as a uint32_t is good practice. Could I do this as a #define.

You can of course write #define RESET_VALUE 0. But the usefulness is not evident in such simple code. It depends if you want to modify the value in the future or not. The compiler will certainly optimize it in the same way for this 10 lines example.

Sign up to request clarification or add additional context in comments.

4 Comments

It is not possible for 0x80001000 to have a negative value. The type will be the first type that can represent its value in the list [ int, unsigned, long, unsigned long, long long, unsigned long long ]. On a 32 bit machine with no padding bits, 0x80001000 will be either unsigned int or unsigned long.
@NisseEngström My interpretation is that for hexadecimal values you take the first type in the list in which the representation fits. "Hexadecimal constants don't have a sign or any inherent way to express a negative number" (source : stackoverflow.com/questions/4737798/…) In our case this is int or long. Please share your reference link I would be happy to read it (I did not found it myself).
The C standard, §6.4.4.1 Integer Constants (point 5). The final public draft can be downloaded for free. -- Assuming an implementation with a 32 bit integer type, the value of 0x80001000 cannot be represented by the corresponding signed integer (the value would be negated), so the type of the constant has to be the unsigned version of the same type.
@NisseEngström I may start to agree with you. After some research and seeing reference from @Lundin in question comments. Could it be explained as the hex representation could fit into unsigned int but decimal could fit into signed long int (decimal constant always in a signed type) and then causing problems during pointer casting in MemoryWrite ?
3

You can use this,

#define FLAG 0x80001000ULL
...
MemoryWrite(FLAG, 0);

12 Comments

How exactly does that answer the question at hand??? You've basically copied the code from the question into your answer.
It removes the reset_value variable.
Yes, you've also changed the text 2147487744 //0x80001000 to 0x80001000... So???
Possibly the only difference between 21474877441 and 0x80001000 is that the first is a signed value and is probably a long long int and the second is an unsigned value and is a lower type.
@AlterMann you said "21474877441 and 0x80001000 are of the same type and haves the same value". They are not of the same type and not of same size. Of course they have the same value but the first may be signed long long int while the second is unsigned long int (not same size)
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.