Author Topic: [GCC] can't make a calculation as part of variable setup  (Read 10932 times)

0 Members and 1 Guest are viewing this topic.

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
[GCC] can't make a calculation as part of variable setup
« on: August 10, 2018, 08:22:02 am »
Code: [Select]
const uint8_t ADC_resolution = 13;
uint8_t speed_0 = 0;                                         // Percentage of speed
uint16_t speed_0_ADC = (speed_0 * (2^ADC_resolution / 100)); // Pre-calculated value of ADC
uint8_t speed_1 = 50;                                        // Percentage of speed
uint16_t speed_1_ADC = (speed_1 * (2^ADC_resolution /100));  // Pre-calculated value of ADC
uint8_t speed_2 = 99;                                        // Percentage of speed
uint16_t speed_2_ADC = (speed_2 * (2^ADC_resolution / 100)); // Pre-calculated value of ADC

const uint8_t good_button_press = 50;
const uint8_t startup_state = 0;
uint8_t button_counts;
uint8_t button_state = startup_state;
uint8_t fan_speed;
uint8_t current_fan_speed_input;
uint8_t analogue_fan_channel_timer;

Any assignment that requires a calculation throws up an error: Error      initializer element is not constant.

Should I just carry out the calculation on a new line?
 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11885
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #1 on: August 10, 2018, 08:25:22 am »
Any assignment that requires a calculation throws up an error: Error      initializer element is not constant.

Should I just carry out the calculation on a new line?

No, that won't work. You need to make sure the initialization expression only contains constants and no variables.

Alternatively you can have a separate initialization method in your code that happens one time to do the initial setup.
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #2 on: August 10, 2018, 08:28:45 am »
It's the statements that setup the variables that cause the problem:

uint16_t speed_1_ADC = (speed_1 * (2^ADC_resolution /100));
uint8_t button_state = startup_state;

I am assigning the values of constants to variable, what is the problem.
 

Offline johnwa

  • Frequent Contributor
  • **
  • Posts: 255
  • Country: au
    • loopgain.net - a few of my projects
Re: [GCC] can't make a calculation as part of variable setup
« Reply #3 on: August 10, 2018, 08:30:33 am »
I think you will find that the caret ('^') operator doesn't do what you think it does...
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #4 on: August 10, 2018, 08:32:37 am »
it's not an exponent ?

is uint16_t suitable for a constant?
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13747
  • Country: gb
    • Mike's Electric Stuff
Re: [GCC] can't make a calculation as part of variable setup
« Reply #5 on: August 10, 2018, 08:33:15 am »
C treats consts like variables, and doesn't always understand that they can never change

Change the consts to #defines e.g.

const uint8_t ADC_resolution = 13;

to

#define ADC_resolution 13
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11885
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #6 on: August 10, 2018, 08:37:41 am »
It's the statements that setup the variables that cause the problem:

uint16_t speed_1_ADC = (speed_1 * (2^ADC_resolution /100));
uint8_t button_state = startup_state;

I am assigning the values of constants to variable, what is the problem.

Well, for example, speed_1 is not a constant and yet you are trying to use it in an initialization expression. That is why the compiler is objecting. Same with speed_0 and speed_2.
 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11885
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #7 on: August 10, 2018, 08:38:54 am »
C treats consts like variables, and doesn't always understand that they can never change

I don't agree with this. Constant is as constant does. Using #define won't solve the problem, and will make the code harder to debug and test later on.
 

Offline johnwa

  • Frequent Contributor
  • **
  • Posts: 255
  • Country: au
    • loopgain.net - a few of my projects
Re: [GCC] can't make a calculation as part of variable setup
« Reply #8 on: August 10, 2018, 08:41:31 am »
it's not an exponent ?

is uint16_t suitable for a constant?

'^' is bitwise exclusive OR. There is a pow() function in the standard library , which works on doubles, but if you just want an integer power of 2, the left shift operator '<<' works well (at least, for unsigned quantities.) For 2^4, say, use '1 << 4'.
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #9 on: August 10, 2018, 08:42:22 am »


Well, for example, speed_1 is not a constant and yet you are trying to use it in an initialization expression. That is why the compiler is objecting. Same with speed_0 and speed_2.

even if i make it a constant i get the same.
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #10 on: August 10, 2018, 08:43:49 am »
C treats consts like variables, and doesn't always understand that they can never change

Change the consts to #defines e.g.

const uint8_t ADC_resolution = 13;

to

#define ADC_resolution 13


i originally did that and it compiled ok but am told that it's not good practice and i can see that it can mask problems. Every time I try to follow best practice I land in more trouble.
 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11885
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #11 on: August 10, 2018, 08:44:47 am »
I think you will find that the caret ('^') operator doesn't do what you think it does...

it's not an exponent ?

