Getting started with AVR and C

(snip, someone wrote)

(snip, then I wrote)

I haven't read the standard so recently, but I thought that was only after the default promotions. Values smaller than int would be promoted to int, then the size of the multiply (and product) determined.

If you multiply two 8 bit unsigned char values, is the product modulo 256? I don't think so.

Maybe not completely irrelevent, consider a system with a 64 bit int.

Regardless of the target size, but not of int size.

Now it gets interesting. When were the int_32_t and int_16_t added to C?

Seems to me that compilers only claiming a version of the standard before they were added wouldn't have to use the same rules.

Consider that a compiler might have a int_128_t that it could add and subtract, but not multiply or divide. Maybe it can generate a 128 bit product from two 64 bit operands. Does the standard prohibit a compiler from offering those operations?

-- glen

Reply to
glen herrmannsfeldt
Loading thread data ...

Yes, it's two-stage process.

In case it helps, here is the terminology as used by the C standard:

"integer promotions" These are the conversions that often occur prior to preforming an arithmetic operation. They form part of the:

"usual arithmetic conversions" which is how a common type is arrived at for arithmetic operations that requite it. Unless complex or floating types are involved, the integer promotions are performed on both operands and then a set of rules is used to determine the common type. For integer types it is usually simply the widest of the two, even if that is an unsigned type and the other is a signed type.

"default argument promotions" apply to function calls in the absence of a prototype. These are the integer promotions augmented by a conversion of float to double.

The standard never refers to a conversion as a cast (a cast is an operator that performs an explicit conversion) and it uses the term "promotion" only in the context of the implicit conversions described above. A conversion of one type to a wider one in some other context is not called a promotion.

No, it's not.

1999. The types are intN_t and uintN_t (no extra _) for various N. They are optional, but must be defined if the implementation has suitable types (basically 2's complement and no padding bits). Other, similar, types like int_leastN_t and int_fastN_t are required in all implementations. For example, int_least32_t is the smallest type that has at least 32 (value) bits.

True.

I don't think it could define int128_t unless it could multiply them.

--
Ben.
Reply to
Ben Bacarisse

(snip, I wrote)

For comparison purposes, I believe that Fortran does not have this rule.

If you add, subtract, multiply, or (I believe) divide 8 bit integers the result is, generally, eight bits. One should, at least, not be surprised if the result is computed modulo some small value.

I like the C rules better.

PL/I generally tries to keep the bits until it reaches the implementation maximum. That is complicated when scaled fixed point (non-integer) values are used, where it keeps the appropriate digits (binary or decimal) to the right of the radix point, possibly truncating on the left.

-- glen

Reply to
glen herrmannsfeldt

On 11/28/2012 07:29 PM, Tim Wescott wrote: ...

Sort-of, but not quite. When he said "Nope", he wasn't referring to your expectation that gcc-avr was ANSI compliant. He was referring to your expectation that it would promote 16-bit integers to 32 bits. On a conforming implementation of C with 16-bit ints, promotion of integer types halts at 16 bits, and goes no further.

It was that first quote from you that I'm correcting. Not any other statement. Specifically:

--
James Kuyper
Reply to
James Kuyper

On 11/28/2012 08:19 PM, Tim Wescott wrote: ...

There is a conversion to 32-bits, but it is NOT a promotion. See

6.3.1.1p2 for a definition of the integer promotions.
--
James Kuyper
Reply to
James Kuyper

How can you possibly know? Do you read his mind? Have an uncited conversation with him? Is he your sock-puppet?

Oh Christ. READ THE CONTEXT. That statement was made in reply to a question asking about what would happen if you cast one of the operands to 32 bit! And you're replying to a post that told you that it was misleading without its context, and again taking it out of context.

Missing the context the first time is understandable -- that statement came about after two previous postings, and you do have to follow the conversation.

But I have just told you to READ THE CONTEXT. So where do you get off with repeating a statement of mine, out of context, which YOU'VE DAMNED WELL BEEN TOLD is misleading when taken out of context, then criticizing that false meaning of it?

That's shooting straight through "rude" and getting right into "dishonest".

--
Tim Wescott 
Control system and signal processing consulting 
 Click to see the full signature
Reply to
Tim Wescott

Remember the "as if" clause. In reality, if you add, subtract, multiply, or divide two uint8_ts and store the result in another uint8_t on a CPU where 8-bit arithmetic operations are faster than larger operations (or do the same with at least some of those operations for signed numbers which happen, implementation-specifically, to be implemented in twos-complement), any sane compiler *will* perform the operations at 8-bit width because the results in all cases are provably equivalent to the same operations performed with promotion.

Chris

Reply to
Christopher Head

Of course you are correct here. I should not be posting so late - or I should have drunk more coffee first, because I know this stuff (as long as my brain is functioning correctly!).

Apologies if I've added to the confusion here, and thanks for the correction.

Reply to
David Brown

As pointed out by Hans-Bernhard, you are correct here. I'm sorry for causing confusion by posting while half asleep.

Default "int" promotions are done first for each operand. They are promoted to "signed int", "unsigned int", "signed long int" or "unsigned long int" (and "long long" for newer C standards), stopping at the first type that covers the entire range. In practice, this means anything smaller than an "int" will get promoted to a "signed int".

The types were officially added with C99, but they existed in practice before that as "long int" and "short int" on most compilers (some targets don't support 16-bit types, and thus have "short int" as 32-bit and no int16_t. And the standards allow compilers with a "short" of

64-bit or more, in which case neither "int32_t" nor "int16_t" would exist - but I have never heard of such a beast).

The rules haven't changed (again, sorry for my mistaken post). Types such as "int32_t" are just typedef's for "normal" C types.

The "int128_t" here is either a typedef for an existing C type (which could include "long long int" in C99), in which case it would have to support all integral operations, or it is purely a compiler extension, in which case it is non-standard. But I believe the standards say that /if/ a type of this form "int128_t" is defined in standard headers for the compiler, then it must act as a full integral type of that size.

Reply to
David Brown

The context was

i.e. that there was one cast to 32 bits already. Therefore ANSI C says that there would be a second conversion to 32 bits of the other operand. Or at least the resulting code should behave *as if* that had happened. (I'm pretty sure I've seen an architecture with shorter*longer->longer opcodes.)

Initially I thought what Tim wrote was in error, but upon unravelling the thread, I worked out that he had gone forward from the premises correctly, and others hadn't. Without those premises - confusion ensues.

Phil

--
Regarding TSA regulations: 
How are four small bottles of liquid different from one large bottle? 
 Click to see the full signature
Reply to
Phil Carmody

(snip)

Most likely, but as they aren't in the C89 standard, unless the user typedef's them, seems to me the compiler is free to implement then in any way desired.

-- glen

Reply to
glen herrmannsfeldt

(snip, someone wrote)

Maybe, but many have N*N-->2N multiply. Some compilers figure out that if you cast one (or both) from a shorter length that they can use such a multiply on the shorter length. This especially important when the size is large enough that the hardware doesn't support it.

Many 32 bit machines have a 32*32 --> 64 multiply, and a 64 bit (long long) type. If you cast one (or both) 32 bit int to 64 bit (long long), the compiler knows to use the 32 bit multiply.

-- glen

Reply to
glen herrmannsfeldt

Since we were nit-picking anyway: not quite. As of C99 the standard explicitly foresees the possible need to have more than the usual 10 different integer types ({signed|unsigned} {char|short|int|long|long long}) in a target. That's why they included a provision for "extended integer types". These types don't have standardized names (because they can't), but their behaviour is still covered by the standard.

So the type behind int128_t need not be an "existing C type" (as in: something that was already defined before), nor is it allowed to be a pure compiler extension (which the standard would have no say over at all). If it's an extension, it has to be a standard extension, so its behaviour is ruled by the standard.

Yes.

Reply to
Hans-Bernhard Bröker

That is correct - but I would be very surprised to see a compiler that did have a type with a name like that, and did not implement it the obvious way. It might be /legal/ under C89 rules for the compiler to have a type called "int32_t" with different behaviour, but I can't imagine it actually being the case. I'm sure Tim Wescott can think of an exception, however!

Reply to
David Brown

I can read and understand English, and in particular, the specialized dialect of it which is sometimes called "standardese". I understood precisely what he was talking about. In particular, I understand what "promotion" means in the context of the C standard, and know that you used the term incorrectly, something which you still do not seem to have understood - nothing in your comments indicates any awareness that this is the issue we're both talking about.

A conforming implementation of C will promote integer values to 32 bits only if 'int' is exactly 32-bits. Do you believe that the context I've missed changed 'int' to a 32-bit type? If not, your use of "promote" to describe that conversion is incorrect, though your expectation that there would be such a conversion is accurate.

--
James Kuyper
Reply to
James Kuyper

...

Of course. I knew that context, and knew that the conclusion you describe was the correct result. However, that's not the conclusion Tim Wescott reached - the conversion you describe is part of the usual arithmetic conversions (6.3.1.8p1) but is NOT an integer promotion (6.3.1.1p2).

Those premises had nothing to do with the confusion, which is about the meaning of the word "promote" in the context of the C standard.

--
James Kuyper
Reply to
James Kuyper

That's not quite right, though I'm not exactly sure what you mean. As you say, the integer promotions are done first. That can produce either an int or an unsigned int, or it may have no effect at all if the type is already "bigger" than an int. Then one operand, but sometimes both operands, are further converted (not promoted) to get a common type. You can read the rules at

formatting link
(sec. 6.3.1.8)

but the conversion does not stop at the first type that covers the entire range (at least according to how I interpret that phrase). For example, in (unsigned)1 * (signed)-1 the signed operand is converted to the type of the unsigned one even though that type can't cover the entire range of the operand or operands.

Almost any summary of the rules is going to be wrong; if an accurate summary can be written it should go into the language standard -- it would be a great boon -- but I don't think that's possible. For example I had to put "bigger" in quotes because the rule is based on a technical term called the conversion rank of the type and not on its size. (The integer promotions have no effect on a long int even on systems where a long int is no bigger than an int).

--
Ben.
Reply to
Ben Bacarisse

These may be the usual ones, but there are 11 "standard integer types" because they include _Bool. (Well, you did say we are nit-picking!)

--
Ben.
Reply to
Ben Bacarisse

On 11/29/2012 03:37 AM, David Brown wrote: ...

Not quite. The integer conversions never change anything to any type other than 'int' or 'unsigned int'.

"If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.58) All other types are unchanged by the integer promotions." (6.3.1.1p2) The first use of "integer promotions" in that clause is italicized, which is an ISO convention indicating that the sentence containing that phrase serves as the definition of the phrase.

..

I've heard of machines with 32-bit short, but not 64-bit. Note that while int32_t and int16_t could not be provided by for such a compiler, int_least32_t and int_fast32_t (and similarly for 16) must be.

Yes they have. In C99 and later, and are standard headers, and if #included, the identifiers they define must meet certain well-specified requirements. In C90, there were no such standard headers, no guarantees on what a header file with that name would contain if you successfully #included it, and no corresponding restrictions on how user code could use those identifiers after #including those header files.

That depends upon what you mean by 'normal'. The C99 standard distinguishes between standard and extended integer types. The standard integer types have names specified by the C standard; extended types are implementation-defined, and may have other names. There are many standard typedefs that are required to have either arithmetic or integer type; but there are none that are restricted to standard integer types. Would you consider __extended_integer_type to be a "normal" C type?

...

No, supporting int128_t would not be a non-standard extension, it's just providing an optional feature of standard C. The key difference is that if an implementation chooses to support an optional feature, it must support it in precisely the manner specified by the standard for that feature; extensions give an implementation a lot more freedom. In C2011, there's a lot of optional features.

The only size-named types that a conforming implementation of must provide are [u]int_leastN_t, and [u]int_fastN_t for N = 8, 16, 32, and 64. For all other values of N, and for [u]intN_t for all values of N, the typedefs are optional. You can determine precisely which of the optional types are supported by #ifdef of the corresponding

*_MAX macro. If that macro is #defined, you can use the corresponding type in full confidence that it behaves precisely as specified by the standard.
--
James Kuyper
Reply to
James Kuyper

On 11/29/2012 09:07 AM, James Kuyper wrote: ...

I just realized that the meaning of the phrase "All other types" is not clear without the preceding part of that clause which I snipped:

int)

--
James Kuyper
Reply to
James Kuyper

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.