3.4 — Sizeof, comma, and conditional operators

Sizeof operator

Operator Symbol Form Operation
Sizeof sizeof sizeof(type)
sizeof(variable)
Returns size of type or variable in bytes

We covered the sizeof(type) form of the operator in lesson 2.3 -- Variable sizes and the sizeof operator. Refer to that lesson for more information on the sizeof(type) form of the operator.

Note that sizeof can also be used on a variable, and will return the size of that variable:

Comma operator

Operator Symbol Form Operation
Comma , x, y Evaluate x then y, returns value of y

The comma operator allows you to evaluate multiple expressions wherever a single expression is allowed. The comma operator evaluates to its rightmost operand.

For example:

z would be assigned the result of evaluating ++y, which equals 3.

In almost every case, a statement written using a comma would be better written as separate statements. For example, the above code should be written as:

Note that comma has the lowest precedence of all the operators, even lower than assignment. Because of this, the following two lines of code do different things:

Most programmers do not use the comma operator at all, with the single exception of inside for loops, where its use is fairly common. We discuss for loops in a future lesson.

Note that although a comma is used to separate the parameters in a function call, this is not using the comma operator.

Similarly, when declaring multiple variables on a single line, the comma there is just a normal separator, not the comma operator

Rule: Avoid using the comma operator, except within for loops.

Conditional operator

Operator Symbol Form Operation
Conditional ?: c ? x : y If c is nonzero (true) then evaluate x, otherwise evaluate y

The conditional operator (?:) (also known as the “arithmetic if” operator) is C++’s only ternary operator (it takes 3 operands). Because of this, it’s also sometimes referred to as the “ternary operator” (we suggest you avoid calling it this in case C++ adds another ternary operator in the future).

The ?: operator provides a shorthand method for doing a particular type of if/else statement.

If/else statements in the following form:

```if (condition)
expression;
else
other_expression;
```

can be rewritten as:

```(condition) ? expression : other_expression;
```

Note that the operands of the conditional operator must be expressions themselves (not statements).

For example, an if/else statement that looks like this:

```if (condition)
x = some_value;
else
x = some_other_value;
```

can be rewritten as:

```x = (condition) ? some_value : some_other_value;
```

Many people find this more compact form easier to read.

As another example, to put the larger of values x and y in variable larger, we could write this:

Or this:

It is common to put the conditional part of the expression inside of parenthesis, both to make it easier to read, and also to make sure the precedence is correct.

It is also worth noting that the expression between the ? and : is evaluated as if it were parenthesized.

Keep in mind that the ?: operator has a very low precedence. If doing anything other than assigning the result to a variable, the ?: statement needs to be wrapped in parenthesis.

For example to print the larger of values x and y to the screen, we could do this:

Or we could do this:

Because the << operator has higher precedence than the ?: operator, the statement:

would evaluate as:

That would print 1 (true) if x > y, or 0 (false) otherwise!

The conditional operator gives us a convenient way to simplify simple if/else statements, particularly when assigning the result to a variable or returning the result as part of a function return. It should not be used for complex if/else statements, as it quickly becomes both unreadable and error prone.

Rule: Only use the conditional operator for simple conditionals where it enhances readability.

The conditional operator evaluates as an expression

It’s worth noting that the conditional operator evaluates as an expression, whereas if/else evaluates as a set of statements. This means the conditional operator can be used in some places where if/else can not.

For example, when initializing a const variable:

There’s no satisfactory if/else statement for this. You might think to try something like this:

However, this won’t compile, and you’ll get an error message that classSize isn’t defined. Much like how variables defined inside functions die at the end of the function, variables defined inside an if or else statement die at the end of the if or else statement. Thus, classSize has already been destroyed by the time we try to print it.

If you want to use an if/else, you’d have to do something like this:

This one works because we’re not defining variables inside the if or else, we’re just returning a value back to the caller, which can then be used as the initializer.

That’s a lot of extra work!

The type of the expressions must match or be convertible