No...  :(

For powers you need to use the pow() function.

(Or what johnwa said)
« Last Edit: August 10, 2018, 08:47:33 am by IanB »
 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11885
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #12 on: August 10, 2018, 08:49:53 am »
even if i make it a constant i get the same.

If you replace this:

Code: [Select]
uint16_t speed_0_ADC = (speed_0 * (2^ADC_resolution / 100));
with this:

Code: [Select]
uint16_t speed_0_ADC = (0 * (2^ADC_resolution / 100));
It still doesn't compile?
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #13 on: August 10, 2018, 08:52:15 am »
even if i make it a constant i get the same.

If you replace this:

Code: [Select]
uint16_t speed_0_ADC = (speed_0 * (2^ADC_resolution / 100));
with this:

Code: [Select]
uint16_t speed_0_ADC = (0 * (2^ADC_resolution / 100));
It still doesn't compile?

Than does, so it is complaining that a constant is not a constant!

Code: [Select]
const uint8_t speed_0 = 0;                                         // Percentage of speed
uint16_t speed_0_ADC = (speed_0 * (((1 << ADC_resolution) - 1) / 100)); // Pre-calculated value of ADC
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4034
  • Country: nz
Re: [GCC] can't make a calculation as part of variable setup
« Reply #14 on: August 10, 2018, 08:57:19 am »
This is fine with g++:

Code: [Select]
#include <inttypes.h>

const uint8_t ADC_resolution = 13;
const uint8_t speed_0 = 0;                                         // Percentage of speed
const uint16_t speed_0_ADC = (speed_0 * ((1<<ADC_resolution) / 100)); // Pre-calculated value of ADC
const uint8_t speed_1 = 50;                                        // Percentage of speed
const uint16_t speed_1_ADC = (speed_1 * ((1<<ADC_resolution) /100));  // Pre-calculated value of ADC
const uint8_t speed_2 = 99;                                        // Percentage of speed
const uint16_t speed_2_ADC = (speed_2 * ((1<<ADC_resolution) / 100)); // Pre-calculated value of ADC

const uint8_t good_button_press = 50;
const uint8_t startup_state = 0;
uint8_t button_counts;
uint8_t button_state = startup_state;
uint8_t fan_speed;
uint8_t current_fan_speed_input;
uint8_t analogue_fan_channel_timer;
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #15 on: August 10, 2018, 08:59:02 am »
right:

project_variables.h
Code: [Select]
extern const uint8_t ADC_resolution;
extern const uint8_t startup_state;
extern const uint8_t speed_0;                                // Percentage of speed
extern const uint16_t speed_0_ADC;   // Pre-calculated value of ADC
extern const uint8_t speed_1;                              // Percentage of speed
extern const uint16_t speed_1_ADC;   // Pre-calculated value of ADC
extern const uint8_t speed_2;                              // Percentage of speed
extern const uint16_t speed_2_ADC;   // Pre-calculated value of ADC

project_variables.c
Code: [Select]
const uint8_t ADC_resolution = 13;
const uint8_t speed_0 = 0;                                         // Percentage of speed
const uint16_t speed_0_ADC = (speed_0 * (((1 << ADC_resolution) - 1) / 100)); // Pre-calculated value of ADC
const uint8_t speed_1 = 50;                                        // Percentage of speed
const uint16_t speed_1_ADC = (speed_1 * (((1 << ADC_resolution) - 1) / 100));  // Pre-calculated value of ADC
const uint8_t speed_2 = 99;                                        // Percentage of speed
const uint16_t speed_2_ADC = (speed_2 * (((1 << ADC_resolution) - 1) / 100)); // Pre-calculated value of ADC


const uint8_t startup_state = 0;
uint8_t button_state = startup_state;

won't compile.
« Last Edit: August 10, 2018, 09:00:59 am by Simon »
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13747
  • Country: gb
    • Mike's Electric Stuff
Re: [GCC] can't make a calculation as part of variable setup
« Reply #16 on: August 10, 2018, 09:03:42 am »
C treats consts like variables, and doesn't always understand that they can never change

Change the consts to #defines e.g.

const uint8_t ADC_resolution = 13;

to

#define ADC_resolution 13


i originally did that and it compiled ok but am told that it's not good practice and i can see that it can mask problems. Every time I try to follow best practice I land in more trouble.

Whenever I hear people saying things are "best practice" it usually turns out they don't understand the problem or haven't given it any thought.
There is almost never a "best" way to do something, only more or less applicable to a particular situation.

Some older compilers would actually copy const variables to RAM at startup, so using const rather than #define would be actively bad compared to using #define.

What problem exactly would it mask ?
 
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 
The following users thanked this post: Siwastaja

Offline hans

  • Super Contributor
  • ***
  • Posts: 1638
  • Country: nl
Re: [GCC] can't make a calculation as part of variable setup
« Reply #17 on: August 10, 2018, 09:04:23 am »
A classical discrepency between the GCC and G++ compilers. With godbolt.org, I noticed that this code (@brucehoult) will compile in GCC8.x and up, but not on older versions. On the other hand, it works in even the oldest G++ compilers.

However.. before GCC8.x flows downstream to IDE packages, you probably have to wait half a dozen years.
And I wouldn't recommended switching over a whole project to G++ because of this. That compiler is a bit stricter and your project may not compile (properly - under optimizations) elsewhere.

I would recommended replacing the "constants" with a macro in this case.
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13747
  • Country: gb
    • Mike's Electric Stuff
Re: [GCC] can't make a calculation as part of variable setup
« Reply #18 on: August 10, 2018, 09:07:37 am »
And with constants you also have to dick about with externs (or put them in a header file).
You probably want constants like this in a header file anyway so all compile-time opitons are in the same place and not scattered throughout the code

For this situation. #define works just fine, if not better.

Just do it and get on with the job instead of worrying about what language purists think is good or bad practice.
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline janoc

  • Super Contributor
  • ***
  • Posts: 3785
  • Country: de
Re: [GCC] can't make a calculation as part of variable setup
« Reply #19 on: August 10, 2018, 09:11:38 am »
Simon, that will not work. The language specification says the following about const:

Quote
Notes

C adopted the const qualifier from C++, but unlike in C++, expressions of const-qualified type in C are not constant expressions; they may not be used as case labels or to initialize static and thread storage duration objects, enumerators, or bit field sizes. When they are used as array sizes, the resulting arrays are VLAs.

What const in C means is that you cannot modify that variable after it has been initialized (when used as an l-value). When const variable appears on the right side (r-value) of the assignment, the const is effectively ignored. That's why you cannot do what you are trying to do.

See here:
https://en.cppreference.com/w/c/language/const

BTW, calculating that value 2**ADC_resolution like that repeatedly is a bit silly - that value is a constant, why don't you precalculate that?
 
The following users thanked this post: Siwastaja, newbrain

Offline hans

  • Super Contributor
  • ***
  • Posts: 1638
  • Country: nl
Re: [GCC] can't make a calculation as part of variable setup
« Reply #20 on: August 10, 2018, 09:13:33 am »
Well , in another thread we ranted a lot about the pitfalls of macro's.. I don't like them, but in a GCC environment like this there is not better alternative.
Still points up for writing down formulas in code, rather than the calculated values. It's more flexible, and the formula itself is already documentation rather than some "magic" number.

You could write the formula in a function, but then you're not creating a const setup value. A compiler can optimize this away, though. But using a macro will probably yield the most deterministic code in terms of performance, as it needs to be fully evaluated irrelevant of optimization levels.

If you only use this value at 1 location in your program (e.g. at initialization of peripherals), you could also do the calculation inside that function. Arguably a bit nicer than littering the program with more global variables.
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #21 on: August 10, 2018, 09:16:44 am »
I am trying to initialise it but i can't even do that. I declare the const name and then it won't take the value assingned. If i make the calculated value a variable instead the error is the same.
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #22 on: August 10, 2018, 09:18:47 am »
Well , in another thread we ranted a lot about the pitfalls of macro's.. I don't like them, but in a GCC environment like this there is not better alternative.
Still points up for writing down formulas in code, rather than the calculated values. It's more flexible, and the formula itself is already documentation rather than some "magic" number.

You could write the formula in a function, but then you're not creating a const setup value. A compiler can optimize this away, though. But using a macro will probably yield the most deterministic code in terms of performance, as it needs to be fully evaluated irrelevant of optimization levels.

If you only use this value at 1 location in your program (e.g. at initialization of peripherals), you could also do the calculation inside that function. Arguably a bit nicer than littering the program with more global variables.

The code is designed so that I can use any ADC resolution I like. By changing the one number all constants will adjust as will the oversampling algorithm and anything else.
 

Offline janoc

  • Super Contributor
  • ***
  • Posts: 3785
  • Country: de
Re: [GCC] can't make a calculation as part of variable setup
« Reply #23 on: August 10, 2018, 09:20:44 am »
Also, re #define vs const:

Using #define (preprocessor macro) for constants is a bad practice because the compiler has no way to check the type of the value. #define is basically string replacement/concatenation before even the compiler sees it. So if someone #defines the constant to something unexpected or invalid, you are going to have a much harder time trying to find the problem - typical problem when changing between compilers. Relying on certain compiler behaviour (e.g. GCC) is a way to hell - when you will have to change to a non-GCC compiler for whatever reason (Visual C+++, clang, Microchip's PIC compilers, etc.) you will suffer.

In C using #define macros for constants is the idiomatic solution because of exactly the problem you are facing (const doesn't declare a "constant" only that the given block of memory cannot be changed after initialization). Newer revisions of C++ use constexpr declaration to explicitly tell the compiler that something is constant at compile time - with that your code would work just fine. C doesn't have that, unfortunately.

 
The following users thanked this post: oPossum, newbrain

Offline janoc

  • Super Contributor
  • ***
  • Posts: 3785
  • Country: de
Re: [GCC] can't make a calculation as part of variable setup
« Reply #24 on: August 10, 2018, 09:24:17 am »

The code is designed so that I can use any ADC resolution I like. By changing the one number all constants will adjust as will the oversampling algorithm and anything else.

Then calculate that value once (it is the same value for all instances where you use it) and use the calculated value multiple times. Doing this at runtime, especially on a microcontroller, is a pretty expensive operation for no reason.

But anyway, you can't write the code the way you want - you need to either switch to C++ and use constexpr (assuming your toolchain is modern enough to handle it) or you will have to precalculate these values/use macros because C doesn't allow non-constant expressions in the initializers (const foo is not a constant expression!)
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: [GCC] can't make a calculation as part of variable setup
« Reply #25 on: August 10, 2018, 09:28:44 am »
This code actually compiles if you use the C++ compiler ('g++') rather than GCC
Code: [Select]
#include <stdio.h>
const int i = 8;
const int j = 10*i;

int main(int argc, char *argv[]) {
   printf("i = %i, j = %i\n",i,j);
}

GCC gives:
Code: [Select]
a.c:3:22: error: initializer element is not constant

So why does 'C' not work? The way I think about it is....

If the compiler is expected to retrieve values from the program's memory to retrieve a value to initialise a static variable, it won't compile.

It fails because the initialization of 'j' requires the compiler to read the memory that will be allocated to hold i.

So why is this the case?

Imagine you had two code modules. The first one was just
Code: [Select]
/* define_i.c Define storage and set values for i */
const int i = 8;

And to go along with that you had a header file, to tell other modules all about 'i', but not what it's value actually is
Code: [Select]
/* define_i.h Header file */
extern const int i;

You might have legitimate reasons for doing this - you might define all your configuration variables in a file called "config.c", and have a "config.h" that allows other C programs to access the config settings.

So now the main module could be:
Code: [Select]
/* main.c */
#include <stdio.h>
#include "define_i.h"
const int j = 10*i;

int main(int argc, char *argv[]) {
   printf("i = %i, j = %i\n",i,j);
}


When the compiler attempts to processes the "main.c" program into an object file, it knows that there is going to be a constant variable called 'i' somewhere in memory ( thanks to the declaration in "define_i.h"), however the value it has is not known to the compiler at that time.

It is only when you have compiled both C programs and link them together that the value for 'i' gets defined.

So why does it work for C++?

C++ has the concept of constructors that (among other things) are used to initialise static variables. These are called before your main() function is run to handle cases like this. It is most likely also the source of undefined/random behaviors, as there is no clear order in which these get called, so most likely best avoided.
« Last Edit: August 10, 2018, 09:34:01 am by hamster_nz »
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13747
  • Country: gb
    • Mike's Electric Stuff
Re: [GCC] can't make a calculation as part of variable setup
« Reply #26 on: August 10, 2018, 09:30:46 am »
Also, re #define vs const:

Using #define (preprocessor macro) for constants is a bad practice because the compiler has no way to check the type of the value.

For numerics like this I don't see a problem, maybe even avoids some unnecessary type conversions.possibly even some run-time calculations if the compiler isn't smart enough to flatten them into a compile-time constant.

Quote
#define is basically string replacement/concatenation before even the compiler sees it. So if someone #defines the constant to something unexpected or invalid, you are going to have a much harder time trying to find the problem
Any method is going to have problems with typos etc.

Errors caused by #defines can sometimes be harder to find, though in the case of XC32 which is what I mostly use, it generally tells you where something was defined so typos etc. can usually be found easily.

I'd argue that for something that is fixed at compile time like this, #define makes more sense than const, as const is semntically treated as a variable, which the compiler may or may not be smart enough to deal with efficiently.

Just wondering if all compilers be smart enough to combine multiple floating point consts into an integer result without invoking any FP code?
e.g.
#define clock 24000000
#define divclock clock*0.25


 


« Last Edit: August 10, 2018, 09:36:58 am by mikeselectricstuff »
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #27 on: August 10, 2018, 09:32:49 am »

The code is designed so that I can use any ADC resolution I like. By changing the one number all constants will adjust as will the oversampling algorithm and anything else.

Then calculate that value once (it is the same value for all instances where you use it) and use the calculated value multiple times. Doing this at runtime, especially on a microcontroller, is a pretty expensive operation for no reason.

But anyway, you can't write the code the way you want - you need to either switch to C++ and use constexpr (assuming your toolchain is modern enough to handle it) or you will have to precalculate these values/use macros because C doesn't allow non-constant expressions in the initializers (const foo is not a constant expression!)

Yes in theory I can do the calculation once, in reality the time it takes at startup/compile is not an issue, one problem at a time.

So in simple language how do I define a constant that is based on another?
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4034
  • Country: nz
Re: [GCC] can't make a calculation as part of variable setup
« Reply #28 on: August 10, 2018, 09:34:52 am »
By the way, this works fine in C. #define isn't the only answer.

Code: [Select]
#include <inttypes.h>

enum {
    ADC_resolution = 13,
    ADC_factor = (1<<ADC_resolution) / 100,
    speed_0 = 0,                            // Percentage of speed
    speed_0_ADC = speed_0 * ADC_factor,     // Pre-calculated value of ADC
    speed_1 = 50,                           // Percentage of speed
    speed_1_ADC = speed_1 * ADC_factor,     // Pre-calculated value of ADC
    speed_2 = 99,                           // Percentage of speed
    speed_2_ADC = speed_2 * ADC_factor,     // Pre-calculated value of ADC

    good_button_press = 50,
    startup_state = 0,
};

uint8_t button_counts;
uint8_t button_state = startup_state;
uint8_t fan_speed;
uint8_t current_fan_speed_input;
uint8_t analogue_fan_channel_timer;

#include <stdio.h>

int main(){
    printf("speed_0_ADC = %d\n", speed_0_ADC);
    printf("speed_1_ADC = %d\n", speed_1_ADC);
    printf("speed_2_ADC = %d\n", speed_2_ADC);
    return 0;
}
 
The following users thanked this post: hans, andyturk, NorthGuy

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: [GCC] can't make a calculation as part of variable setup
« Reply #29 on: August 10, 2018, 09:35:51 am »
Another solution is to call a specific initialization function in main() only once right after device power-up, which would precompute the "constant" values at runtime. A more standard solution is to go with the #define way. One extreme solution is to use an external program/script generating a C header file with precomputed constant values and include this header file into the project.
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: [GCC] can't make a calculation as part of variable setup
« Reply #30 on: August 10, 2018, 09:36:09 am »
So in simple language how do I define a constant that is based on another?

Code: [Select]
#define BITS (10)
const int max_val = (1<<BITS)-1;
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #31 on: August 10, 2018, 09:37:04 am »
So if I make all of these variables does it solve the problem? RAM is not an issue.
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: [GCC] can't make a calculation as part of variable setup
« Reply #32 on: August 10, 2018, 09:43:06 am »
By the way, this works fine in C. #define isn't the only answer.

Code: [Select]
#include <inttypes.h>

enum {
    ADC_resolution = 13,
    ADC_factor = (1<<ADC_resolution) / 100,
    speed_0 = 0,                            // Percentage of speed
    speed_0_ADC = speed_0 * ADC_factor,     // Pre-calculated value of ADC
    speed_1 = 50,                           // Percentage of speed
    speed_1_ADC = speed_1 * ADC_factor,     // Pre-calculated value of ADC
    speed_2 = 99,                           // Percentage of speed
    speed_2_ADC = speed_2 * ADC_factor,     // Pre-calculated value of ADC

    good_button_press = 50,
    startup_state = 0,
};

uint8_t button_counts;
uint8_t button_state = startup_state;
uint8_t fan_speed;
uint8_t current_fan_speed_input;
uint8_t analogue_fan_channel_timer;

#include <stdio.h>

int main(){
    printf("speed_0_ADC = %d\n", speed_0_ADC);
    printf("speed_1_ADC = %d\n", speed_1_ADC);
    printf("speed_2_ADC = %d\n", speed_2_ADC);
    return 0;
}

That is nice, in an ugly way  :D, define the values in enums, then store the enums in variables... does it work for floats or doubles?

Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11885
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #33 on: August 10, 2018, 09:47:42 am »
So if I make all of these variables does it solve the problem? RAM is not an issue.

Well, sure. It's the difference between initialization and assignment.

For example, while this won't work:

Code: [Select]
int n = 3;
int m = 5 * n;

This will work:

Code: [Select]
int n, m;
n = 3;
m = 5 * n;
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #34 on: August 10, 2018, 09:51:02 am »
sounds like constants in C are still bollocks and the only true constant is a define.

So I need to split the operations up.
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: [GCC] can't make a calculation as part of variable setup
« Reply #35 on: August 10, 2018, 09:51:43 am »
This will work:

Code: [Select]
int n, m;
n = 3;
m = 5 * n;

Not for me:
Code: [Select]
$ cat main.c
#include <stdio.h>
int i;
int j;
i = 5;
j = i*10;

int main(int argc, char *argv[]) {
           printf("i = %i, j = %i\n",i,j);
}

Code: [Select]
$ gcc -o main main.c
main.c:4:1: warning: data definition has no type or storage class
 i = 5;
 ^
main.c:4:1: warning: type defaults to ‘int’ in declaration of ‘i’ [-Wimplicit-int]
main.c:5:1: warning: data definition has no type or storage class
 j = i*10;
 ^
main.c:5:1: warning: type defaults to ‘int’ in declaration of ‘j’ [-Wimplicit-int]
main.c:5:5: error: initializer element is not constant
 j = i*10;
     ^
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4034
  • Country: nz
Re: [GCC] can't make a calculation as part of variable setup
« Reply #36 on: August 10, 2018, 09:53:43 am »
That is nice, in an ugly way  :D, define the values in enums, then store the enums in variables... does it work for floats or doubles?

No floating point. Only char, short, int, long, long long and the corresponding unsigned variants.
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13747
  • Country: gb
    • Mike's Electric Stuff
Re: [GCC] can't make a calculation as part of variable setup
« Reply #37 on: August 10, 2018, 09:53:50 am »
So if I make all of these variables does it solve the problem? RAM is not an issue.

Well, sure. It's the difference between initialization and assignment.

For example, while this won't work:

Code: [Select]
int n = 3;
int m = 5 * n;

This will work:

Code: [Select]
int n, m;
n = 3;
m = 5 * n;
but would be a PITA as it would need to be declared extern in any module that needs it.
I've yet to see a convincing argument (for this situation) against #defining it all in a header file included by all modules. Just remember to bracket any expressions to avoid operator precedence issues
Also simplifies product variants where different sets of constants are used.

 
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline hans

  • Super Contributor
  • ***
  • Posts: 1638
  • Country: nl
Re: [GCC] can't make a calculation as part of variable setup
« Reply #38 on: August 10, 2018, 09:56:33 am »
By the way, this works fine in C. #define isn't the only answer.

Code: [Select]
#include <inttypes.h>

enum {
    ADC_resolution = 13,
    ADC_factor = (1<<ADC_resolution) / 100,
    speed_0 = 0,                            // Percentage of speed
    speed_0_ADC = speed_0 * ADC_factor,     // Pre-calculated value of ADC
    speed_1 = 50,                           // Percentage of speed
    speed_1_ADC = speed_1 * ADC_factor,     // Pre-calculated value of ADC
    speed_2 = 99,                           // Percentage of speed
    speed_2_ADC = speed_2 * ADC_factor,     // Pre-calculated value of ADC

    good_button_press = 50,
    startup_state = 0,
};

uint8_t button_counts;
uint8_t button_state = startup_state;
uint8_t fan_speed;
uint8_t current_fan_speed_input;
uint8_t analogue_fan_channel_timer;

#include <stdio.h>

int main(){
    printf("speed_0_ADC = %d\n", speed_0_ADC);
    printf("speed_1_ADC = %d\n", speed_1_ADC);
    printf("speed_2_ADC = %d\n", speed_2_ADC);
    return 0;
}

 :clap: :clap: :clap:

I think I've seen the EFM32 libraries being built in this way, although at most they were doing was some bit banging for registers.
But I wasn't a real fan of that style. Sure it works and the compiler does it's job, but it can be confusing.

Nonetheless, sounds like there is a lot of debate how to put in constants in a program. Nice to see all the solutions.

I think generally speaking for C with the given tool limitations, most people hardcode numbers into a program or resort to a macro.
Sure you can do better in C++, but speaking as embedded in a single entity, weare not ready for that yet.

Just wondering if all compilers be smart enough to combine multiple floating point consts into an integer result without invoking any FP code?
e.g.
#define clock 24000000
#define divclock clock*0.25


G++ 4.1.2: thinks the outcome is a double (rightly so) and complains when trying to squeeze it into an integer somewhere.
G++ 4.4.7 already does an implicit conversion back to integers..
GCC 4.1.2: does same as G++ 4.4.7
Not sure what other compilers might do, like CCS, IAR or XC8. :-//
 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11885
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #39 on: August 10, 2018, 10:01:44 am »
Not for me:

Well, true. But of course you didn't put the executable statements in a function block. Some details are left for the reader.
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #40 on: August 10, 2018, 10:14:21 am »
OK I am back to defines, but
#define speed_0_ADC ((speed_0 * (((1 << ADC_resolution) - 1) / 100))U) does not work, do I need to care about the "U" as it is always a positive value?
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13747
  • Country: gb
    • Mike's Electric Stuff
Re: [GCC] can't make a calculation as part of variable setup
« Reply #41 on: August 10, 2018, 10:17:26 am »
OK I am back to defines, but
#define speed_0_ADC ((speed_0 * (((1 << ADC_resolution) - 1) / 100))U) does not work, do I need to care about the "U" as it is always a positive value?
If you're using #define, you don't include the type, so no "U"
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #42 on: August 10, 2018, 10:19:06 am »
#define ADC_1_percent (((1 << ADC_resolution) - 1) / 100)  // raw oversampled ADC value of 1%
#define speed_0 0U                                         // Percentage of speed
#define speed_0_ADC (speed_0 * ADC_1_percent)              // Pre-calculated value of ADC
#define speed_1 50U                                        // Percentage of speed
#define speed_1_ADC (speed_1 * ADC_1_percent)              // Pre-calculated value of ADC
#define speed_2 99U                                        // Percentage of speed
#define speed_2_ADC (speed_2 * ADC_1_percent)              // Pre-calculated value of ADC
 

Online SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] can't make a calculation as part of variable setup
« Reply #43 on: August 10, 2018, 10:20:36 am »

