This question already has answers here:
Why is ++i considered an l-value, but i++ is not?
(11 answers)
Closed 8 years ago.
What the title says. For C++, (++a)++ does compile. Strangely enough, though, ++(a++) does not:
int main() {
int a = 0;
++a++; // does not compile
(++a)++; // does compile
++(a++); // does not compile
}
But in Java, it does not for all three:
public class Test {
public static void main(String[] args) {
int a = 0;
++a++; // does not compile
(++a)++; // does not compile
++(a++); // does not compile
}
}
Is there any reason why C++ compiles this but not in Java?
None of the examples work in Java because both postfix and prefix increment operations return values not variables we can see this by going to the JLS section on Postfix Increment Operator ++ for an example and it says:
The result of the postfix increment expression is not a variable, but a value.
The JLS section for Prefix Increment Operator ++ says the same thing.
This would be like trying to increment a literal value (see it live):
2++ ;
++3 ;
which gives the following error:
required: variable
found: value
Which is the same error we receive for your examples.
In C++ prefix increment returns an lvalue but postfix increment returns an prvalue and both prefix and postfix increment in C++ require an lvalue. So your first and third C++ example:
++a++;
++(a++)
fails because you are attempting to apply prefix increment to a prvalue. While the second C++ example:
(++a)++;
is okay because prefix increment returns an lvalue.
For reference the draft C++ standard in section 5.2 Postfix expressions says:
The value of a postfix ++ expression is the value of its operand [...] The operand shall be a modifiable lvalue
and:
The result is a prvalue
and section 5.3 Unary expressions says:
The operand of prefix ++ is modified [...] The
operand shall be a modifiable lvalue
and:
The result is the updated operand; it is an lvalue
Related
This question already has an answer here:
What is the type of a ternary expression with int and char operands? [duplicate]
(1 answer)
Closed 2 years ago.
This subject is already asked but I didn't understand it.
You'll find my program below. When I run this program it prints X and 88. When I remove do the declaration of int i = 0 it returns X and X. I found some explanations here : Unexpected output when using a ternary operator and final variable but i didn't understand it so much. I don't understand why this program returns X and 88 instead of X and X.
public class Ternary {
public static void main(String[] args) {
char x = 'X';
int i = 0;
System.out.println(true ? x : 0);
System.out.println(false ? i : x);
}
}
please read the rules of ternary operator here
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25
1st one is result of If one of the operands is of type T where T is byte, short, or char, and the other operand is a constant expression of type int whose value is representable in type T, then the type of the conditional expression is T. T being type char in this case and constant expression being 0
so the output is of type char which is x
2nd one is case for Otherwise, binary numeric promotion is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands.
read about binary numeric promotion here https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2
last case of point 2 applies here Otherwise, both operands are converted to type int. and converting char to int gives its ascii value which is 88
and hence the output is 88
This question already has answers here:
Java conditional operator ?: result type
(5 answers)
Why does the ternary operator unexpectedly cast integers?
(3 answers)
Closed 6 years ago.
Please consider we have code below:
Object obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass() + "\nvalue = " + obj);
And its result is:
class java.lang.Long
value = 0
Instead of:
class java.lang.Integer
value = 0
Could someone clarify why we have such functionality in Java? It is very strange for me.
Do you have any example where this can be useful?
UPDATE:
Here is piece of bytecode, where we can see, whats going on there
NEW java/lang/Integer
DUP
LDC "0"
INVOKESPECIAL java/lang/Integer.<init> (Ljava/lang/String;)V
INVOKEVIRTUAL java/lang/Integer.intValue ()I
I2L
INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
ASTORE 1
What's going on here is the result of
Binary numeric promotion turning your Integer and Long types into long for use as the common type to apply to the conditional operator expression
Unboxing those wrapper objects
And then boxing the resulting value of the conditional expression
The conditional operator's second and third operands must end up having the same type, which is the resulting type of the expression. Integer and Long are not, of course, the same type.
However, as described in JLS§15.25, the compiler will apply binary numeric promotion when determining the possible common type to apply to the expression. That section has the handy Table 15.25-D which tells us that when the second operand is of type Integer and the third operand is of type Long, the compiler will do binary numeric promotion on Integer,Long. Binary numeric promotion on Integer,Long yields long. So the result of the conditional operator expression is long.
Since the expression's result type is long, the Integer or Long will have to be unboxed (and then cast, in the case of Integer).
Finally, you assign it to an Object, which forces boxing, and wraps the long in a Long. Thus, you end up with a Long containing the value 0, which matches your output.
So effectively, if we ignore the fact the compiler will optimize half of the following away since it's dealing with a constant expression thanks to the true in the code (I've used flag below instead), that code ends up being this:
Object obj = Long.valueOf(flag ? (long)(new Integer(0)).intValue() : (new Long(1)).longValue());
System.out.println(obj.getClass() + "\nvalue = " + obj);
The (long)(new Integer(0)).intValue() represents unboxing the Integer and casting it to long so it matches the expression result type.
The (new Long(1)).longValue() represents unboxing the Long so it matches the expresion result type.
And the Long.valueOf represents the boxing at the end.
This behavior is well explained in the JLS - 15.25. Conditional Operator ? ::
The conditional operator has three operand expressions. ? appears between the first and second expressions, and : appears between the second and third expressions.
[...]
The type of a conditional expression is determined as follows:
[...]
Otherwise, if the second and third operands have types that are convertible (§5.1.8) to numeric types, then there are several cases:
[...]
Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands.
Actually long can store the value of an integer but integer can not store the value of long(Concept is widening) and you are storing it in Object that's why it's storing it in Long. internally it's also using boxing and unboxing
Possible compiler code:
Long obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass() + "\nvalue = " + obj);
Not working code(unable to compile):
Integer obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass() + "\nvalue = " + obj);
check by yourself and let me know if you havr any doubt in it.
This is related to how the ternary operator works.
The operands on both sides of the : must be of compatible types, so you can't have this:
true ? 1 : "Hello"
Since int and String cannot be implictly converted to each other.
In your case however, the types are compatible! An int can be implicitly converted to long. And that's what the compiler did! It saw an int and a long and decides that the expression should evaluate to a long. It unboxes the two values and implictly convert the int to a long. And finally, it boxes the resulting long so it becomes Long and put it in the variable.
I have a java class as follows:
class A{
public static void main(String[] args){
int a=10;
a*=a++ +a;
System.out.println(a);
}
}
Output:210
In my opinion the output should be 231 calculated as follows:
a*=10+11;
a*=21;
a=a*21;
a=11*21;
a= 231;
Can anyone please explain me where am I wrong and why?
In any statement of the type:
x *= y;
The initial value of the LHS is evaluated before the RHS. So your statement:
a *= a++ + a;
Is equivalent to:
a = a * (a++ + a);
Which sets a to the value 10 * (10 + 11) => 210.
If you're particularly interested in the formal specification related to this point you can find it here which contains the rule "If the operator is a compound-assignment operator (§15.26.2), then evaluation of the left-hand operand includes both remembering the variable that the left-hand operand denotes and fetching and saving that variable's value for use in the implied binary operation."
Consider 15.7.1. Evaluate Left-Hand Operand section of java specs where it says - First, the left-hand operand is evaluated to produce a variable then the value of the right-hand operand are used to perform the binary operation indicated by the compound assignment operator
In your case it is a = 10 * ((11)+10) = 201
This question already has answers here:
What is the purpose of Java's unary plus operator?
(7 answers)
Closed 8 years ago.
I ran across this while reviewing a colleague's code. She'd left it in by accident (it used to be a String concatenation), and I assumed that it wouldn't compile. Turns out I was wrong, so I tried seeing what that operator did:
public static void main(String[] args) {
int i = -1;
System.out.println(String.format("%s", +i));
System.out.println(String.format("%s", +i));
}
As far as I can tell, it does nothing, but I'm curious if there is a reason it's allowed to compile. Is there some hidden functionality to this operator? It's similar to ++i, but you'd think the compiler would barf on +i.
That is the plus unary operator +. It basicaly it does numeric promotion, so "if the operand is of compile-time type byte, short, or char, it is promoted to a value of type int".
Another unary operator is the increment operator ++, which increments a value by 1. The increment operator can be applied before (prefix operator) or after (postfix operator) the operand. The difference is that the prefix operator (++i) evaluates to the incremented value, whereas the postfix operator (i++) evaluates to the original value.
int i = -1;
System.out.println(+i); // prints -1
System.out.println(i++); // prints -1, then i is incremented to 0
System.out.println(++i); // i is incremented to 1, prints 1
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Have a look at the following code :
Case 1 :
char a = 'x' ^ 'y';
It is working fine.
But when I use variable instead of constants as here :
Case 2:
char x = 'x';
char y = 'y';
char a = x ^ y; // Error!
In java language : case 1 is working and value of a comes out to be 1 but case 2 is not working.
In C and C++ : both cases are working, and the value of a comes out to be 1
In C# : both the cases are not working.
In javascript : both cases are working, which is not a HLL, and value of a comes out to be 0.
I understand that java is converting variables to integer to do binary operation, but why it is working in case 1 and not in case 2, Why same is not working in C# And why the values are different in the case of javascript.
Updated
When I made the variables final than it is working in java, but still not in C#
final char x = 'x';
final char y = 'y';
char a = x ^ y;
But still I cannot understand why constants are working but when using variable they are not. And why same is not happening with other high level programming language.
I think it is a basic operation and should be working in all programming languages with same behaviour.
Note To test all above cases in javascript I am replacing 'char' with 'var' in all cases and they are working.
Answering for Java only.
The expression 'x' ^ 'y' is a constant expression; x ^ y is not, unless both variables are declared final. Furthermore, the result is an int; ^ is an integral bitwise operator, meaning that both operands have to be promoted to an integral type before being evaluated. char promotes to int.
So you have this int expression, and you try to narrow it to a char. In the general case, this could lead to a loss of precision (ints are 4 bytes, chars are 2), so the compiler doesn't let you do that without you explicitly stating it's what you want to do (via a cast to char). However, you can implicitly narrow constant expressions, if their value would fit into the new type. From JLS 5.2:
A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.
(Emphasis added)
Intuitively, this makes total sense: the error is there to tell you that you may lose precision, and so it wants you to confirm that you know that; in a sense, it's a loud warning. But if the compiler can know absolutely that this won't happen, as it can for a constant expression, then it makes things a bit easier for you and "hides" that warning.
I will consider C languages that is C, C++ and C#.
In C# there is no implicit conversion from an integral type to type char. According to section "11.1.5 Integral types" of the ECMA 334 Standard "C# Specification"
• There are no implicit conversions from other types to the char type.
In particular, even though the sbyte, byte, and ushort types have
ranges of values that are fully representable using the char type,
implicit conversions from sbyte, byte, or ushort to char do not exist.
So you need explicitly to cast the result of the operator to type char. For example
using System;
namespace ExclusiveOr
{
class Program
{
static void Main(string[] args)
{
char a = ( char )('x' ^ 'y' );
char c = 'x', d = 'y';
char b = ( char )( c ^ d );
Console.WriteLine("a = {0}, b = {1}", (int)a, (int)b);
}
}
}
The output is
a = 1, b = 1
According to the C Standard (section 6.7.9 Initialization)
4 All the expressions in an initializer for an object that has static
or thread storage duration shall be constant expressions or string
literals
So for example this code will be compiled
#include <stdio.h>
char a = 'x' ^ 'y';
int main(void)
{
printf( "a = %d\n", a );
return 0;
}
The output is
a = 1
However this code will not be compiled
#include <stdio.h>
char c = 'x';
char d = 'y';
char b = c ^ d;
int main(void)
{
printf( "b = %d\n", b );
return 0;
}
will not be compiled. The GCC compiler will issue error
prog.c:8:1: error: initializer element is not constant char b = c ^ d;
However if you will make varaible b local then the code will be compiled successfully
#include <stdio.h>
char c = 'x';
char d = 'y';
int main(void)
{
char b = c ^ d;
printf( "b = %d\n", b );
return 0;
}
The output is
b = 1
In C++ there is no such a restriction for objects with the static storage duration so all examples of programs similar to C programs showed above will be compiled.
Under normal circumstances, the operands of the following binary operators are "widened" before the operation is performed.
(From the JLS 5.6.1)
The multiplicative operators *, /, and % (§15.17)
The addition and subtraction operators for numeric types + and - (§15.18.2)
The numerical comparison operators <, <=, >, and >= (§15.20.1)
The numerical equality operators == and != (§15.21.1)
The integer bitwise operators &, ^, and | (§15.22.1)
In certain cases, the conditional operator ? : (§15.25)
In the case of char operands, widening will convert the operands to int.
For the arithmetic and bitwise operations, the type of the operation's result is the same as the "wider" of the two operands.
When x and y have type char, the expression x ^ y gives you an int value. That can't be assigned back to a char without a type cast, and hence you get a compilation error.
For the case where you are using char literals, the same widening process happens. But there is a "special exception" in the language which allows the value of a constant expression to be implicitly narrowed, provided that the constant expression's value will fit into the type. In this case, 'x' ^ 'y' will "fit" into a char, so the assignment is allowed.
The JLS reference for this exception for constant expressions is JLS 5.2.