2

I am trying to get rid of violation of Rule 20.5

Sample code:

#define VAL 2
int32_t func(void)
 {
    int32_t n1 = VAL;
    #undef VAL
    #define VAL(x) (x*x)
    return VAL(n1);
 }

Is there any work around for undef here without changing any other lines ?

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
Amardeep
  • 89
  • 3
  • 8
  • Why do you need to use `#undef`? As in, why do you need to change the definition of a macro? – Oliver Charlesworth Dec 12 '17 at 10:06
  • No, you'll need to change other lines to avoid redefining VAL. – Ian Abbott Dec 12 '17 at 10:08
  • 2
    POW2 would be a more appropriate name for the second form of VAL. The 'workaround' would be to give a good reason why that is needed. but nothing obvious comes to mind. + redefining the macro in the function is a bit weird – Nicolae Natea Dec 12 '17 at 10:10
  • 2
    note that `#define VAL(x) (x*x)` is a very bad way to [define a square function](https://stackoverflow.com/q/10820340/995714) – phuclv Dec 12 '17 at 10:26
  • 1
    Is this real example or you ask hypothetically? What is the problem to scan for `#undef` or definition name and modify? If it is used 100-200 times, it is better to start the project from zero. It is far away from MISRA. – i486 Dec 12 '17 at 10:34

1 Answers1

6

No, there is no work-around. The code is badly written, there is no justification for using the pre-processor like this. It is just obfuscation - get rid of it. Use plain variables instead.

There exists almost no scenario where the use of #undef is justified. The only valid case I can think of is "X macros", and even those should be used sparsely.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • The typical use of `#undef` section is in repeatedtly used include files which does not include the header guard. These include files are meant e.g. for opening and closing of memory sections or other pragma handling. When header include opens a new section, an error macro is defined (e.g. `SECTION_ERROR`). The "error macro" is undefined when the header is included second times to close an opened section. If the "error macro" is detected when a new section should be opened, the `#error` is returned by preprocessor. – karelok Jan 16 '18 at 06:58
  • @karelok What you describe sounds like obfuscation. All headers should have header guards. Headers should not be used for opening memory sections, pragmas doing such things should be in local files. Generally, there is no correspondence between translation units and memory, because one translation unit may contain non-sensitive code, sensitive code such as ISRs, read-only variables, static storage variables etc etc. Therefore, the design you describe makes no sense at all to me. – Lundin Jan 16 '18 at 07:28
  • Actually it is defined by AUTOSAR standard. Please look at the example in [AUTOSAR 3.1 Memory Mapping, page 21](https://www.autosar.org/fileadmin/user_upload/standards/classic/3-1/AUTOSAR_SWS_MemoryMapping.pdf). You can see an code example at the bottom of the page - worth a thousand word. Such approach is great when your code deals with plenty of different platforms. I.e.: you as the developer know that your structure should be placed in rom, but you are not aware of memory layouts of all used platforms. The memory displacement is designed by SW integrator via MemoryMapping.h. – karelok Jan 20 '18 at 20:20
  • @karelok AUTOSAR is however by no means canonical for how to write and design C programs - rather the opposite. For example, all of those examples do collide with another automotive standards which _is_ canonical, namely MISRA-C. Which, as it turns out, bans the use of `#undef`. – Lundin Jan 22 '18 at 07:51