To properly comply with C++’s type checking, both expressions in a conditional statement must either match, or the second expression must be convertible to the type of the first expression.

So while you might expect to be able to do something like this:

The above example won’t compile. One of the expressions is an integer, and the other is a string literal. The compiler will try to find a way to convert the string literal to an integer, but since it doesn’t know how, it will give an error. In such cases, you’ll have to use an if/else.

71 comments to 3.4 — Sizeof, comma, and conditional operators

• Ashie

Sweet, this just helped shorten the code from the last lesson!

• Anon

Hi Alex, I was wandering: String can't be casted into int in the code right at the end, therefore it won't compile. But, int can be casted into string. So, if the roles were flipped, would the code compile than? and if not, why?

• nascardriver

Hi Anon!

> But, int can be casted into string
Explicitly, yes, but there needs to be an implicit conversion sequence, which there is not.
We can also cast a const char* to an int explicitly.

> So, if the roles were flipped, would the code compile than?
No, the order doesn't matter.

> and if not, why?

For this statement to be valid at least one of the three must be satisfied:
* B and C have the same type.
* There's an implicit conversion sequence to transform B to C (B can implicitly be cast to C).
* There's an implicit conversion sequence to transform C to B (C can implicitly be cast to B).

In this example, none of these cases is true.
* const char* is not the same type as int.
* int cannot be implicitly converted to const char*.
* const char* cannot be implicitly converted to int.

This is valid, because int and double can implicitly be cast to each other. One direction would've been enough to compile.

References
* Lesson 4.4 - Implicit type conversion (coercion)
* Lesson 4.4a - Explicit type conversion (casting)

• Chris

Hi Alex, i was just wondering, in your last snippet of code, you have false set in like this:

const int classSize = getClassSize(false);

I was wondering why you have to do that? Shouldn't getClassSize(); return a true or false value, then set the value based off of what the answer to that is?

• nascardriver

Hi Chris!

@getClassSize returns an int and takes a bool as parameter.

Passing false will set @isBigClassRoom to false and cause @getClassSize to return 20. @classSize is 20.

• Vu Dang

Alex, I have a question. What is actually an initializer in your statement: "the initializer can't be a statement."

• Alex

The initializer for a variable can't be a statement -- it must be an expression. That expression could be a literal value (e.g. 20 or 30), or a function call, or any other valid expression.

But that statement sort of missed the mark altogether. I've updated the lesson with a better and more accurate explanation of why an if/else can't be used (directly) in the const variable case.

Let me know if it makes more sense now.

Mr. Vu Dang, our dear Teacher, by "initializer", in the context of this example, means the value of variable "classSize", that is 30 or 20, eventually 20. Regards.
Regards dear Teacher, and many thanks for permission to answer question.

• Nick M

Just wanted to say thanks very much for this resource. Things are explained from first principles here. Most other C++ learning resources (i've used many) seem to introduce concepts in a somewhat haphazard way. This is the most clear, and best learning tool I've found so far.

• Hema

Will If statement and conditional operator act the same way in all the cases?

• Alex

Yes.

• James Ray

Hi Alex,

You have a few examples that have cout rather than std::cout. For consistency with earlier lessons, should you use std::cout, rather than just cout?

• Alex

Yes, definitely. I've updated the lesson. Thanks for pointing out the inconsistency.

• James Ray

You're welcome!

• Matthieu B.

There's an empty code section of one line right at the end of this lesson.

• Alex

Thanks, fixed.

• Grace

Could you please evaluate this and tell me why 1 is displayed?
int x=10,y=5;
cout<<(x>y)&&((x-2<2) || (!y>5));

Thanks!

• Alex

Breaking it down:
std::cout << (x>y)&&((x-2<2) || (!y>5)); becomes
std::cout << (true)&&((false) || (true)); becomes
std::cout << true&&true; becomes
std::cout << true
which prints as 1, since std::cout prints booleans as integer values by default.

• Stephane

!y > 5 :
y can be smaller or greater than 5, not so?

• Alex

Oops, the < signs were being interpreted as HTML. I've fixed them so they print as intended. Thanks!

• David

std::cout <<(x>y) && ((x-2<2) || (!y>5));

becomes
std::cout << true && (false || true);

or
std::cout << 1 && (0 || 1);

Because the boolean (0 || 1) evaluates to true, we have
std::cout << 1 && 1;

Since << has higher precedence than &&, << evaluates first.
(std::cout << 1) && 1;

So "1" ("true") is printed in the console, and the rest is discarded.

std::cout << (1 && 1);

"1" ("true") would still be printed because the boolean (1 && 1) evaluates to true.

• Amoeba

Why does (!y>5) evaluate to true?

Shouldn't it be like: (!y > 5) = (!5 > 5) = (0 > 5) = false ?

• Alex

Yes, ! takes precedence over >

• subh

I used code::blocks IDE and executed below statements. Outcome is 0;  Contrary to the given statement about comma operator (,).

int x = 0;
int y = 2;
int z = (++x, ++y)

• Alex

I'm not sure what you mean by "outcome is 0". What outcome? What were you expecting to happen?

• subh

Oh. My Mistake. It works fine.

int main()
{
int x = 0;
int y = 2;
int z = (++x, ++y);
std:: cout << z;
}

Output: 3

• Nyap

so basically;
1) sizeof operators will also evaluate to the size of a variable if you give it's name/identifier
2) comma operators are a way of combining multiple expressions. They evaluate to the value that is on the very right
3) conditional operators:
(expression) ? (value to evaluate to if expression is non-zero/true) : (value to evaluate to if expression is zero/false)

• Peng

Consider the above example, the GCC complain:
F:\LearnCpp\main.cpp|12|error: 'classSize' was not declared in this scope|
"It’s worth noting that the conditional operator evaluates as an expression, whereas if/else evaluates as statements. ", what's the exact meaning of this? Could you give the more detailed about it?
Nothing could be better for your help, Thanks Alex 🙂

• Alex

The problem here is that the lines that execute as part of the if/else statement are considered to have block scope, so the above actually compiles as if you'd typed:

In this context, it's a little easier to see that classSize is local to the block, and thus not accessible to be printed using std::cout.

Remember: an expression is a sequence of operators and operands that evaluates to a value. A statement is the C++ equivalent of a sentence, and ends in a semicolon. You can define a named variable in a statement, but not an expression.

• Karl

how to replace if else with conditional operator here??

• Alex

Replace:

with:

• Dear Teacher,

Also that I do not remember any teaching of yours about ":" in present or past lessons.
Regards.

• nascardriver

Hi Georges!

The ":" is covered in this lesson as it's part of the conditional operator.

• Dear nascardriver, please let me say: oooops you are right, I'm wrong. Many thanks for you replied and for your instructive answer. I'm sorry for delay in reply. Regards.

• Domenic D

I believe you said that the parts after the condition must be expressions not statements. Kinda wondering if there is a reason for that.

eg)

After the condition the two parts above are statements. Right? This works in CB but why should I not do this. Confused???

• Alex

cout << "whatever" is actually an expression, not a statement (remember, statements end in a semicolon).

Note that you can make any expression into a statement by putting a semicolon on the end of it (these are called expression statements). So when we write cout << "whatever"; this is an expression statement.

As for the reason why statements are disallowed inside the conditional operator, the conditional operator itself is an expression, sso what is inside it must also be an expression so the whole thing can evaluate to a single value. Otherwise you could do some weird stuff like this:

What does this even mean?

• Jim

Alex,
You've used z = ( x, y ) as a comma separator.  Does the compiler first assign z = x , then assign z = y, so this is the reason the comma uses the right most operand?

Is it true that if the code were z = ( u,v,w,x,y ) that  all of these variables would be assigned one at a time to z and end up with z = y?  Is it also possible to use integers
z= ( 1, 2 )?

• Alex

No, (x,y) is evaluated first to produce the value y, and then y is assigned to z. At no point will x be assigned to z.

For z = (1, 2), (1, 2) should evaluate to 2, and then the value 2 will be assigned to z.

• bram jorna

what is the usefull use of the conditional operator?
i get that it makes the code smaller. but doing so it might confuse you and give errors.
does it have any other advantages over a normal if/else statement apart from reducing the size of the typed code??

• Alex

Yes. The conditional operator evaluates as an expression, whereas if/else evaluates as a set of statements. This means the conditional operator can be used in places where if/else can not.

For example, when initializing a const variable:

There's no equivalent if/else statement for this, since const variables must be initialized when defined, and the initializer can't be a statement.

• Chris

I don't understand your sentence "There’s no equivalent if/else statement for this, since const variables must be initialized when defined, and the initializer can’t be a statement.". what is the point?

I can use if/else statement like this and work well :

• Alex

I think we're quibbling about the meaning of "equivalent". You're using it in the sense of "produces the same result", I'm using in the sense of "as good as".

While your suggestion does work (in this case), it has some serious downsides:
* It's a lot more complicated (7 lines instead of 2, and introduces a new variable into the scope)
* It's may be a lot slower, because you're doing an assignment and an initialization, whereas the conditional version does only the initialization. Integers are cheap to copy, so in this case it's probably not a big deal. But if this were a large array, you wouldn't want to take the performance hit of making an extra copy.

Therefore, I think it's safe to say it's not as good as using a conditional.

I'll change the word "equivalent" to "satisfactory" to indicate the statement is a comprehensive judgment, not just based on whether it works.

• Pravasi Meet