If you're using #define, you don't include the type, so no "U"

But we always have to do: #define F_CPU 8000000UL

discreet values with "U" on the end work, the issue is putting it after the formula
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4034
  • Country: nz
Re: [GCC] can't make a calculation as part of variable setup
« Reply #44 on: August 10, 2018, 10:25:28 am »
OK I am back to defines, but
#define speed_0_ADC ((speed_0 * (((1 << ADC_resolution) - 1) / 100))U) does not work, do I need to care about the "U" as it is always a positive value?

*What* is that U doing there?  |O

You can add a "U" as part of the syntax of an integer: 123U. Just like a "." is part of the syntax of a floating point number.

"U" isn't something you can just throw in at random as some kind of type conversion operation.

There's #define speed_0_ADC ((unsigned)(speed_0 * (((1 << ADC_resolution) - 1) / 100)) for that.
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: [GCC] can't make a calculation as part of variable setup
« Reply #45 on: August 10, 2018, 10:30:23 am »
OK I am back to defines, but
#define speed_0_ADC ((speed_0 * (((1 << ADC_resolution) - 1) / 100))U) does not work, do I need to care about the "U" as it is always a positive value?

It really isn't needed in this case, but if it was important, you want to use a 'type cast':

Code: [Select]
#define ADC_RESOLUTION (12)
#define ADC_MAX  ((1 << ADC_RESOLUTION) - 1)
#define ADC_SPEED_PERCENT(x) ((uint_32)( x * ADC_MAX / 100))

