0
int main(){
 char a = 5 + (16711935 * 1200);
 return 0;
}

Based on the type of integer literals and conversion rules in C, 16711935 is of type int and 1200 is promoted to an int. My question is what is the type of the intermediate result of this multiplcation before it gets added to 5 and then converted to a char?

Does the intermediate result also follow the integer literal rules?

Edit: This question is not specific to multiplication, it is just an example.

Daniel Walker
  • 6,380
  • 5
  • 22
  • 45
Dan
  • 2,694
  • 1
  • 6
  • 19
  • Note C does not call 16711935 an _integer literal_, but an _integer constant_. C has 2 literals: _string_ and _compound_. `(int){16711935}` is an _compound literal_ of type `int`. – chux - Reinstate Monica Jul 30 '22 at 03:12

1 Answers1

3

The conversion rules apply to all operations involving integer types, whether the operands are integer constants or objects of integer type.

In the case of this expression, the integer constants 5, 16711935, and 1200 all have type int (assuming an int is 32 bits wide), so there is no conversion applied to the operands of the + and = operators. The resulting expression has type int and is converted to char before being assigned to a.

The types applied to integer constants are specified on this page, which originates from section 6.4.4.1 of the C standard.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • what if the intermediate result is bigger than an int? say 16711935 * 16711935 – Dan Jul 30 '22 at 03:01
  • `16711935 * 1671193` is signed integer overflow - UB. – chux - Reinstate Monica Jul 30 '22 at 03:03
  • @Dan Then you have integer overflow resulting in undefined behavior. The type of the result is dependent solely on the types of the operands, not their values. – dbush Jul 30 '22 at 03:03
  • another example then `if (16711935 * 1671193 > 1){}`, what is the result type of `16711935 * 1671193` here? – Dan Jul 30 '22 at 03:05
  • @Dan Again, the type of the result is dependent solely on the types of the operands. So the result of `int * int` is always `int`. – dbush Jul 30 '22 at 03:06
  • ok that's what I've been looking for, so there is a rule that says`the result is dependent solely on the types of the operands. So the result of int * int is always int` ? do you have a link to the specific rule? – Dan Jul 30 '22 at 03:07
  • 1
    @Dan From section 6.3.1.8p1 regarding Usual Arithmetic Conversions: *"Many operators that expect operands of arithmetic type cause conversions and yield result types in a similar way. The purpose is to determine a common real type for the operands and result. For the specified operands, each operand is converted, without change of type domain, to a type whose corresponding real type is the common real type. **Unless explicitly stated otherwise, the common real type is also the corresponding real type of the result**"* – dbush Jul 30 '22 at 03:12
  • @dbush just wanted to confirm that in `uint64_t a = 16711935 * 1671193;` the result is a `unint64_t`, but in `if (16711935 * 1671193 < 5){}` the intermediate result type of the multiplication is also an `int` (same type as the biggest operand according to conversion rules) which overflows and we get UB? – Dan Jul 30 '22 at 16:42
  • @Dan The result of the multiplication is still an `int`, and that result is converted to a `uint64_t` before assignment. – dbush Jul 30 '22 at 16:48
  • @dbush so if the intermittent results still is an int then we also have UB in the first case? – Dan Jul 30 '22 at 16:56
  • 1
    @Dan Correct. `int * int` will always result in an `int`, regardless of what other expression it may be a part of. – dbush Jul 30 '22 at 16:58
  • Solution is to cast at least one of the inputs to the expected result type then? I.e `uint64_t a = (uint64-t)16711935 * 1671193;` – Dan Jul 30 '22 at 17:16
  • 1
    @Dan Correct... – dbush Jul 30 '22 at 17:26
  • Thank you, could I bother you with one last question? Multiplication is a widening operation, meaning int32 x int32 will result in an int64, however, doing a `uint32_t a = 5 * 6` does not cause an overflow or UB because even though the result is 64 bits, the higher 32 bits are 0 in this case which does not cause an overflow correct ? – Dan Jul 30 '22 at 18:42
  • @Dan No, int32 x int32 results in a int32, so the result can overflow. – dbush Jul 30 '22 at 19:05
  • Not talking about C rules here, arithmetically int32 x int32 results in twice it's size, which is int64. It can be even done by hand on paper. – Dan Jul 30 '22 at 19:12
  • I will ask this question in a separate post, thanks. – Dan Jul 30 '22 at 21:21