Page 1 of 2

Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 1:59 pm
by onlyonemac
Hi,

This is not so much a question of how to write code, but a matter of coding style. Say I have some code like the following:

Code: Select all

#define TABLE_ADDRESS (void*) 0x00030000
#define TABLE_SIZE 256

static void init_table()
{
	domain	(*table)[TABLE_SIZE];
	uint8_t	current_entry;

	table = TABLE_ADDRESS;

	current_entry = 0;
	while (current_entry < TABLE_SIZE)
	{
		((*table)[current_entry]).name = NULL;
		((*table)[current_entry]).format = 0;
		((*table)[current_entry]).size = 0;

		current_entry += 1;
	}
}
The relevant lines here are "#define TABLE_SIZE 256", "uint8_t current_entry;", and "while (current_entry < TABLE_SIZE)". As you can see, the loop will never end because current_entry will keep wrapping round from 0 to 255 and never reach 256.

So how should I make it so that I can count 256 values in a uint8_t? Using a uint16_t seems a bit wasteful here, but in reality I have to limit the table size to only 255 values. It really seems like I should be able to initialise an array of 256 values using a uint8_t for the counter, but I may be wrong. Am I missing something here, or do I really need to either reduce the table to 255 values or switch to a uint16_t for the counter? If so, which of the latter two would be more acceptable (considering that the size of the table is kind of flexible)?

Thanks,

onlyonemac

Re: Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 2:04 pm
by cmpsb
If you insist on using uint8_t, how about

Code: Select all

   uint8_t current_entry = 0;
   do
   {
      ...

      current_entry += 1;
   } while (current_entry > 0);
?

Re: Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 3:24 pm
by gerryg400
onlyonemac wrote:Using a uint16_t seems a bit wasteful here,
You should use an int or a size_t and allow the compiler to decide the best way. There isn't any waste since current_entry is a stack variable and will be aligned as the compiler sees fit anyway.

Re: Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 3:25 pm
by bluemoon
onlyonemac wrote:So how should I make it so that I can count 256 values in a uint8_t? Using a uint16_t seems a bit wasteful here
No. The array index will likely to be promoted to native address size anyway.
I suggest to use native integer or size_t to give you flexibility to change the table size.

Re: Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 3:40 pm
by iansjack
Am I missing something here?

Why not use a "for" loop? (It may be no more efficient, but it is a clearer style of coding IMO.)

Edit: I should add, use a uint_16. If your C-compiler is at all recent you can declare the variable within the loop ( "for (uint_16 i = ... )" ) so it will only use the extra byte of storage whilst the loop is executing. Hardly a big deal. In any case the lifetime of the variable is likely to be fairly short so you are worrying about nothing when you say it is wasteful.

Re: Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 3:46 pm
by onlyonemac
cmpsb wrote:If you insist on using uint8_t, how about

Code: Select all

   uint8_t current_entry = 0;
   do
   {
      ...

      current_entry += 1;
   } while (current_entry > 0);
?
Sounds interesting, if not a little hackish, although I'm not familiar with using do ... while loops in C so I am more likely to get "off-by-one" bugs if I use them in the few places where I need to iterate through this table.
bluemoon wrote:
onlyonemac wrote:So how should I make it so that I can count 256 values in a uint8_t? Using a uint16_t seems a bit wasteful here
No. The array index will likely to be promoted to native address size anyway.
I suggest to use native integer or size_t to give you flexibility to change the table size.
That seems like a good idea; I might do that, although the thing is that if I switch to a 32-bit index then I feel compelled to "max out" the array size and have 4294967296 entries lol. Such are the joys of Asperger's...

Anyway, I might just leave it at 255 for now. This table is really only used in one code module, and the size of the table doesn't honestly affect anything except the maximum number of items that can be handled by that module. 256 is more than enough; extending it at any time would require modification of that module only because of the abstraction between it and other modules.

Re: Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 3:50 pm
by kzinti
Use an int or a size_t. I prefer the former, some prefer the later.

Re: Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 3:50 pm
by onlyonemac
iansjack wrote:Why not use a "for" loop? (It may be no more efficient, but it is a clearer style of coding IMO.)
That would not change anything, as the loop condition is still evaluated before execution of the loop body. The only solution that I can see that works with a uint8_t is the one suggested by cmpsb.

Re: Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 3:53 pm
by kzinti
Relying on the uint8_t's overflowing to 0 is non-standard / non-conforming / non-portable and will get you in trouble at some point.

Basically, underflow/overflow behaviour for integers is undefined in the C and C++ standards. The compiler can and will optimize this into an infinite loop depending on the compiler options you use.

Just use an a signed int, it's the safest thing and the most efficient as well.

Re: Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 4:00 pm
by iansjack
onlyonemac wrote:
iansjack wrote:Why not use a "for" loop? (It may be no more efficient, but it is a clearer style of coding IMO.)
That would not change anything, as the loop condition is still evaluated before execution of the loop body. The only solution that I can see that works with a uint8_t is the one suggested by cmpsb.
Yes; I clarified my post in an edit. I just think that a "for" loop is cleaner when iterating a fixed number of times.

But, in any case, as I mention in my edit, the worry about larger variables being wasteful is illusory. They are only transitory.

Re: Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 4:10 pm
by onlyonemac
Yes I get it that having a larger variable is not really wasteful of space or processing power, but it still feels "wasteful" to have a whole extra 8 (or 12) bits when only one of those bits is used on and only on the very last iteration of the loop. Using a uint8_t seems "cleaner" when I am only needing a relatively small number of items, so I will just make it 255 elements instead of 256 as it doesn't *really* make a difference.

Re: Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 4:40 pm
by iansjack
If you only need 255 elements then a uint_8 is fine. But don't make the mistake of confusing what seems to be wasteful with what actually is. You can waste a lifetime chasing illusory "improvements" to code. Using one extra byte for a few moments is not wasteful (especially when you are initializing a 256 element array of structures each consisting of several bytes).

Re: Coding style: uint8_t for 256 entries

Posted: Fri Nov 27, 2015 10:41 pm
by intx13
If you are interested in that level of constraint of resources (whether for fun, for OCD, or for some other reason), you probably want to use assembly anyway. Tell GCC to dump the assembly code for your program and look at it - you'll probably see more "unnecessary" uses of wide registers/aligned memory than your loop variable.

Re: Coding style: uint8_t for 256 entries

Posted: Sat Nov 28, 2015 12:41 am
by cmdrcoriander
onlyonemac wrote:Yes I get it that having a larger variable is not really wasteful of space or processing power, but it still feels "wasteful" to have a whole extra 8 (or 12) bits when only one of those bits is used on and only on the very last iteration of the loop. Using a uint8_t seems "cleaner" when I am only needing a relatively small number of items, so I will just make it 255 elements instead of 256 as it doesn't *really* make a difference.
If 'waste' is what you're concerned with, consider that the compiler will almost definitely be using a full word (32 or 64 bits) for that variable - it's likely to just be in a register, but even in memory, the compiler is pretty likely to make sure it's word-aligned by padding it with extra bytes. The only one being wasteful is you, by not using those bits to free yourself from trivial worries like this :D

Re: Coding style: uint8_t for 256 entries

Posted: Sat Nov 28, 2015 3:11 am
by Techel
kiznit wrote: Basically, underflow/overflow behaviour for integers is undefined in the C and C++ standards.
Over/Underflow for unsigned integers is well defined :) :
A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.