const uint_32 speed_0_ADC = ADC_SPEED_PERCENT(0)
const uint_32 speed_1_ADC = ADC_SPEED_PERCENT(50)
const uint_32 speed_2_ADC = ADC_SPEED_PERCENT(99)

You also will want to be careful/mindful about overflows too.
« Last Edit: August 10, 2018, 10:34:27 am by hamster_nz »
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13747
  • Country: gb
    • Mike's Electric Stuff
Re: [GCC] can't make a calculation as part of variable setup
« Reply #46 on: August 10, 2018, 10:45:28 am »

If you're using #define, you don't include the type, so no "U"

But we always have to do: #define F_CPU 8000000UL
why? surely if a value is big enough to need a long, the compiler will figure that out in the context where the constant gets used.

Only numeric values can have the type suffixes, so if you need them, only put them after things that are numbers.
so :
#define speed_0  1000UL
#deifine ADC_resolution 13UL
#define speed_0_ADC ((speed_0 * (((1 << ADC_resolution) - 1) / 100UL)))
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: [GCC] can't make a calculation as part of variable setup
« Reply #47 on: August 10, 2018, 10:50:43 am »
But we always have to do: #define F_CPU 8000000UL
why?
Those damn 16-bit C compilers used on small micros...
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline janoc

  • Super Contributor
  • ***
  • Posts: 3785
  • Country: de
Re: [GCC] can't make a calculation as part of variable setup
« Reply #48 on: August 10, 2018, 12:03:15 pm »
Also, re #define vs const:

Using #define (preprocessor macro) for constants is a bad practice because the compiler has no way to check the type of the value.

For numerics like this I don't see a problem, maybe even avoids some unnecessary type conversions.possibly even some run-time calculations if the compiler isn't smart enough to flatten them into a compile-time constant.


Never had a problem with differently sized types on different compilers? Or signed vs unsigned? All of that gets muddied up if you use macros - the compiler will promote the literal to whatever type it needs to perform the operation - which may not be the type the programmer has intended (or assumed). If you use a const instead, the type is explicit and if the conversion would be problematic you at least get a warning about it.

Quote
#define is basically string replacement/concatenation before even the compiler sees it. So if someone #defines the constant to something unexpected or invalid, you are going to have a much harder time trying to find the problem
Any method is going to have problems with typos etc.

Errors caused by #defines can sometimes be harder to find, though in the case of XC32 which is what I mostly use, it generally tells you where something was defined so typos etc. can usually be found easily.

I wasn't referring so much to typos (those tend to be obvious) but things such as libraries (re)defining various things behind your back. Typical cases are the min/max macros, size_t, char being redefined as unsigned char, etc. That can break code in subtle ways you won't notice because the code will likely still compile. Just not behave as expected.
 
I'd argue that for something that is fixed at compile time like this, #define makes more sense than const, as const is semntically treated as a variable, which the compiler may or may not be smart enough to deal with efficiently.

That applies only for C where the compiler (or rather the language standard) is sadly too dumb and prevents many of these compile-time optimizations.

Just wondering if all compilers be smart enough to combine multiple floating point consts into an integer result without invoking any FP code?
e.g.
#define clock 24000000
#define divclock clock*0.25

If you define it like this - i.e. macros, then not. The use of divclock gets literally substituted for clock * 0.25 which is of double type. Not to mention that you should put the macro in parentheses, i.e. (clock * 0.25) otherwise you may get an unexpected surprise if it gets used in an expression with a higher priority operator than a multiplication next to it. The preprocessor works really on the text search & replace level, nothing more. I think the xc32 compiler is GCC-based, so you can see the preprocessing result by running it with the -E switch on your source file. It will stop after the preprocessing stage before compilation and you can see the results of the macro substitutions. You will see that the preprocessor does not do any arithmetics there for you.


OTOH, if you use C++11 or newer, you can do this:

constexpr int clock = 24000000;
constexpr int divclock = clock / 4;

and this will be calculated by the compiler at compile time and optimized out, basically ending as equivalent to writing:
constexpr int divclock = 6000000;

If you are wondering why did I replace the multiplication by 0.25 by division by 4 - multiplication by 0.25 will work too but it will end up promoted to double and then truncated into the int constant expression. That will likely trigger a warning about a possible data loss due to the truncation. Division by 4 is an integral division in this case, so no warning. Another way of avoiding that warning would be by using an explicit cast there.
« Last Edit: August 10, 2018, 12:11:29 pm by janoc »
 

Offline janoc

  • Super Contributor
  • ***
  • Posts: 3785
  • Country: de
Re: [GCC] can't make a calculation as part of variable setup
« Reply #49 on: August 10, 2018, 12:13:38 pm »
But we always have to do: #define F_CPU 8000000UL
why?
Those damn 16-bit C compilers used on small micros...

