Author Topic: button_port[start] = 0; has no storage class...... and conflicting data types  (Read 1659 times)

0 Members and 1 Guest are viewing this topic.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
So

Code: [Select]

#define start 0
#define Bn 3
uint8_t button_port[Bn];
button_port[start] = 0;


What did I do wrong? I hate GCC, it's error messages are cryptic and every time I do a new project just like another one in the past issue crop up that never did before.
« Last Edit: October 30, 2019, 04:36:05 pm by Simon »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Oh and 0 is an invalid initializer, so is 1 and 2.
 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11876
  • Country: us
Try this:

Code: [Select]
#define SIZE 1
uint8_t button_port[SIZE];
button_port[0] = 0;
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Sorry I got myself in a muddle, the array size is declared as 3. I corrected it.
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
You're not trying to assign to the array outside a function, are you?
« Last Edit: October 30, 2019, 09:28:39 pm by andersm »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
well yea. The array has a static value setup at the beginning of the program and does not change. Should I specify it as a constant or static?
 

Online oPossum

  • Super Contributor
  • ***
  • Posts: 1415
  • Country: us
  • Very dangerous - may attack at any time
Code: [Select]
uint8_t const button_port[Bn] = { 0, 0, 0 };
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
OK, but I still don't understand why the array is failing does it need to be in the main function at least? I was trying to create a separate file that I can include in any project that handles button presses - not possible?
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
OK, but I still don't understand why the array is failing does it need to be in the main function at least?
The language rules do not allow it. If you want to initialize the contents of the array you must either do it as part of the definition, like in oPossum's post, or inside a function before it's used. But also remember that all global and static variables are initialized to zero by default.

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
Assignment operation needs to be done in a function. Any function works.

x = y; generates code - instructions. They need to be somewhere. In C, you can't have free-hanging code. If you did, when would it run? If you want to run it "at the start", main() function is for this purpose.

OTOH,
type x = y;
is a definition with initialization; it will reserve memory, and the compiler handles the code that runs before the main() to actually make it initialized. oPossum has shown how to initialize an array. For a complex initialization, you may need to do "with code", that would  be in the beginning of main(), for example. The C standard specifies that your compiler will generate code that initializes all global (and static, inside functions) variables to zero. So if you need zero initialization to all members, just do:

uint8_t button_port[Bn];

If one of the members need to be something else, it's not bad to just overwrite that one in the beginning of main().
« Last Edit: October 31, 2019, 09:08:07 am by Siwastaja »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Of course yes. I had forgotten that putting code in a *.c file is not putting it in main().
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12856
As Siwastaja just pointed out,
Code: [Select]
button_port[0] = 0;is a statement.  Statements are not allowed outside of functions, (and would be unreachable there anyway), so the compiler attempted to interpret it as a declaration or definition, saw the = and decided it was a definition with initialisation, and complained its invalid, as per the error message.

For your button input driver, if you need to do anything more complex than initialise your arrays with fixed values, you'll need an initialiser function, (which should *NOT* be in your #included header*),  to be called near the beginning of the main() function of your user program.

Its *RARE* for a single header file to be portable between projects - normally the smallest package that is, is a C source file and a header declaring its interfaces.

* see: https://www.gamedev.net/articles/programming/general-and-gameplay-programming/organizing-code-files-in-c-and-c-r1798/
« Last Edit: October 31, 2019, 09:27:31 am by Ian.M »
 

Offline Twoflower

  • Frequent Contributor
  • **
  • Posts: 737
  • Country: de
An alternative to oPossums code:
Code: [Select]
#define Bn (3)
uint8_t const button_port[Bn] = { 0 };
With this code you only need to change the define if the Bh needs to be changed.
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
An alternative to oPossums code:
Code: [Select]
#define Bn (3)
uint8_t const button_port[Bn] = { 0 };
With this code you only need to change the define if the Bh needs to be changed.

Note that this initializes button_port[0] to 0, explicitly, and the rest to 0, implicitly. So you do the same initialization, in two different ways, combined in one command. IMHO, this may be confusing.

If you really want to initialize everything to 0, just omit the initializer; the C standard initializes all global data to zero.

If you wanted to change the table initialization to, say, 1, an inexperienced programmer in hurry might try to change that 0 to 1, assuming the whole table changes in a nice generic way. But it won't - only the first item changes, the array will be 1,0,0. Hence, it's better to leave the explicit initialization out completely, forcing you to think about it if you need to change the initial value (adding a for loop in the beginning of main is a viable generic option, then).

Also, at least some compilers seem to put all explicitly initialized data to the .data section, even if initialized to zero, wasting flash storage. When implicitly initialized to zero, it goes to .bss, without flash storage required.
« Last Edit: October 31, 2019, 01:21:50 pm by Siwastaja »
 
The following users thanked this post: Twoflower

Offline Twoflower

  • Frequent Contributor
  • **
  • Posts: 737
  • Country: de
Siwastaja is right, the explanations in the Web are not pointing this out and I fell for it. It's get more clear if you do something like uint8_t const button_port[Bn] = { 2 }; and the resulting array is 2, 0, 0.

Depending on the compiler (gcc and clang seem to support this) a construct using designators to specify an area can be used:
Code: [Select]
#define Bn (3)
uint8_t const button_port[Bn] = { [0 ... Bn-1] = 2};
This will initialize the complete array to 2.

But I would not use that as this seems an extension of some compilers and is, to my understanding, not covered by the standard.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf