Making large constants in C source more readable?

后端 未结 8 839
遇见更好的自我
遇见更好的自我 2020-12-19 06:34

I\'m working on some code for a microprocessor.
It has a few large, critical constants.

#define F_CPU 16000000UL

In this case, this is the C

相关标签:
8条回答
  • 2020-12-19 06:59

    Another aproach would be using the ## preprocessor operator in a more generic macro

    #define NUM_GROUPED_4ARGS(a,b,c,d) (##a##b##c##d)
    #define NUM_GROUPED_3ARGS(a,b,c)   (##a##b##c)
    
    #define F_CPU NUM_GROUPED_3ARGS(16,000,000UL)
    
    int num = NUM_GROUPED_4ARGS(-2,123,456,789); //int num = (-2123456789);
    int fcpu = F_CPU; //int fcpu = (16000000UL);
    

    This is somehow WYSIWYG but not immune against misuse. E. g. you might wnat the compiler to complain about

    int num = NUM_GROUPED_4ARGS(-2,/123,456,789);  //int num = (-2/123456789); 
    

    but it will not.

    0 讨论(0)
  • 2020-12-19 07:01

    One possibility is to write it like that:

    #define F_CPU (16 * 1000 * 1000)
    

    alternatively

    #define MHz (1000*1000)
    #define F_CPU (16 * MHz)
    

    Edit: The MHz(x) others suggested might be nicer

    0 讨论(0)
  • 2020-12-19 07:05
    // constants.h
    #define Hz   1u              // 16 bits
    #define kHz  (1000u  *  Hz)  // 16 bits
    #define MHz  (1000ul * kHz)  // 32 bits
    
    // somecode.h
    #define F_CPU (16ul * MHz)   // 32 bits
    

    Notes:

    • int is 16 bits on a 8 bit MCU.
    • 16 bit literals will get optimized down to 8 bit ones (with 8 bit instructions), whenever possible.
    • Signed integer literals are dangerous, particularly if mixed with bitwise operators, as common in embedded systems. Make everything unsigned by default.
    • Consider using a variable notation or comments that indicate that a constant is 32 bits, since 32 bit variables are very very slow on most 8-bitters.
    0 讨论(0)
  • 2020-12-19 07:12

    Yes, C does have preprocessor separators: ##

    So you can write

    #define F_CPU 16##000##000UL

    which has exactly the same meaning as 16000000UL. (Unlike other structures like 16*1000*1000 where you need to be careful not to put them in places where the multiplication can cause problems.)

    0 讨论(0)
  • 2020-12-19 07:15

    maybe something like that?

    #define MHz(x) (1000000 * (x))
    ...
    #define F_CPU MHz(16)
    

    Also, I don't like #defines. Usually it's better to have enums or constants:

    static const long MHz = 1000*1000;
    static const long F_CPU = 16 * MHz;
    
    0 讨论(0)
  • 2020-12-19 07:18

    It might help readability to define the constant as:

    #define F_CPU_HZ 16000000UL
    

    That way you know what type of data is in it. In our SW we have a few peripherals which require assorted prescalers to be set, so we have a #defines like this:

    #define SYS_CLK_MHZ    (48)
    #define SYS_CLK_KHZ    (SYS_CLK_MHZ * 1000)
    #define SYS_CLK_HZ     (SYS_CLK_KHZ * 1000)
    
    0 讨论(0)
提交回复
热议问题