Delay Routine: Fully-portable C89 if possible

Oct 09, 2007 100 Replies

Strange you should say that --- the experts on the C standard working group clearly thought otherwise. Or why else do you think they wrote all that stuff about the exact-width integer types all being optional?

That's not actually a separate issue. A C implementor is not at liberty to provide uint32_t, but forbid qualifying it as volatile. I.e. if they want to shy away from volatile uint32_t, they can't offer uint32_t at all.

Volatile has just about nothing to do with that. You're looking for (an improved version of) sigatomic_t.

Hans-Bernhard:

#define VALUE_BITS(m) (((m)-1) /(((m)-1)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30 \ + ((m)-1)%0x3fffffffL /(((m)-1)%31+1)/31%31*5 + 4-12/(((m)-1)%31+3))

Works for all unsigned integer types.

Martin

David:

There's nothing at all wrong with extra features, so long as they don't alter the behaviour of fully-standard-compliant programs or prevent them from compiling successfully.

I do indeed write my code to a quality standard, and that standard finds nothing wrong with "unsigned". The majority of good C programmers leave out the redundant keywords unless they really wanna be explicit about what they're doing. When was the last time you saw "auto" in a C file? Or even in the real world, who writes a plus sign behind positive numbers?

Nope definitely not, you just have to be guaranteed to have a given range with the type. For example:

short unsigned : at least through 65535 long : at least -2147483647 through 2147483647

Again I contest the need for this.

The microcontroller I'm using currently has 6-Bit ports but 8-Bit registers and memory chunks... still no problem though.

Martin

Ulf:

Plain char's should be used to store characters, so their sign is irrelevant. If you want to use a byte for arithmetic, then try signed char or unsigned char.

Martin

David:

For what purposes would you want an integer type of a given size (other than an integer type of *at least* a given size)? The only difference between a 33-Bit int and a 32-Bit int is that the former will take longer to wrap around to zero upon overflow, and it will also retain an extra bit when left-shifted. You'll still have all the range you want though.

Martin

David:

With time you come to ignore the English-language meaning of the keywords. When's the last time you thought about the meaning of "static" when you wanted a private function, or a variable that stays around for the next function call.

Martin

Hans-Bernhard:

That's a very defeatist attitude... you'd be suprised what you can get done with a few macros.

Martin

I hate to tell you this, but I use it, religiously. Speeds my reading in cases where I am skimming though code and, also, the compiler will certainly complain if for some reason the line is placed outside a function, whether because a #define was used where it shouldn't have been or some cut and paste, etc. Doesn't cost me much, as I type at about 100 words a minute and I don't happen to mentally frame up code nearly as fast as I can type it. (I also use LET in BASIC, too, rather than just write the assignment itself. A habit I formed about three decades ago when writing a pretty-printer, after writing an interpreter for BASIC.)

But I also think it is fine to leave them out. What is important is to be consistent in writing your application, so that others who are reading it can learn what to expect and then expect to see what they have learned from reading your code.

Jon

When you want perform modulo-N arithmetic.

Grant Edwards grante Yow! I had a lease on an at OEDIPUS COMPLEX back in visi.com '81...

Grant:

You can be fully portable and efficient at the same time.

Unchecked, likely to contain an error or two:

#define N 32

#if VALUE_BITS(char unsigned) == N # define MODULO_ARITHMETIC_N(a,b) ((char unsigned)((a) + (b))) #elif VALUE_BITS(short unsigned) == N # define MODUL...

#else # define TWO_POW(x) (1

Hmm.. don't the low-order N bits of an unsigned always obey modulo-N arithmetic? I.e, use the "guaranteed long enough" type then mask at the point of use.

For example you could do

uint8_t index; ... index++; buffer[index] = c;

or

unsigned char index; ... index++; buffer[index&0xff] = c;

The compiler should optimize this to the same code. Also this way I can use other masks for different N.

John Devereux

Until divide or shift right.

Grant Edwards grante Yow! This is my WILLIAM at BENDIX memorial CORNER visi.com where I worship William Bendix like a GOD!!

Then why is the method you propose completely unportable?

I've informed you days ago that such a VALUE_BITS functionality doesn't exist.

I'm sure you'll be prepared to show the world how to mask modulo 2^32 arithmetic, given that pre-C99 standard C doesn't offer any way to express 2^32 as a numeric constant?

Hans-Bernhard Br=F6ker:

It's not non-portable.

Indeed you did misinform me of such. I've already posted the VALUE_BITS macro. I could fill a warehouse with the things that you don't know. Maybe you should consider the possibility that just because you don't know how to do something, that doesn't mean that someone else doesn't know how to.

Martin

Hans-Bernhard Br=F6ker:

It's easy to get only the bits you want:

(Unchecked, likely to contain an error or two)

#define BITMASK_X_BITS_SET(one_expression,x) ( \ ( \ ( \ ( \ (one_expression)

unsigned long x; ... x &= 0xffffffff;

John Devereux

The example you showed relied on interpreting types during macro processing. No compiler following the C standard has to do that. This trick is non-portable.

Before saying such things one should be very careful (apart of being not really polite): it could be just the other way around.

Rob

rob:

Wups you're right, I forgot the preprocessor can't play with type casts and so forth. Looks like we'll have to use limits.h:

#if UCHAR_MAX > ...

When I'm unsure of something, or just plain ignorant of something, I don't declare my thoughts as explicit truth -- I'll let be known that I'm not 100% sure on what I'm saying. Contrast the two:

1) There's no way of getting VALUE_BITS 2) I don't know of any way of getting VALUE_BITS, does anyone else?

Martin

There are several situations where a 33-bit integer would not suit when I want a 32-bit integer (or more realistically, reasons why I might particularly want a 16-bit integer and not a 32-bit integer). Here's a few of them:

1) RAM space - on a small micro, you don't want to waste space.

2) Speed - on a small micro, larger integers take a lot more time and code space to work with.

3) Interfaces with hardware - you want to get the sizes matching exactly.

4) Interfaces with external equipment or other programs - if you are sending data to another program, you want to be 100% sure of the data formats.

5) Bit manipulation - sometimes it's important to know the exact number of bits when doing logic operations.

6) Array efficiency - it is often more efficient to access arrays of structs if the element size is a power of two for easy calculation of addresses, so it's important to know the exact size of the elements.

There are probably many more reasons, but that's enough to get started.

mvh.,

David

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required