More like 8 bit compilers - that macro is from 8bit AVRs. The compiler itself doesn't need it but a lot of standard AVR library code relies on this macro being defined with the MCUs clock frequency because many functions need to calculate various delays and dividers.
 

Offline snarkysparky

  • Frequent Contributor
  • **
  • Posts: 414
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #50 on: August 10, 2018, 12:52:26 pm »
for the compiler not knowing the type of a #define can you do this

#define someconst  (unsigned)42 

 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: [GCC] can't make a calculation as part of variable setup
« Reply #51 on: August 10, 2018, 01:11:42 pm »
don't abuse #define  :palm: :palm: :palm: :palm:
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11631
  • Country: my
  • reassessing directives...
Re: [GCC] can't make a calculation as part of variable setup
« Reply #52 on: August 10, 2018, 01:27:27 pm »
i have a hunting knife and it has this sawtooth like on the top that always bite me in the ass, that knife is not good and its not the safe practice, kitchen knife will be better because it has no sawtooth on the top, safe. knife is at fault not me, i'm perfect and clever, dont use define because i'm too lazy to declare type safe code and i can produce whatever bug in the program, define is at fault, define creates bugs not me. i'm perfect and better than Bjarne Stroustrup, i may as well design my own language and compiler :palm:, this is neverending story, people already went to the moon, we are here debating while polishing our fat ass, because thats good.
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: [GCC] can't make a calculation as part of variable setup
« Reply #53 on: August 10, 2018, 03:03:51 pm »
i have a hunting knife and it has this sawtooth like on the top that always bite me in the ass, that knife is not good and its not the safe practice, kitchen knife will be better because it has no sawtooth on the top, safe. knife is at fault not me, i'm perfect and clever, dont use define because i'm too lazy to declare type safe code and i can produce whatever bug in the program, define is at fault, define creates bugs not me. i'm perfect and better than Bjarne Stroustrup, i may as well design my own language and compiler :palm:, this is neverending story, people already went to the moon, we are here debating while polishing our fat ass, because thats good.

 :-DD :-DD :-DD :-DD :-DD
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #54 on: August 10, 2018, 03:13:09 pm »
Off-topic opinions on C++ follow...

C++ has the concept of constructors that (among other things) are used to initialise static variables. These are called before your main() function is run to handle cases like this. It is most likely also the source of undefined/random behaviors, as there is no clear order in which these get called, so most likely best avoided.

Static constructors are always called in order for a given file. But you're right, it's difficult to predict the initialization order of static variables that appear in different files. The problem isn't constructors though... Constructors are very useful! The issue is with using static class instances. The fewer static instances you have, the better.

You can (almost) have your cake and eat it too with placement new. You can allocate memory statically for an instance of a class, but delay calling the constructor until somewhere within main(). I use a template for that:

Code: [Select]
  /**
   * @brief returns a reference to a singleton instance
   * @tparam T the type of the singleton
   *
   * This template function uses placement new to statically allocate
   * memory for a single class instance, but delay its construction
   * until the function is called for the first time.
   *
   * Subsequent calls to the<T> return the same instance. The
   * constructor for T will only be called once.
   */
  template <class T>
  T &the() {
    alignas(T) static char memory[sizeof(T)];
    static T *             instance = nullptr;

    if (instance == nullptr) instance = new (memory) T;
    return *instance;
  }

and my main() usually looks like this:

Code: [Select]
int main() {
  the<Application>().run();
  return 0;
}

 

Offline snarkysparky

  • Frequent Contributor
  • **
  • Posts: 414
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #55 on: August 10, 2018, 03:24:55 pm »
Well might the gods of "best practice" actually shine their light on the situation,  just this once, and bestow their wisdom upon the mere mortals of the planet.

 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4034
  • Country: nz
Re: [GCC] can't make a calculation as part of variable setup
« Reply #56 on: August 10, 2018, 10:20:37 pm »
Well might the gods of "best practice" actually shine their light on the situation,  just this once, and bestow their wisdom upon the mere mortals of the planet.

It seems pretty simple to me. "Best practice" is to read and understand the manual for the tool you've chosen to use, and then decide for yourself how you want to use its capabilities and features.

Flailing around entering random input into your tool and expecting it to somehow intuit what you want is not best practice.

C is one of the simplest, most transparent, and least magical programming tools there is, second only to actual assembly language and maybe such simple orthogonal languages as FORTH or Scheme. The manual tells you precisely what you can do, what you can't do, and what is undefined.

With all of those simple languages you can build anything you want -- you're not restricted to what Brendan Eich or Guido van Rossum decided you should be able to do. The downside is that you *have* to build everything you want.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #57 on: August 10, 2018, 10:40:10 pm »
Quote
precompute the "constant" values at runtime.
Quote
switch to C++
Quote
enum {
    ADC_resolution = 13,
    ADC_factor = (1<<ADC_resolution) / 100,
    :
These are pretty extreme "solutions" for conforming to a "#defines are bad practice" suggestion, for a case where I think #define would work just fine.  (Especially the "enum" one - "#define is untyped, so instead we're going to use enum, which is a poorly defined type not-very-much like the actual data"???)



Quote
[8000000L and similar]
>> Those damn 16-bit C compilers used on small micros...
More like 8 bit compilers - that macro is from 8bit AVRs.
I wish they had never ported C to that damned PDP11!(actually, you don't need the "L" on numbers like 1000000; you're more likely to need "1L")
 

Online ejeffrey

  • Super Contributor
  • ***
  • Posts: 3717
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #58 on: August 11, 2018, 03:26:18 am »
A classical discrepency between the GCC and G++ compilers. With godbolt.org, I noticed that this code (@brucehoult) will compile in GCC8.x and up, but not on older versions. On the other hand, it works in even the oldest G++ compilers.

However.. before GCC8.x flows downstream to IDE packages, you probably have to wait half a dozen years.
And I wouldn't recommended switching over a whole project to G++ because of this. That compiler is a bit stricter and your project may not compile (properly - under optimizations) elsewhere.

I would recommended replacing the "constants" with a macro in this case.

Well it isn't much a discrepancy between gcc and g++ as between C and C++.

C requires that all global variable initializers be expressions of literals.  A variable, even a "const" variable is not allowed in the initializer expression.  In principle, the language could be changed to allow "const" varaibles whose value is known, but this is not the case.  Note: you can have a "const" variable whose value is not known at compile time.  For instance, it could be "extern" (defined in a different source file), volatile (changeable by an external event), or forward declared with the value occurring later in the file.

This is one reason (of many) that despite the problems with #define macros it is most common to use #define for compile time constants, especially when you need multiple constants derived from each other.

C++ on the other hand lets you initialize global variables with almost anything you want including runtime computation.  This is handled by linker magic.  For instance, on ELF systems, every object file has a ".init" section.  Initializer code is placed in there and the linker makes sure that all code in .init sections gets called before main().

Note that this has "interesting" behavior too.  The order of initializers in different translation units is undefined, so initializing a variable from an "extern" variable is pretty much always wrong.  Furthermore, within a translation unit, the order of initialization depends on whether variables are const or not, *and* whether their initializer is a compile time constant.

 
The following users thanked this post: hans

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #59 on: August 11, 2018, 06:15:41 am »
These are pretty extreme "solutions" for conforming to a "#defines are bad practice" suggestion, for a case where I think #define would work just fine.
Another "solution" would be to quit worrying about having to compute everything at compile time. Composing a few bitmasks as the program runs isn't a big deal, and if it makes the code more readable/understandable, that's even better.

Besides, compilers are *really* smart these days, and even code that looks bulky may get collapsed into constants by a good optimizer.
 

Offline Nusa

  • Super Contributor
  • ***
  • Posts: 2416
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #60 on: August 11, 2018, 06:29:06 am »
Always remember that #defines are not constants, they're macro strings, and when you use them you're doing string replacement. Any evaluation happens at their point of use.

For example, some perfectly legal code:
Code: [Select]
#define A (2+
#define B 2+3)
#define C * 10
// Type your code here, or load an example.
int test() {
    return A B C;
/*    return (2+ 2+3) * 10;  // looks like this after macro replacement */
/*     return 70; // looks like this after compiler optimization */
}
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11631
  • Country: my
  • reassessing directives...
Re: [GCC] can't make a calculation as part of variable setup
« Reply #61 on: August 11, 2018, 08:27:54 am »
why people insist on using archaic cryptic U or L? |O that is meant for backward compatibility for languages that dont support more civilized syntax? when C already provides clearer and much more configurable type safe syntax such as:
Code: [Select]
#define my_data uint_32
#define my_const ((my_data)(3141))
otoh const <insert whatever data type> myVar will stay in memory forever and people or me and you can change the value with whatever untype unsafe syntax provided by the language. its best to think how compiler will do its job at compile time imho.

For example, some perfectly legal code:
Code: [Select]
#define A (2+
#define B 2+3)
#define C * 10
// Type your code here, or load an example.
int test() {
    return A B C;
/*    return (2+ 2+3) * 10;  // looks like this after macro replacement */
/*     return 70; // looks like this after compiler optimization */
}
its the people who code in such a way that embarked those people who complained C/C++ is cryptic garbage mess and not safe practice... i did it once (long time ago) because i need massive typing shortcut and save me alot of trouble when i tried to improve the code chunk which occured very many times, but this technique better we keep to ourself rather than advising people to do the same. its a "nasty language hack" that we can do with C/C++
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline Nusa

  • Super Contributor
  • ***
  • Posts: 2416
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #62 on: August 11, 2018, 10:12:36 am »
I wasn't trying to demonstrate good practice, I was trying to emphasize the nature of #defines. Thinking of them as constants means you're going to burn yourself again and again when you forget about operator precedence or forget necessary parentheses.

#define A 2+2
#define B (2+2)

int i = A;
int j = B;
int k = A * 10;
int l = B * 10;
// the values of i,j,k,l are 4,4,22,40. Do you understand why?
« Last Edit: August 11, 2018, 10:15:42 am by Nusa »
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: [GCC] can't make a calculation as part of variable setup
« Reply #63 on: August 11, 2018, 11:24:50 am »
C treats consts like variables, and doesn't always understand that they can never change

I don't agree with this. Constant is as constant does. Using #define won't solve the problem, and will make the code harder to debug and test later on.

yup, and it makes the code harder to debug!
 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11885
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #64 on: August 11, 2018, 11:29:46 am »
C treats consts like variables, and doesn't always understand that they can never change

I don't agree with this. Constant is as constant does. Using #define won't solve the problem, and will make the code harder to debug and test later on.

yup, and it makes the code harder to debug!

But I have learned that the C and the C++ standards are a little different in this regard, and it is important to know whether you are using C or C++ when considering what behavior to expect.

(It is IMHO a little strange that the C and C++ languages are diverging. It would seem more sensible on the face of it for C to be a subset of C++.)
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: [GCC] can't make a calculation as part of variable setup
« Reply #65 on: August 11, 2018, 12:25:12 pm »
I can't use C++ for my stuff, for a lot of reasons.

It is IMHO a little strange that the C and C++ languages are diverging. It would seem more sensible on the face of it for C to be a subset of C++

The C language is defective in a lot of features, hence it's not weird that you see the C and C++ languages to diverge  :-//
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: [GCC] can't make a calculation as part of variable setup
« Reply #66 on: August 11, 2018, 12:37:30 pm »
sounds like constants in C are still bollocks and the only true constant is a define.

So I need to split the operations up.

Sounds like you simply don't have a very good grasp of C yet.  If you define a 'const' value (const int my_const=5;), that value will exist in a memory location after the compiler has place it in the relevant memory section and the linker has allocated it an address.  Any code with visibility of this const value can read it, either via immediate addressing or via a pointer.  Since the preprocessor runs before the compiler (hence the name) you have been asking the preprocessor to use this value before it actually exists.

When you use #define with a literal value (e.g. #define MY_VALUE 5) the preprocessor creates a symbol that it can subsequently use to to replace any later instances of the symbol with that literal value.  This is not a constant value (though it can't change), it's a literal.  It won't have a unique memory address allocated for it, you can't access it via a pointer etc.
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: [GCC] can't make a calculation as part of variable setup
« Reply #67 on: August 11, 2018, 01:30:36 pm »
hence it's bad for debugging.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4034
  • Country: nz
Re: [GCC] can't make a calculation as part of variable setup
« Reply #68 on: August 11, 2018, 01:54:56 pm »
I can't use C++ for my stuff, for a lot of reasons.

What reasons?

If you can use C++ on an Arduino Uno with 2 KB of RAM (as you do) then there aren't many places you can't use it.

Using the C++ compiler doesn't force you to use any language features you don't want. You don't have to use exceptions. You don't have to use new and delete. You don't even have to use templates (though used skilfully they don't cause bloat) or classes (ditto). You can just treat C++ as a "better C".
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11631
  • Country: my
  • reassessing directives...
Re: [GCC] can't make a calculation as part of variable setup
« Reply #69 on: August 11, 2018, 02:19:30 pm »
thats why they said... go hunting or camping with kitchen knife thats much safer. otoh looking from my eye, there is a serious semantics ambiguity going on between constant the number and constant the variable (memory allocated), or constant as in mathematics, and constant as in computing science. as for me, i prefer anything that is allocated in memory as "not constant" and anything "defined" or literal as "constant". imo, "const" keyword in C/C++ is just to let the compiler know that a programmer cant change it in legitimate way. but once you cast it to void and then back to another non const pointer, then it will be changeable like flint. btw i guess some people will rely on memory monitor/view while debugging instead of common sense or mental strength of whats that define means and how its semantically translated into a program.
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: [GCC] can't make a calculation as part of variable setup
« Reply #70 on: August 11, 2018, 02:30:24 pm »
What reasons?

Not technically reasons against C++, it's more a matter of convenience, i.e. I don't have enough money to buy a C++ compiler from Cosmic, while for my professional job, I am not often allowed to use C++ in avionics. We use Ada for everything needs abstraction and high-level design. Licenses for tools like Stood/C++ and Understand C++, as well as licenses for C++ debuggers, are usually 300-500% overpriced, hence as a freelancer, it's not so convenient for me to buy them, and I only have a regular pair of licenses for C's stuff. Anyway, in the past we did something in C++ (the customer paid for licenses, as their property), e.g. a couple of firmware for  Avionics Full-Duplex Switched Ethernet (aka AFDX), but the testing and the qualifying of C++ code is usually a bloodbath  :-//
« Last Edit: August 11, 2018, 04:51:15 pm by legacy »
 

Offline snarkysparky

  • Frequent Contributor
  • **
  • Posts: 414
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #71 on: August 11, 2018, 04:20:41 pm »
I see now.   5 expert in best practices would never even succeed in writing a hello world program if they must have consensus.

99.999%  of the software the world runs on has some suboptimal practice in the source.

Experts in best practice will argue about a knats @zz until the sun burns out.

Is it the norm in industry to have some smug sob criticize your code no matter what you do.

I suspect when they craft code the concept of "good enough"  runs in their head.  But when debating or reviewing others code the criticism  comes out.

I'm frustrated by these discussions which contain megabytes of criticism but microbytes of suggestions.

 |O
 
The following users thanked this post: Siwastaja

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: [GCC] can't make a calculation as part of variable setup
« Reply #72 on: August 11, 2018, 04:47:20 pm »
I'm frustrated by these discussions which contain megabytes of criticism but microbytes of suggestions.

hence, why don't you try to pass examinations like ACM and SIGACT in computer science (university), and then find a job in avionics, where you will be forced to master such concepts by practical contexts? :popcorn:

 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11631
  • Country: my
  • reassessing directives...
Re: [GCC] can't make a calculation as part of variable setup
« Reply #73 on: August 11, 2018, 06:44:34 pm »
not applicable in eevblog junkyard... and certainly dont ask Simon to do so...
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline snarkysparky

  • Frequent Contributor
  • **
  • Posts: 414
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #74 on: August 11, 2018, 06:49:23 pm »
""hence, why don't you try to pass examinations like ACM and SIGACT in computer science (university), and then find a job in avionics, ""

who said I want to or need to.  A tiny percentage of the code written needs that level of care. If you answer for everybody to need that then your answer is incorrect.

which textbook will tell me what to do with #define and why casting a constant in there is bad.
 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11885
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #75 on: August 11, 2018, 07:12:48 pm »
hence, why don't you try to pass examinations like ACM and SIGACT in computer science (university), and then find a job in avionics, where you will be forced to master such concepts by practical contexts? :popcorn:

There are two ways a program can fail:

1. The program does not do what the programmer intended, due to faulty implementation and misunderstanding about how the programming system works;
2. The program does exactly what the programmer intended, but the programmer's intentions were wrong.

I see a lot of bugs of the second kind in my daily work. Does ADA have any tools to help prevent such bugs?
 

Offline glarsson

  • Frequent Contributor
  • **
  • Posts: 814
  • Country: se
Re: [GCC] can't make a calculation as part of variable setup
« Reply #76 on: August 11, 2018, 07:47:40 pm »
No. Ada doesn't even solve #1.
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11631
  • Country: my
  • reassessing directives...
Re: [GCC] can't make a calculation as part of variable setup
« Reply #77 on: August 11, 2018, 08:00:27 pm »
reaching page 4 for what obviously #define is a solution... and i'm sorry for the OP reluctant to it...
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13747
  • Country: gb
    • Mike's Electric Stuff
Re: [GCC] can't make a calculation as part of variable setup
« Reply #78 on: August 11, 2018, 08:39:08 pm »
sounds like constants in C are still bollocks and the only true constant is a define.

So I need to split the operations up.

