1

What's the difference between 160000000UL and (unsigned long) 160000000?


PROBLEM:

I have a #define with the following:

#define SYS_CLK (160000000UL / 1000UL)

SYS_CLK is different depending on the system clock. I want to know if I can change it to:

#define SYS_CLK ((unsigned long)(RCC_MAX_FREQUENCY/*get freq from the system. It returns e.g. 160000000U*/) / 1000UL)

And RCC_MAX_FREQUENCY is defined as:

#define RCC_MAX_FREQUENCY           168000000U

Are they the same?

(I checked this, but it's not my question.)

Mohammad Kholghi
  • 533
  • 2
  • 7
  • 21
  • For most practical purposes, there is no difference. However, your revised `SYS_CLK` macro may not be a compile-time constant — it depends on whether `RCC_MAX_FREQUENCY` is a compile-time constant.' – Jonathan Leffler Aug 25 '21 at 14:53
  • @JonathanLeffler `RCC_MAX_FREQUENCY` is also a macro. – Mohammad Kholghi Aug 25 '21 at 14:58
  • 1
    But what sort of macro? Does it evaluate to an integer constant expression? It may not matter. It may be crucial. It isn't entirely clear to me what you're worried about. Why are you worried? – Jonathan Leffler Aug 25 '21 at 15:00
  • With `#define SYS_CLK (RCC_MAX_FREQUENCY / 1000UL)`, the type of the `SYS_CLK` constant depends on the type of the `RCC_MAX_FREQUENCY` constant. If that used the `ULL` suffix (or is greater than `ULONG_MAX`), then `SYS_CLK` would have type `unsigned long long` (or possibly `long long` if `RCC_MAX_FREQUENCY` has no suffix and is greater than `ULONG_MAX`). The type cast forces it to be `unsigned long`. – Ian Abbott Aug 25 '21 at 15:00
  • To me this seems as two different questions in one.... please only ask one question at the time – Support Ukraine Aug 25 '21 at 15:01
  • Mohammad Kholghi, Why do you feel the need for a cast? `#define SYS_CLK ((RCC_MAX_FREQUENCY) / 1000u)` should be sufficient. Casting to `long`, etc, is irrelevant in macro processing. – chux - Reinstate Monica Aug 25 '21 at 15:05
  • @IanAbbott I've added more codes. Please check it. – Mohammad Kholghi Aug 25 '21 at 15:12
  • @JonathanLeffler I've added the definition of `RCC_MAX_FREQUENCY` in Q. Please read it. – Mohammad Kholghi Aug 25 '21 at 15:12
  • @4386427 I didn't get you. Why 2 questions? I've asked a Q, and added more details. – Mohammad Kholghi Aug 25 '21 at 15:13
  • @chux-ReinstateMonica Because The `RCC_MAX_FREQUENCY` is 168000000U, but I need to know if casting, makes it as 168000000UL? – Mohammad Kholghi Aug 25 '21 at 15:14
  • @MohammadKholghi Depends how `RCC_MAX_FREQUENCY` is eventually used, something not shown in the question. – chux - Reinstate Monica Aug 25 '21 at 15:18
  • @MohammadKholghi Casting with `(unsigned long)` does make `(unsigned long) 160000000` in the C code (not the pre-processing). But _why_ do you need to know if the constant is some sort of `long` like `(unsigned long)`? How is the `long` part important? – chux - Reinstate Monica Aug 25 '21 at 16:43
  • @chux-ReinstateMonica I need to make it `long`, so that everybody can use it. It's somehow a library, which is expected to be written in general, so other co-workers/people can just copy and paste to their own projects. (I code for STM32, so `RCC_MAX_FREQUENCY` is a global variable that I'm sure everyone who uses my library, has this variables depending on his device) – Mohammad Kholghi Aug 25 '21 at 20:07
  • 1
    @MohammadKholghi If left as `unsigned`, everybody can still use it. Still unclear why a `long` requirement. – chux - Reinstate Monica Aug 25 '21 at 21:22
  • @chux-ReinstateMonica You're right. 32-bits is enough for 160M. I did not think carefully. Thanks a lot! – Mohammad Kholghi Aug 26 '21 at 08:38
  • @chux-ReinstateMonica if `UL` means `unsigned long` and it's 64-bits, then how about `ULL`? I think `UL` means 32, then `ULL` is 64. Am I right? I checked this: https://stackoverflow.com/a/4380700/9691976 – Mohammad Kholghi Aug 26 '21 at 08:44
  • 1
    Mohammad Kholghi, `ULL` makes the constant some _unsigned_ type and _at least_ as wide as `unsigned long long`. `UL` makes the constant some _unsigned_ type and _at least_ as wide as `unsigned long`. `unsigned long` are **at least** 32- bit. `unsigned long` could be 32-bit, 64-bit or in esoteric implementations 36- bit , etc. – chux - Reinstate Monica Aug 26 '21 at 12:31

1 Answers1

1

What's the difference between 160000000UL and (unsigned long) 160000000?

160000000UL is unsigned at pre-processing time, (unsigned long) 160000000 is signed.

When constants are used in a macro at pre-processing time (e.g. #if math), the width (int, long, long long) and cast are irrelevant as the width used is (u)intmax_t. The sign-ness is relevant.


In general, do not force wider constant width with L or LL unless needed. Do use U when sign-ness is needed.

Casting to (unsigned long) or using L can force the constant to be at least 64-bit, when a value about 160,000,000 only needs 32-bit. Using an excessive wide type incurs down-convert warnings. IMO, coders too often ignore/disable such warnings as they are deemed noisy - when in fact they are useful.

Below is OK:

#define SYS_CLK ((unsigned long)(RCC_MAX_FREQUENCY) / 1000UL)

Yet I would recommend:

#define SYS_CLK (RCC_MAX_FREQUENCY / 1000u)
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256