Pages: [1]   Go Down
Author Topic: pointers, functions, bit fields, reference, struct..  (Read 1164 times)
0 Members and 1 Guest are viewing this topic.
Recanati (MC)
Offline Offline
Jr. Member
**
Karma: 0
Posts: 83
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

well, as you can see from the title, I need to put together some of the most odd and obscure features of C. i have this structure containing some settings:

Code:
typedef struct
{
  unsigned int channel  : 4;
  unsigned int octave    : 4;
  unsigned int sens     : 1;
  unsigned int patch    : 7;
  unsigned int waveform : 3;
  unsigned int threshold : 9;
  unsigned int tone    : 4;
}Settings;

and i want to be able to change them using my menu-driven display and a "multipurpose function" that, called with those variables (obviously given by reference and not by value), can show and edit them, instead of writing the same code tons of time. here's a little effort (the parts between /**/ comments are the pieces of code i wansn't able to write):

Code:
void editSetting(char *str, /* don't know what to put here */)
{
  /* storing the old value */
 
  byte state = IDLE;       //variable containing the status of my keypad
  byte save = 255;          // 255=do nothing    1=save and exit    0=exit only
  lcd.setCursor(0, 1);
  lcd.print(str);              //the function also accepts and writes a string used as a description
  lcd.setCursor(9, 2);
 
  while(save != 255)
  {
    state = buttonCheck(A0)
    switch(state)
    {
      case UP:   /* increments the variable */
                 break;
                 
      case DOWN: /* decrements the variable */
                 break;
                 
      case SEL:  save = 1;
                 break;
                 
      case BACK: save = 0;
                 break;
    }
    if(state==SEL || state== BACK)
      break;
    lcd.print(/*variable*/);
  }
  if(state == SEL)
    /*just quit*/
  if(state == back)
    /*reset the variable to the old value saved before and then quit*/
}

hope i was clear, and thanks in advance for your help!
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48556
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If it was my application, the first thing that I would do is evaluate that structure.
Code:
  unsigned int channel  : 4;
You want to use half the storage that an unsigned int allocates, to hold a value. Hmmm, looks like a byte to me, and no reason to mess with bit fields.

Code:
  unsigned int octave    : 4;
Ditto.

Code:
  unsigned int tone    : 4;
Ditto.

Now the order of the fields in the structure doesn't really matter, does it? So, put all the byte values first.

Then, with the struct as defined, use sizeof() on an instance, and see what size the struct is. Then, get rid of the bit field stuff, and see what the new size is. Does the use of the bit field stuff make a significant difference in the size of the struct instances?

How many instances are there going to be?

Quote
void editSetting(char *str, /* don't know what to put here */)
And if you don't give us some idea what is supposed to go there, we don't either.

Code:
    state = buttonCheck(A0)
is missing a ;

Quote
      case UP:   /* increments the variable */
Increments what variable?

Quote
      case DOWN: /* decrements the variable */
Decrements what variable?

Quote
    lcd.print(/*variable*/);
Print what variable? You can't print a whole struct instance, if that is what you are thinking.

Quote
hope i was clear
No, sorry, you weren't.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 291
Posts: 25874
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I need to put together some of the most odd and obscure features of C.
None of these is obscure or odd, and any good C reference or tutorial will tell you all you need to know.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 65
Posts: 2111
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If it was my application, the first thing that I would do is evaluate that structure.
Code:
 unsigned int channel  : 4;
You want to use half the storage that an unsigned int allocates, to hold a value. Hmmm, looks like a byte to me, and no reason to mess with bit fields.

That is not right.

An int is 16 bits, that field only allocates 4 bits.

Integral types <-> bit fields
14 bytes        <-> 4 bytes

The bit field is clearly smaller.

Logged


Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 291
Posts: 25874
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The problem with bit-fields is that they may look like a neat way of mapping structures onto hardware registers or message formats, they're frequently not portable, because of endianness or memory alignment.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
God Member
*****
Karma: 2
Posts: 596
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I guess an enum and a switch/case could do the job.

Quote
Decrements what variable?

struct member perhaps ?
Logged

0
Offline Offline
God Member
*****
Karma: 2
Posts: 596
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

An BTW, why do you pass a string as first argument ?

Code:
void editSetting(char *str, /* don't know what to put here */)
Logged

Recanati (MC)
Offline Offline
Jr. Member
**
Karma: 0
Posts: 83
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If it was my application, the first thing that I would do is evaluate that structure.
Code:
  unsigned int channel  : 4;