Sounds like you simply don't have a very good grasp of C yet.  If you define a 'const' value (const int my_const=5;), that value will exist in a memory location after the compiler has place it in the relevant memory section and the linker has allocated it an address.
So in the OP's scenario, unless the compiler is fairly smart, it would  waste memory on the intermediate constants.
#define would achieve exactly what was required on any compiler, however smart or dumb, and be understandable by any programmer, however smart or dumb.
Seems to me like the optimum solution for the OP's situation.
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13747
  • Country: gb
    • Mike's Electric Stuff
Re: [GCC] can't make a calculation as part of variable setup
« Reply #79 on: August 11, 2018, 08:41:42 pm »
hence it's bad for debugging.
It's a constant. You know what its value is, so doesn't affect debugging.
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #80 on: August 11, 2018, 09:03:59 pm »
Just because a literal is #defined doesn't mean that it won't be allocated storage.  The ARM does not have the ability to do a MOV of a literal to a register for certain values.  You simply can't stuff a 32 bit value into a 32 bit instruction.  This will be noticeable if the literal is -1 or 0xffffffff.

I haven't checked to see how this is resolved.  The issue is discussed here:
http://www.keil.com/support/man/docs/armasm/armasm_dom1359731145835.htm

I would expect the compiler to use an LDR to grab the value out of a literal pool.  Since the value exists in the pool, it is theoretically possible to change it with a pointer to the address.  Getting the address should be difficult, I hope!

As to whether #define is evil incarnate, why not look at some production code and see if is used.  Maybe the Linux kernel.  Whatever those guys are doing is probably as close to 'normal' practices as it gets.

Here's some kernel code from an ATA driver (because that is the first file I opened):

Code: [Select]
/*
 * DaVinci DA850 AHCI SATA platform driver
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/libata.h>
#include <linux/ahci_platform.h>
#include "ahci.h"

#define DRV_NAME "ahci_da850"
#define HARDRESET_RETRIES 5

/* SATA PHY Control Register offset from AHCI base */
#define SATA_P0PHYCR_REG 0x178

#define SATA_PHY_MPY(x) ((x) << 0)
#define SATA_PHY_LOS(x) ((x) << 6)
#define SATA_PHY_RXCDR(x) ((x) << 10)
#define SATA_PHY_RXEQ(x) ((x) << 13)
#define SATA_PHY_TXSWING(x) ((x) << 19)
#define SATA_PHY_ENPLL(x) ((x) << 31)
...

No big surprise...  I would expect to see this type of thing in just about every file.

Notice the parenthesis around x in the definition.  This is critical!
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13747
  • Country: gb
    • Mike's Electric Stuff
Re: [GCC] can't make a calculation as part of variable setup
« Reply #81 on: August 11, 2018, 09:18:57 pm »
It's a constant. You know what its value is, so doesn't affect debugging.

you might don't know what the value is, in fact, there are a lot of ambiguities. #define doesn't consider the type, it's just a piece of text replaced by the pre-processor with the hope the compiler will adjust (and you end forcing casting?), thus the compiler might receive an incorrect value, and the hw-debugger has neither idea nor a clue about it, especially if it's evaluated by an expression of nexted #define's

file1.h #define a=...
file2.h #define b=a+...
file3.h #define c=b+a+...
file4.h #define d=c+b+a+...
file5.h #define e=d+c+b+a+...

one or more of them is wrong, which one? do you need printf to check? can you use printf/puts? the hw-debugger can't, of course, inspect #define, you only know what is the value of "e" if you assign it to a variable.

open some project like OpenBoot for routers like TL-703, and see how many nexted #define's  are used to define what? what is the final value if you have to look at ten header files with multiple lines activated by #if #else ?


The microchip MPLABX editor auto-colours #if blocks, which makes that kind of thing a lot easier 
Quote
it's, as usual, a mess! In fact, it took 2 months to fix a wrong #define activated by a wrong #ifdef, activated by a wrong #define with some crap and candies in the middle; in the meanwhile, a bug was happy to run on my router causing a random freeze of the NIC at the bootstrap :palm: :palm: :palm:
Like I said, more or less appropriate for a given situation... ISTR the OP is talking about a small MCU system,  not a hugely complex piece of code like a router.
At the end of the day you need to get the job done. Bonus points for readability and maintainability. More bonus points for not unnecessarily relying on clever features of particular compilers.
The OP was more concerned about listening to "best practice" from "experts" than thinking about what was appropriate for his situation. That is the lesson to be learnt here.

Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #82 on: August 11, 2018, 10:10:42 pm »
talking about a small MCU system,  not a hugely complex piece of code like a router

It's was the bootloader of the router. The complexity of a bootloader is exactly the same as the code in a small MCU system, and *the* point is focused on the abuse of the #define.

That sounds a lot like blaming the saw for the woodworker's mistake.
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11631
  • Country: my
  • reassessing directives...
Re: [GCC] can't make a calculation as part of variable setup
« Reply #83 on: August 11, 2018, 11:24:04 pm »
open some project like OpenBoot for routers like TL-703, and see how many nexted #define's  are used to define what? what is the final value if you have to look at ten header files with multiple lines activated by #if #else ?
probably you are talking about #defines that are used for portability (does Ada have this feature in mind?) reason, that the same code be used in different router brand that doesnt have this and this functionality. not the #define the OP is talking about here... anyway... the code (or the original programmer) is twice the clever as you are... not me saying that... ;)

Quote from: Brian W. Kernighan
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: [GCC] can't make a calculation as part of variable setup
« Reply #84 on: August 12, 2018, 11:37:28 am »
Just because a literal is #defined doesn't mean that it won't be allocated storage.  The ARM does not have the ability to do a MOV of a literal to a register for certain values.  You simply can't stuff a 32 bit value into a 32 bit instruction.  This will be noticeable if the literal is -1 or 0xffffffff.

True, but this is architecture and value size specific.  If you are using literals, you can't assume that it can be treated like a const.  Even if possible, attempting to do so would be horrible.

It's a constant. You know what its value is, so doesn't affect debugging.

you might don't know what the value is, in fact, there are a lot of ambiguities. #define doesn't consider the type, it's just a piece of text replaced by the pre-processor with the hope the compiler will adjust (and you end forcing casting?), thus the compiler might receive an incorrect value, and the hw-debugger has neither idea nor a clue about it, especially if it's evaluated by an expression of nexted #define's

file1.h #define a=...
file2.h #define b=a+...
file3.h #define c=b+a+...
file4.h #define d=c+b+a+...
file5.h #define e=d+c+b+a+...

one or more of them is wrong, which one? do you need printf to check? can you use printf/puts? the hw-debugger can't, of course, inspect #define, you only know what is the value of "e" if you assign it to a variable.

This is when you would configure the compiler to save the preprocessed output when debugging.
 

Offline donotdespisethesnake

  • Super Contributor
  • ***
  • Posts: 1093
  • Country: gb
  • Embedded stuff
Re: [GCC] can't make a calculation as part of variable setup
« Reply #85 on: August 12, 2018, 03:31:06 pm »
tldr;

C is a terrible programming language
Few people really understand it

Bob
"All you said is just a bunch of opinions."
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11631
  • Country: my
  • reassessing directives...
Re: [GCC] can't make a calculation as part of variable setup
« Reply #86 on: August 12, 2018, 04:49:23 pm »
tldr;
only few people read the topic and OP and then chime in relevantly...
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #87 on: August 12, 2018, 08:25:51 pm »
Just because a literal is #defined doesn't mean that it won't be allocated storage.  The ARM does not have the ability to do a MOV of a literal to a register for certain values.  You simply can't stuff a 32 bit value into a 32 bit instruction.  This will be noticeable if the literal is -1 or 0xffffffff.

True, but this is architecture and value size specific.  If you are using literals, you can't assume that it can be treated like a const.  Even if possible, attempting to do so would be horrible.

It's a constant. You know what its value is, so doesn't affect debugging.

you might don't know what the value is, in fact, there are a lot of ambiguities. #define doesn't consider the type, it's just a piece of text replaced by the pre-processor with the hope the compiler will adjust (and you end forcing casting?), thus the compiler might receive an incorrect value, and the hw-debugger has neither idea nor a clue about it, especially if it's evaluated by an expression of nexted #define's

file1.h #define a=...
file2.h #define b=a+...
file3.h #define c=b+a+...
file4.h #define d=c+b+a+...
file5.h #define e=d+c+b+a+...

one or more of them is wrong, which one? do you need printf to check? can you use printf/puts? the hw-debugger can't, of course, inspect #define, you only know what is the value of "e" if you assign it to a variable.

This is when you would configure the compiler to save the preprocessed output when debugging.

Or you wouldn't write that kind of stuff in the first place.  My C compiler won't accept the '=' sign in the #define statements and I have no idea what the ellipsis expand to.

It is possible to write poor code in any language.  It isn't the fault of the language!

