1

In the example below "a + b" will overflow the size of both variables. Will this temporary result be stored in a 16-bit space or the biggest needed?

Is this situation standardized across compilers? Does the system architecture matter? I'm on an 8-bit microcontroller. Short type is 16-bit.

Is res equal to 50000, 17232, or undefined?

unsigned short a = 50000;
unsigned short b = 50000;
unsigned short res = 0;

void main()
{
    res = (a + b) / 2;
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
Dragos Puri
  • 107
  • 1
  • 6
  • 1
    see e.g. https://stackoverflow.com/a/46073296/10622916 – Bodo Mar 02 '21 at 13:34
  • 2
    TL;DR: When using integer values smaller than `int` in an arithmetic operation, the values will be *promoted* to `int`. – Some programmer dude Mar 02 '21 at 13:34
  • 1
    With the above said, what is the size of `int` on your platform? There's no rule that guarantees that `int` must be larger than `short`, only that it's *at least* as large as `short`. – Some programmer dude Mar 02 '21 at 13:36
  • @Someprogrammerdude An int is 8-bit. – Dragos Puri Mar 02 '21 at 13:40
  • 1
    @DragosPuri that is not possible, `sizeof(int) >= sizeof(short)` according to the standard. – Marco Bonelli Mar 02 '21 at 13:42
  • The types in the image breaks the rules set out in the C specification. `sizeof(char) <= sizeof(short) && sizeof(short) <= sizeof(int)` must always be true. And what is the target system you use which allows one-bit integer values? – Some programmer dude Mar 02 '21 at 13:46
  • According to the table you posted, a `short` has no range. – Ian Abbott Mar 02 '21 at 13:47
  • Please don't go completely changing the question to something completely different when I have taken the time to write a detailed answer. I'll rollback changes. And for the record it won't matter if you use `uint16_t` etc or `unsigned short`. – Lundin Mar 02 '21 at 13:48
  • And indeed, the table you posted is complete trash, where did you find that? I very much doubt that even the most exotic embedded compiler would be _that_ dysfunctional. – Lundin Mar 02 '21 at 13:52
  • @MarcoBonelli According to this compiler, "int" is 8-bit and "short" is 1-bit. I tried to modify this but my edit was not accepted. – Dragos Puri Mar 02 '21 at 13:53
  • @Lundin Does the fact that an "int" is 8 bit change something in this case? Since I didn't know that the size of an int matters, I tried to write the code with "normal" data types, but the actual code is written with "int16". – Dragos Puri Mar 02 '21 at 13:54
  • @DragosPuri What compiler is it? Got any link to the manual? Sounds like something from the 1970s-1980s. – Lundin Mar 02 '21 at 13:54
  • @DragosPuri short is 1-bit? What? Are you sure you're not mixing up bits and *bytes*? – Marco Bonelli Mar 02 '21 at 13:55
  • @Lundin It's a CCS PCH compiler for PICs. https://www.ccsinfo.com/downloads/ccs_c_manual.pdf – Dragos Puri Mar 02 '21 at 13:57
  • @MarcoBonelli Yes, I'm sure. https://www.ccsinfo.com/downloads/ccs_c_manual.pdf See page 43 – Dragos Puri Mar 02 '21 at 13:58
  • @DragosPuri Well, the C standard mandates that `unsigned short` and `unsigned int` can at least contain values 65535. If this compiler doesn't follow such very basic rules, then it isn't a C compiler but non-compliant trash and shouldn't be used. You should probably switch to MPLAB or whatever if you insist on still using old PIC. – Lundin Mar 02 '21 at 14:03
  • @Lundin Unfortunately it's not up to me. I can't convince the client that we should redo years of work and go through expensive instrument testing because I don't like the compiler... But thanks for taking the time and explaining how things work on standard compilers. – Dragos Puri Mar 02 '21 at 14:07
  • Well I'm thinking that table from the manual that you linked is just confused. Try to check `sizeof` the various integer types. The compiler claims to be fully compliant when it comes to translation limits, I read the manual and also their document regarding compliance: http://www.ccsinfo.com/downloads/ansi_compliance.pdf – Lundin Mar 02 '21 at 14:08
  • And regardless, they only attempt some sort of compliance to obsolete C90 "ANSI C". All useful embedded compilers support C99 and/or C11 since ages back. I think you should probably stay clear of this compiler. – Lundin Mar 02 '21 at 14:12
  • That compiler manual is hard to believe. They really do appear to have implemented a 1-bit type, and type `short` is really equated to this 1-bit type -- although type `char` is 8 bits. They also have `int` defaulting to 8 bits. Totally nonstandard. They do allow arrays of bits, but not pointers to bits. Lord knows what the cascading repercussions of *that* choice might be. They also list `void` among the type qualifiers. Hard to know whether to take them seriously at all. Clearly a high-level assembler for dedicated, totally machine-dependent, totally nonportable code. – Steve Summit Mar 02 '21 at 14:29
  • @SteveSummit PCD is for 16-bit PICs and is more expensive. They have different compilers for different PIC families. http://www.ccsinfo.com/content.php?page=compilers See table in the middle of the page. – Dragos Puri Mar 02 '21 at 14:33
  • 1
    @DragosPuri Yup, got it. Adjusted my comment. The bottom line is that this is not a C compiler -- it's a compiler for a language similar to, but in some respects *very* different from, what most people consider to be "Standard C". You are going to have to be very careful working with (and asking questions online about) this compiler, because it has so many significant but sometimes quite subtle departures from what everyone else assumes. – Steve Summit Mar 02 '21 at 14:36
  • 1
    Although C is good at and prized for its use in embedded work, it does make the absolute assumption that type `int` is at least 16 bits. This inevitably leads to uncomfortable and perhaps extreme compromises on 8-bit microcontrollers. It sounds like this compiler has made the particularly uncomfortable compromise of going with 8-bit `int`. This may make writing 8-bit code convenient, but since it violates the Standard in such an extreme way, it pretty much means that all benefits of standardization are lost. You probably can't use the Standard to make useful predictions about *anything*. – Steve Summit Mar 02 '21 at 14:41

1 Answers1

5

Strictly speaking, unsigned types do not overflow but "wrap-around", which is well-defined behavior but perhaps unexpected. Formally see for example the C standard C17 6.2.4/9:

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.

In order to fully understand these things you need to start with Implicit type promotion rules. There are various implicit and subtle things going on in many C expressions.

In this particular case, there are unlikely any implicit conversions because unsigned short is 16 bits on any known 8-bit system, and so is int. In this case the unsigned short is merely converted to unsigned int, both are 16 bit.

Since it's an unsigned type, it is guaranteed by the C standard to wrap-around and yield the value 34464, meaning that the end result is guaranteed to become 17232 on all 8- and 16-bit systems in the real world. Had the types been signed, there would be no guarantees but undefined behavior because of overflow.


To summarize:

Will this temporary result be stored in a 16-bit space or the biggest needed?

16 bit space since only the types of the (potentially promoted) operands matter.

Is this situation standardized across compilers?

Yes, in case of unsigned types the code is 100% portable across 8- and 16 bit system. This is guaranteed by the C standard.

Does the system architecture matter?

Yes, the size of int matters in determining whether something is promoted or not. On 8- and 16 bitters, int is always de facto 16 bits (though in theory C allows it to be something else). On 32 and 64 bitters it is always de facto 32 bits.

Is res equal to 50000, 17232, or undefined?

17232 on 8- and 16 bit systems, 50000 on 32- and 64 bit systems.

Lundin
  • 195,001
  • 40
  • 254
  • 396