Consider following program (See live demo http://ideone.com/Nj3W4z & http://cpp.sh/8snm3)

The above program prints 4 as an output in C but prints 20(sizeof array) as an output in C++. The comma operator in C always results in an r-value even if its right operand is an l-value, while in C++ the comma operator will result in an l-value if its right operand is an l-value. This means that certain expressions are valid in C++ but not in C. That's why in above C program there is lvalue to rvalue conversion occurs but in C++ it always results in locator value.
Following is simple example to demonstrate it.

When you compile above program in C the C compiler will give following error:
[Error] lvalue required as left operand of assignment

It would be better If you add this information.

• Alex

This is technically interesting, but is there a use case where the comma operator returning an lvalue is actually useful?

• afshin javani

is it possible ,to make a program with c++ for android devices ?

int my knowledge=little,why=many;

while((my knowledge==little)||(why==many))
{
how?;

my knowledge++;
why--;
}

• Devashish

Yes, it's possible. You can use the NDK plugin with eclipse for writing in C++. But, because C++ is not the primary language used to write for android, I think you should learn java. If you are familiar with C++, it won't take more than a month to write codes in java. It's a truth that Java is the favorite language chosen by thousands of programmers, to write apps for android.

• Aryan

How do you avoid using a comma operator? I mean a comma is a comma. And the syntax of comma operator and normal comma is astoundingly similar!
Also how does the compiler know that I am using a comma operator and not a comma or using a comma and not a comma operator? (Sorry for so many commas)  😉

• Alex

I'm not sure what you mean. The C++ compiler is smart enough to infer when you're trying to use the comma operator and when you're not.

Typically in C++ the comma operator is used with for loops and that's about it. The other uses of comma are just to fulfill the expected syntax (e.g. to separate function arguments or parameters) -- they're not a use of the comma operator.

• Aryan

How does the compiler know that I am using the normal comma and not the comma operator? Is it that the comma operator gets activated or something when its around some particular type of syntax like the loop that you mentioned.
Also if I want to use comma operator how does the compiler know that I am using the operator and not the normal comma?
(I hope I didn't gave you a headache with so many commas) 😉

• Alex

When the compiler compiles your program, it breaks down each line into components and checks them against its list of valid syntax to ensure each line is valid.

In some of those rules, the comma symbol is used as a separator (e.g. to separate multiple arguments or function parameters).
In other rules, the comma is allowed as an operator (e.g. in an expression).

The language has been defined in such a way that there is no ambiguity about which use is intended (otherwise, the compiler wouldn't be able to compile your program without additional input from you).

• Mr D

ok, so:

means that the compiler only asks “is x bigger then y” (if so, output 1, otherwise 0) and the

part is just ignored?

(By the way, just so you know, when one posts a comment, then later edits it, after the edit the post no longer formats correctly using

)

• Alex

Yes, I believe your analysis is correct.

I noticed that the code formatter, the AJAX comment editor, and the "literal comments" plugin (that ensures code outside of code tags doesn't get treated as HTML) don't play together correctly. It's something we'll have to live with for now.

• mike

Why should we avoid calling it the ternary operator?

• Alex

Because that's not its name. It's the conditional operator. 🙂

Also, there aren't any guarantees there won't ever be another ternary operator.

• techsavvy....aye

how would you use the above snippets for programming ? can you give an example ?

• Darren

Finding the minimum or maximum between two values e.g.

Templating is an advanced topic but essentially means you can call this function with any type you like, so long as the type has the greater-than (>) and less-than (<) operators defined.

• Catreece

The arithmetic if is handy to know it exists, but I don't think I'll ever use it myself. It's far more concise, but also far less clear what's going on and it took a few re-reads of the example code to figure out what was being said even after understanding how it works because of the odd syntax.

I figure it'll be handy when reading over the code from other people, but I'm a stickler for keeping things as easy to read and understand as possible since my past experience has been that, in a week, you won't remember why you did something a certain way and if you have to change it, you'll definitely save time by it being easier to read than you would've saved by typing out a few more lines.

I suppose if you used the arithmetic if constantly, all the time, you'd get used to the format eventually, but even then it's still a matter of consistency: if you're going to do ten of the same kind of action, do it the same way each time so that you don't have to mentally juggle where the variables go when trying to adjust something, especially if you have to adjust all ten of those functions in a similar manner that's just barely off enough that you can't just do a global fix. At that point it's nice to have all ten of those functions looking nearly identical so that it's blatantly obvious what needs to be changed where without having to think about what needs to be altered.

I guess that's just my personal preference, but I'd always favour easier to read code over faster to write code if given the choice. =P

• bacia

return x, y;

would this only return y?

• Alex

Yes. I can't think of a reason you'd want to do this though.

• bla

It's a bit confusing that a lower precedence corresponds to a higher precedence level here. Is that the standard way of saying it?

• jeremy

Is it bad form to place the assignment inside the arithmetric if? eg.:

It compiles fine with Codeblocks and GCC.
This seems more elegant IMHO.

• Alex

I think

is the preferred form for several reasons.

1) It's not as redundant (there's only one assignment to z instead of two).
2) It makes it clearer that something is being assigned to z.

• manju23reddy

hi,
using sizeof function
will resolve during
1. runtime
2. compile time 3. pre-compile time

• mwgamera

It's not a function, sizeof is an operator.
Its value is determined in compile time.

• Steve

Hey, whats the point of the comma operator if all it does is evaluate to the rightmost operand?

• The only place I see the comma operator commonly used is inside loops, to increment multiple variables, especially for loops. We cover for loops in more detail in Chapter 5.7 -- For statements.

Using the comma operator is a useful way to increment or decrement multiple variables in a single expression. For example:

Due to the particular syntax constraints on for loops, all your variables have to be modified in a single expression -- this allows you to do that.

• Are you using the comma operator too when initializing multiple variables in one statement?

• Alex

No, this is an instance where C++ uses a comma as a normal value separator, not as an operator. Same when passing function parameters.

• Roee Sefi

Hi Alex,
If that so, this line:

isn't correct.
There is no comma operator there.

• Alex

Yes, you are correct. I've updated the example accordingly (by removing the "int").