0

I'm programming in Standard C on several microcontrollers now for about 30 years.

Now I have a question:

I have somewhere a variable with type long. The value of this variable does never extend +-0x7fff.
Choosing "long" has other benefits. Because it's a 32 bit machine, arithmetic with 32 bit is faster than 16 or 8 bit (no sign extension needed, this speeds up my fast control algorithm up to 10%...).

On the other hand I have a legacy function, that requires this variable as short. At the moment I'm copying this variable somewhere from "long" into a "short" working variable. To speed my code further up, I want to get rid of this useless copy. As modern CPUs are quite good with pointer operations, I like to access the long variable with a local pointer

short * p;

During initialization of the module

p = (short *) pointer_to_long_variable

so that I can access this variable simply with

do_some_calculations with *p 

I think this idea should work on my low-endian machine, but is this save even on machines with big-endianess?

Sorry for my bad English, I'm not a native speaker :)

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
8051fan
  • 1
  • 1
  • will work on little endian only, you are getting the leftmost 16 bits – pm100 Jan 16 '23 at 01:36
  • 2
    In general, it's not safe on any machine. See [**What is the strict aliasing rule?**](https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule) It's liable to only "work" until it blows up on you. – Andrew Henle Jan 16 '23 at 01:37
  • any reasonable compiler will surely make `(short)(mylong&0xffff)` fast. Or even `short s = (short)mylong;` – pm100 Jan 16 '23 at 01:43
  • @pm100 even without the implicit cast – 0___________ Jan 16 '23 at 02:19
  • Since you're claiming C expertise, I presume that there's something you're not telling us about your situation. Because nothing in the question makes a plausible case for any kind of intermediate variable or dangerous pointer tricks in the first place. Perhaps a useful clarification would be what you mean by the legacy function "requires" the variable as a `short`? What is the signature of that function? – John Bollinger Jan 16 '23 at 03:43
  • @8051fan "this speeds up my fast control algorithm up to 10%..." --> post that code rather than only describe it. – chux - Reinstate Monica Jan 16 '23 at 03:52
  • Always use `stdint.h` in embedded systems. Never use signed variables in embedded systems unless you actually need signed types. Never cast pointers to another pointer type unless you know exactly what you are doing - there's plenty of pitfalls. – Lundin Jan 16 '23 at 07:36
  • Among the wonders to be seen in `stdint.h` is the `uint_fast16_t` which might actually be what you are looking for (?). As in "in need this to be at least 16 bits but if making the variable 32 bit makes the code faster, then go ahead". – Lundin Jan 16 '23 at 07:40
  • `p = (short *) pointer_to_long_variable;` This is undefined behavior a.k.a. nasal demons. – user16217248 Jan 17 '23 at 05:45

1 Answers1

0

You do not need it at all. As a general rule avoid pointer punning at any price. If you need to convert (on byte level) from type a to b then use unions or memcpy (do not worry - memcpy will not be called as it is well known to the compiler)

short legacy(short y)
{
    return y+1;
}

long bar(long x)
{
    return legacy(x);
}

0___________
  • 60,014
  • 4
  • 34
  • 74