You want to use half the storage that an unsigned int allocates, to hold a value. Hmmm, looks like a byte to me, and no reason to mess with bit fields.
...
Paul, i think you're confusing nibbles (4bits) with bytes (8bits). believe me, it would have been nice if I had enough memory to do not mess with bit fields. my struct=32bits=8bytes. allocating all variables as int=7variables * 2bytes (int size) = 14bytes. i will have 3 user-selettable sets of settings, so 8*3=24bytes against 14*3=42.


Quote
I need to put together some of the most odd and obscure features of C.
None of these is obscure or odd, and any good C reference or tutorial will tell you all you need to know.
i meant, they're obscure or odd to me smiley


The problem with bit-fields is that they may look like a neat way of mapping structures onto hardware registers or message formats, they're frequently not portable, because of endianness or memory alignment.
i think (even if the proper word is "hope") that memory alignment is not affected by my struct, because it is made to allocate exactly 4 bytes (as if it was a long integer)


An BTW, why do you pass a string as first argument ?
Code:
void editSetting(char *str, /* don't know what to put here */)
BTWs (and solutions as well) are welcomed! it's because i want the function to manage the display as well, so that string is what it will print. the use of this function to manage ALL the user-made parameter changes will ensure consistency among all the menu sections.
Logged

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 65
Posts: 2111
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Until you know the correct amount of bits in a byte, You need to steer clear of bitfields.

32 bits is ony 4 bytes, not 8.

You need to re-consider the alignment statement you posted.

Here is a handy paragraph

Quote
c99 - Bit Fields.
An implementation may allocate any addressable storage unit large enough to hold a bitfield.
If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit.
If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined.
The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined.
The alignment of the addressable storage unit is unspecified.

Also note that the standard says that a "bit-field shall have a type that is a qualified or unqualified
version of int, unsigned int, or signed int", so having a bit-field in a char type is non-standard.

This explicitly makes bit-fields non portable, not even slightly.

Arduino is perfect for bit fields as they work on a 1 byte address boundary. But do not use the bit field with out extensive testing.

A standard class' data members are placed in memory in the order they are listed, a bit field can be backwards and there is no way to force its MSB/LSB ordering.

However by allocating contiguous memory using a 32 bit integer
then casting to your bit field ensures the bit field is mapped to memory.
« Last Edit: February 21, 2012, 09:20:59 pm by pYro_65 » Logged


Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48556
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Paul, i think you're confusing nibbles (4bits) with bytes (8bits).
Yes, I got the size wrong. Pre-coffee answers are not always the best.
Logged

Recanati (MC)
Offline Offline
Jr. Member
**
Karma: 0
Posts: 83
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Until you know the correct amount of bits in a byte, You need to steer clear of bitfields.

32 bits is ony 4 bytes, not 8.

You need to re-consider the alignment statement you posted.


never said neither that 32 bits equals 8 bytes nor that my sketch has to be portable, since every arduino uses 1-byte adresses, doesn't it?

however, i forgot to explain that the main goal by now it to get the function to work passing any of the setting variable (or any othere, already said that i will use this function very often in this project) by reference.
Logged

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 65
Posts: 2111
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
my struct=32bits=8bytes

Is this not saying 32bits  = 8 bytes, which is wrong.

Bitfield members are non-addressable. You cannot pass a member by reference. you will get 'Unable to bind" errors. You will have to pass the entire structure by reference then access the member directly.
Logged


Recanati (MC)
Offline Offline
Jr. Member
**
Karma: 0
Posts: 83
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
my struct=32bits=8bytes

Is this not saying 32bits  = 8 bytes, which is wrong.

Bitfield members are non-addressable. You cannot pass a member by reference. you will get 'Unable to bind" errors. You will have to pass the entire structure by reference then access the member directly.

oh, you're right, it was just silly mistake. however, with the right calculations we'll have 12bytes against 42, that is even a wider ratio to justify an eventual adoption of bit fields.
Logged

Austin, TX
Offline Offline
Full Member
***
Karma: 0
Posts: 134
I make my own electricity.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This explicitly makes bit-fields non portable, not even slightly.

If bit fields were portable, they wouldn't be useful.  It's precisely because they aren't portable -- meaning, don't have an abstract machine defined behavior -- that they are so useful.
Logged

Pages: [1]   Go Up
Jump to: