2
#include <stdio.h>
int main()
{
   short int a;
   char c;
   printf("%d %d %d",sizeof(a),sizeof(c),sizeof(c+a));
}

In this sizeof a is 2 byte size of char is 1 byte but i add them up it is giving 4 byte. what it is doing inside the expression to make it 4

msc
  • 33,420
  • 29
  • 119
  • 214
  • 2
    Aside: `%d` ==> `%zu` – Weather Vane Oct 12 '17 at 17:46
  • 5
    how on earth is this getting so many votes? – Niall Cosgrove Oct 12 '17 at 17:53
  • 2
    Yeah... That's puzzling... Given that the expression `sizeof(c+a)` is a nonsensical and useless by itself. Well, I guess some people are just surprised by the results as the OP is. – Eugene Sh. Oct 12 '17 at 17:56
  • @EugeneSh. IMO it's actually an interesting question that gets into the nuances of the integer conversion rules. As in, "Why isn't the output 2?" Because offhand, you'd think `short + char` should be a `short`, right? – Andrew Henle Oct 12 '17 at 18:18
  • @Andrew I would even agree with you if I hadn't seen every third question on SO about the same effect and formulated much better. – Eugene Sh. Oct 12 '17 at 18:20
  • to start, the operator: `sizeof` returns a `size_t` which is further defined as `long unsigned int`. So the `%d` format specifiers are not correct. When compiling, always enable the warnings, then fix those warnings: (for `gcc`, at a minimum use: `-Wall -Wextra -pedantic -Wconversion -std=gnu11` ) – user3629249 Oct 13 '17 at 03:56
  • Does this answer your question? [Why does sizeof(char + char) return 4?](https://stackoverflow.com/questions/35300925/why-does-sizeofchar-char-return-4) – phuclv Apr 16 '20 at 01:49

4 Answers4

11

Adding a short int to a char results in an int, which apparently is 4 bytes on your system.

This is a case if "integer promotion". See In a C expression where unsigned int and signed int are present, which type will be promoted to what type? for an explanation. The rules are rather confusing, but the answers there explain it rather well.

Per 6.3.1.8 Usual arithmetic conversions of the C standard, the actual conversion rule is:

If both operands have the same type, then no further conversion is needed.

Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.

Otherwise, both operands are converted to the unsigned
integer type corresponding to the type of the operand with signed integer type.

The result is 4, because, as @WeatherVane noted in the comments:

5.1.2.3 para 11 EXAMPLE 2 In executing the fragment char c1, c2; /* ... */ c1 = c1 + c2; the "integer promotions" require that the abstract machine promote the value of each variable to int size and then add the two ints and truncate the sum. But there is no truncation here because the destination is unknown.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
  • 1
    Are you certain that it is promoting to an int and not a short? (Not saying you are wrong, I am just trying to figure out how the standard specifies promotion) – Christian Gibbons Oct 12 '17 at 17:49
  • @ChristianGibbons If the posted code and output is correct, it *is* being promoted to an `int`. Although as I read the rules, I also think that might be wrong and it *should* be promoted to a `short`. This might be a compiler bug. – Andrew Henle Oct 12 '17 at 17:50
  • 2
    @ChristianGibbons `a+c` has not been assigned to any target variable. Arithmetic calculations are promoted to `int`. – Weather Vane Oct 12 '17 at 17:50
  • @WeatherVane When I read through those rules, when I start with `short + char`, I wind up with `short`, not `int`. What am I missing? – Andrew Henle Oct 12 '17 at 17:53
  • 1
    This is not a type conversion to another variable type; there is no target variable type. Arithmetical calculations are promoted to `int` (to lessen the likelihood that intermediate values overflow) but I don't know the reference. – Weather Vane Oct 12 '17 at 17:56
  • 3
    5.1.2.3 para 11 EXAMPLE 2 In executing the fragment `char c1, c2; /* ... */ c1 = c1 + c2;` *the "integer promotions" require that the abstract machine promote the value of each variable to int size and then add the two ints and truncate the sum.* But there is no truncation here because the destination is unknown. – Weather Vane Oct 12 '17 at 18:07
  • @WeatherVane If you don't mind I'll add that to the answer. – Andrew Henle Oct 12 '17 at 18:14
  • @AndrewHenle please do. – Weather Vane Oct 12 '17 at 18:18
3

sizeof returns the size of the object representation after it has been evaluated. The expression c+a apparently returns an int, which is four bytes. I think what you are looking for is:

sizeof(c) + sizeof(a)

Derek Brown
  • 4,232
  • 4
  • 27
  • 44
3

When integral types like char, short int, bool take less number of bytes than int, then these data types are automatically promoted to int or unsigned int when an operation is performed on them.

C11 §6.3.1.1 Boolean, characters, and integers

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)

So, c+a are converted to type int and the result has this common type of operands that is int.

Also, the behaviour of your code is undefined, because you have used the wrong format specifier.

So, use %zu instead of %d because sizeof() returns size_t and size_t is unsigned.

C11 Standard: §7.21.6.1: Paragraph 9:

If a conversion specification is invalid, the behavior is undefined. 225) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

msc
  • 33,420
  • 29
  • 119
  • 214
2

For the mathematically inclined (and because it occurred to me to wonder when such a thing might ever be true):

The misapprehension that is OP is labouring under is that

f(x) + f(y) = f(x+y)

which is certainly not true for sizeof() for the reasons Tom points out in the comments.

The class of functions for which it is true are called Additive Maps

Typical examples include maps between rings, vector spaces, or modules that preserve the additive group.

Niall Cosgrove
  • 1,273
  • 1
  • 15
  • 24
  • 1
    Fun but in "C", sizeof is a compile-time operator and they are not functions. Back to abstract algebra, the two "+" operators are different, one being on unsigned integer values and the other being on types so I don't think you have a map. – Tom Blodget Oct 12 '17 at 18:53
  • 1
    @tom-blodget yep was just having some fun with a silly question :) Updated the answer to reference your input. – Niall Cosgrove Oct 12 '17 at 19:04