There's a huge difference between using #define to do some bit of literal generation and trying to get it to expand multiple files into "War and Peace".
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: [GCC] can't make a calculation as part of variable setup
« Reply #88 on: August 13, 2018, 12:17:21 am »
yeah, whatever, I have just found another *funny* abuse of macro in a chunk of abnormal working code

this line:

Code: [Select]
#define DIV(a,b) a / b

WTF is the reason to #define it? and, worse still, why not in a safer way? :horse:

Code: [Select]
#define DIV(a,b) (a) / (b) /* safer version, well ... at least it does what is supposed to do */

2411 lines below, there is this pretty chunk of code:

Code: [Select]
   delta = DIV(x2,x1+2);

and it's of course wrong: with x2=25, and x1=3, it gives the wrong result of 10, and not 5

why? because the preprocessor expands it this way: (25 / 3) + 2  :palm: :palm: :palm: :palm:

25/(3+2) != (25/3)+2, and the following if { .. } else { .. } is completely fucked up, hence under certain conditions this is the reason for the abnormal working of the firmware I was asked to fix up.

Macros can't be debugged. When you have a macro that translates to a number or a string, the source code will have the macro name, and you can't "see" what the macro translates to. So you don't actually know what is going on. You need disassembly, and/or look at the hw-debugger.

Thus, it hasn't been immediate to realize that macro can confuse people debugging the code, and yet again, I have just messed up three hours of my time for debugging :palm: :palm: :palm:
« Last Edit: August 13, 2018, 12:27:25 am by legacy »
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11631
  • Country: my
  • reassessing directives...
Re: [GCC] can't make a calculation as part of variable setup
« Reply #89 on: August 13, 2018, 12:51:14 am »
Code: [Select]
#define DIV(a,b) a / b
WTF is the reason to #define it? and, worse still, why not in a safer way? :horse:
Code: [Select]
#define DIV(a,b) (a) / (b) /* safer version, well ... at least it does what is supposed to do */
(exam) question.... whose fault?
(a) the define
(b) the programmer
the answer is.... let me guess... a person with ACM exam passed and designed a hybrid language will answer.... (a)  |O
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline Nusa

  • Super Contributor
  • ***
  • Posts: 2416
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #90 on: August 13, 2018, 12:55:33 am »
// Finish the job of making it safer if you're going to do it at all
// You need to isolate the entire result as well as the input parameters in the macro.

// this would break your "safer" version. Modulo is same precedence as multiplication and division
delta = 100 % DIV(25,3);
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11631
  • Country: my
  • reassessing directives...
Re: [GCC] can't make a calculation as part of variable setup
« Reply #91 on: August 13, 2018, 01:31:44 am »
Then definetely (a) :-\
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: [GCC] can't make a calculation as part of variable setup
« Reply #92 on: August 13, 2018, 09:24:32 am »
Or you wouldn't write that kind of stuff in the first place.  My C compiler won't accept the '=' sign in the #define statements and I have no idea what the ellipsis expand to.

The example is nowhere near syntactically correct, but the gist of if should be clear.  The ellipsis simply means that more code could follow.

It is possible to write poor code in any language.  It isn't the fault of the language!

There's a huge difference between using #define to do some bit of literal generation and trying to get it to expand multiple files into "War and Peace".

You are preaching to the converted, deeply nested #defines can be a nightmare to understand/debug for someone else looking at the code.
 

Online tggzzz

  • Super Contributor
  • ***
  • Posts: 19497
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: [GCC] can't make a calculation as part of variable setup
« Reply #93 on: August 13, 2018, 09:47:00 am »
Ever get the feeling that modern[1] C is part of the problem rather than part of the solution?

[1] C was good technology when I first used it in 1981 :)
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12859
Re: [GCC] can't make a calculation as part of variable setup
« Reply #94 on: August 13, 2018, 10:03:05 am »
OTOH the ISO C++ standard committee didn't realise that C++ templates were actually a Turing complete language that  executes at compile time.  IMHO that's *WORSE* than the ANSI C preprocessor mess, with greater potential for inadvertent or deliberate obfuscation.
 

Online tggzzz

  • Super Contributor
  • ***
  • Posts: 19497
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: [GCC] can't make a calculation as part of variable setup
« Reply #95 on: August 13, 2018, 11:08:42 am »
OTOH the ISO C++ standard committee didn't realise that C++ templates were actually a Turing complete language that  executes at compile time.  IMHO that's *WORSE* than the ANSI C preprocessor mess, with greater potential for inadvertent or deliberate obfuscation.

Hey! That's my line! Glad to see someone is listening :)

That debacle indicates the language was out of the comprehension of the language designers, and it hasn't got better since! If mere users produce something that "works", then it is mere good fortune ;)

(We'll skate over the "difficulties" that debuggers have when there are templates and exceptions :) )
« Last Edit: August 13, 2018, 11:10:16 am by tggzzz »
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: [GCC] can't make a calculation as part of variable setup
« Reply #96 on: August 13, 2018, 01:41:21 pm »
If you take a power nailer, you can drive a nail into your foot and injury yourself. Or you can drive it into your eye and kill yourself. Does it make the power nailer less useful? or less safe? Of course not. You just don't drive nails into your body, and that's what keeps you safe.

The same thing with computer languages (also macros, and everything else). Even if you can do stupid things, you don't have to. Computer languages are tools, just as the power nailer.
 

Online tggzzz

  • Super Contributor
  • ***
  • Posts: 19497
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: [GCC] can't make a calculation as part of variable setup
« Reply #97 on: August 13, 2018, 02:07:19 pm »
If you take a power nailer, you can drive a nail into your foot and injury yourself. Or you can drive it into your eye and kill yourself. Does it make the power nailer less useful? or less safe? Of course not. You just don't drive nails into your body, and that's what keeps you safe.

The same thing with computer languages (also macros, and everything else). Even if you can do stupid things, you don't have to. Computer languages are tools, just as the power nailer.

Whoosh!


That's the sound of the key point whizzing past you, as you trot out a trite and unhelpful sound-bite.

(Unless, of course, you want to argue that it is only to be expected that the designers of power nailers refused to acknowlege that it could be used to nail yourself - until after someone demonstrated that you could nail a person. Because the C++ template designers did refuse to acknowledge their creation was Turing complete until someone rubbed their faces in it)
« Last Edit: August 13, 2018, 02:11:56 pm by tggzzz »
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: [GCC] can't make a calculation as part of variable setup
« Reply #98 on: August 13, 2018, 02:33:09 pm »
the above piece of code is the firmware of a laser-engraver, and it comes from a group of hipsters of the opensource, even if their products are closed-software.

a person with ACM exam passed

They have a cool and modern company building, with a tree-lined avenue at the entrance of the company, Mercedes business cars in front of a serious pop-art logo, and a couple of sexy girls at the reception, but I frankly doubt their "developers" have ever passed an ACM exam, since in order to pass the examination you have to understand and master the reason why abusing #define is bad.

aka, if the examinator asks you to write a piece of code for the laboratory, and you write #define div(a,b) ... well, It's for sure the best way to relist your tired ass on the examination-chair six months later  :-//


anyway, their firmware also had other defects, got all fixed, got all the money, I can finally get my vacation 8)
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11631
  • Country: my
  • reassessing directives...
Re: [GCC] can't make a calculation as part of variable setup
« Reply #99 on: August 13, 2018, 03:10:46 pm »
well if its that easy.. in fact i never have a need for #define div(a,b)... and i built few programs in VB which has no define feature let alone pointer, somewhat crippled but safer (i guess).... pascal/delphi too which i ditched long time ago. i think i can make the examiner happy :-\ otoh one thing for sure, i never come across a programming language or anybody claim that we can program at moderate complexity and it will run nicely at the first compile. if Ada is so good its should already be applauded by many serious developers around the globe and the epidemic should have infected us the "clueless" hobbiests here. isnt advancement in science should be had for free to public? why keep to Avionics? ;)
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: [GCC] can't make a calculation as part of variable setup
« Reply #100 on: August 13, 2018, 03:25:52 pm »
That's the sound of the key point whizzing past you, as you trot out a trite and unhelpful sound-bite.

(Unless, of course, you want to argue that it is only to be expected that the designers of power nailers refused to acknowlege that it could be used to nail yourself - until after someone demonstrated that you could nail a person. Because the C++ template designers did refuse to acknowledge their creation was Turing complete until someone rubbed their faces in it)
Who cares?

What difference does it make if the "C++ template designers" weren't perfect engineers. Who cares if they didn't set out to build a Turing-complete meta language, but discovered one along the way? Heck, I bet they suffered from bad breath and questionable politics too, but that doesn't affect the utility of what they created.

Sometimes useful things are discovered rather than conceived. Like Penicillin, for example, or Teflon. You know, Astroglide was an accidental discovery too.

C++ is like Astroglide for programmers and I, for one, will not be going back to life without it.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf