I came across this code line in C:
#define RUNDE(n) ( K ^= Q[n], y = K, K = F(K) ^ xR, xR = y )
Is it valid to assign something to K multiple times? I thought it's invalid to change a variable more than one time in one statement.
Is it valid to assign something to K multiple times?
That's perfectly valid C macro. A comma operator , is used here.
Using , operator you can assign a value to a variable multiple times.
e.g.K = 20, K = 30; This will assign 30 to K overwriting the previous value of 20.
I thought it's invalid to change a variable more than one time in one statement.
Yes it leads to undefined behavior if we try to modify a variable more than once in a same C statement but here first , is a sequence point.
So it's guaranteed that we will be modifying the K second time (K = 30) only when all the side effects of first assignment (K = 20) have taken place.
This is well-defined as the comma operator evaluates its first operand before its second.
However, IMHO this code is horrible and you shouldn't write it. inline functions exist to do things like this; using the preprocessor is just abuse. Sure, you would need to pass some arguments to an inline function, but this is far preferable to relying on names from the surrounding scope.
In C++ this would be regarded as nasty; in C it's permissible as the reliance on the preprocessor is more necessary.
But in either case your expression is perfectly well-defined. The comma operator (which is evaluated from left to right), acts as a sequenced expression separator.
The elegant thing with this macro is that its value is the value of xR = y, which is the final value of y.
But the inelegance of this macro, such as using variable names that are not passed as arguments, probably outweighs any benefits. My inclination is to bin it.
It is a valid comma operator, that perform all statements in sequence, returning the value of the last statement.
That macro is a sequence of assignments, using the last assignment (y or xR) as return value
Related
I have a question on a program that includes the following if statement:
if (x =+ 4){
x += 5;
}
I've never seen anything like that before, surely it isn't a typo? Does =+ actually do anything?
x =+ 4
means
x= (+4)
or simply
x=4
though such construction syntactically correct and can be compiled, does not make much sense and most probably a typo, where x==4 was intended, especially that it is used as condition for if
In the early days of C, =+ was the same as +=, but that's long gone and never made its way into C++.
=+a is understood to be = (+a)
The unary + operator promotes the argument to an int if it's of a narrower type, otherwise it's a no-op.
And = is regular assignment.
You can contrive a difference between =+ and = in this way:
If = was twice overloaded for two particular pairings, for example {Foo, int} and {Foo, char}, and you had an instance of Foo foo and a char c, then
foo = c // calls the overload taking a `char`
and
foo =+ c // calls the overload taking an `int`
would call different overloads.
Sorry, my initial answer was due to foolishly misreading the question.
The correct answer, is this code simply assigns x the value of positive 4,
because this is then non zero it satisfies the if and increments it further by 5.
A simpler form of this program in its current state would be:
x = 9;
However I strongly suspect there was a typo involved and the statement inside the if condition should either be x == 4, x += 4 or x != 4 depending on context.
OK just to round this out, I did find that my hunch was right, =+ and =- are indeed just obsolete forms of the += and -= op's in use today:
Stack Overflow: What does =+ mean in C?
https://www.cs.auckland.ac.nz/references/unix/digital/AQTLTBTE/DOCU_064.HTM (now that's a vintage web page!)
and specifically
https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C
tells us that they were changed: "Compound assignment operators of the form =op (such as =-) were changed to the form op= (that is, -=) to remove the semantic ambiguity created by constructs such as i=-10, which had been interpreted as i =- 10 (decrement i by 10) instead of the possibly intended i = -10 (let i be -10)."
So it's not to do with making an argument explicitly +ve or -ve. You can simply substitute the modern forms, eg use += in place of =+.
What would be a quick and accurate way of initializing a complex array? Are there any differences in the following:
complex(real64) :: x(2,2)
x = 0
x = 0d0
x = (0d0,0d0)
Are they the same and can I assume I get the same result on every compiler? Does the standard say anything about it? The question is specifically about initializing to zero, not any other number.
Before coming to the real answer, a note about terminology. In Fortran what you have here is not initialization but assignment. These are two distinct things. Yes, it's clear what is meant here but it's perhaps good to become aware of the distinction.
The lines like x=0 are intrinsic assignment statements. To the left of = is the variable and to the right the expression. For each of these in the question there are two considerations:
the variable and expression may differ in type or type parameter;
the variable is an array and the expression a scalar.
As stated in a related answer, when the variable and expression differ in type or type parameter (but are type conformable as in this case) the expression is converted to the type and type parameter of the variable.
The first two assignments certainly involve type conversion: 0 is an integer and 0d0 is a (double precision) real. Although (0d0, 0d0) is a complex - so there is no type conversion - this will be of different kind unless double precision is the same as real(real64).
So, for at least the first two we have conversion like the equivalent
x = CMPLX(0, KIND=real64)
x = CMPLX(0d0, KIND=real64)
and for the third perhaps
x = CMPLX((0d0, 0d0), KIND=real64)
With
x = (0._real64, 0._real64)
we can be sure the kinds of the variable and the expression are the same.
As long as CMPLX(0, KIND=real64) has the same value as (0._real64, 0._real64) you can be sure that the assignment x=0 (for now, for scalar x) has the same effect as x=(0._real64, 0._real64). This is mandated by the Fortran standard.
Zero is somewhat of a special case in that it appears in every model number set, but whenever a (mathematical) number is used which can be exactly represented in all three the effect will be the same. Equally,
x = 3.14_real64
and
x = (3.14_real64, 0._real64)
are equivalent.
Perhaps worth noting, though, is that some compilers with some options may offer warnings about implicit conversion. That is one difference to be observed even with the numeric values being equivalent.
Coming to the array/scalar aspect: the expression is treated as though it is an array of the same shape as the variable with every element equal to that scalar value.
To conclude: each of those three assignments has the same Fortran-effect. After the assignment x is an array of given shape with each element having complex value (0._real64, 0._real64).
Now, that isn't to say that there won't be a possibility of something exciting happening at a low level, and that zero-setting may be a special case. But that's something between you and your compiler (and system).
I was going through someone elses code and I wasn't able to get the syntax of following
c = x<0 ? x = -x,'L':'R';
and
if(x) x--,putchar(c);
going by the symantics, it is clear that in the first, variable c is assigned 'L' or 'R'.And in the second, both x-- and putchar() are executed. But what exactly is the role of comma operator here??
But what exactly is the role of comma operator here?
In this case, code obfuscation. The original developer probably thought they were being clever.
The comma operator allows you to perform multiple actions in a single statement, but you are almost always better off using 2 statements. In those cases, it expands to:
if( x < 0 ) {
x = -x;
c = 'L';
} else {
c = 'R';
}
and
if(x) {
x--;
putchar(c);
}
The comma operator evaluates both expressions, and returns the value of the last.
The first expression does two things in one statement. If chooses 'L'
or 'R' and also sets x to its negative if 'L' is chosen.
The second expression (the part after the 'if') decrements x and then
puts a character. The meaning of this is unclear without more context.
Readability in both could be improved by using separate statements rather than the comma operator. The first tries to shoehorn an if statement into a conditional expression. But the second is already using an if statement, so it's unclear why the comma operator was chosen at all.
The role of the comma operator in that context is to allow using the conditional operator and write an assignment as part of the evaluation of one of the expressions.
In my opinion, this is just horrible style. An if statement would have better communicated the intent of that code, and would have hardly been less efficient.
Why does int a[x,y] convert into a[y], since comma operator operates left to right? I would expect a[(x,y)], since inner operation will finish first. But in the first one it is supposed to take the first argument.
I'm not planning to use the comma operator for array initialization, just asking why this happens.
I read it in a book, and I'm confused.
Update:
Wikipedia says:
i = a, b, c; // stores a into i
i = (a, b, c); // stores c into i
So as first line of code says in the array the first value must be assigned to the array. Note: I'm not actually planning to use this. I'm just asking. I'm learning C++ and I read in a book that in an array declaration a[y,x]; so it should be a[y], x; not a[x]. Why does the compiler do this?
The comma operator , is also known as the "forget" operator. It does the following:
Completely evaluate the left operand
Forget its value
Completely evaluate the right operand
Use value of right operand as value of entire operator expression.
So in your case, it behaves just as it should. a[x, y] first evaluates x, then discards its value, then uses the value of y as the value of the entire expression (the one in brackets).
EDIT
Regarding your edit with Wikipedia. Note that the precedence of , is less than that of =. In other words,
i = a, b, c;
is interpreted as
(i = a), b, c;
That's why a is copied into i. However, the result of the entire expression will still be c.
I believe that your compiler is assuming that you meant to add parentheses. In C++ there's a comma operator and a comma separator. The comma operator must itself and its operands be enclosed in parentheses. The int array constructor only expects one value, so I'm guessing that your compiler is trying to help you out.
http://msdn.microsoft.com/en-us/library/zs06xbxh(v=vs.80).aspx
EDIT: int a[x,y] is not valid; int a[(x,y)] is valid; his compiler is assuming he meant to add parentheses. In a more general context the comma operator doesn't require parentheses. In function calls and initializers parentheses are required to distinguish between using a comma operator and a comma separator.
The Question :
In programming , assignment statement is an expression , but how about initialization?Is it an expression??
the parentheses of a while loop should contain an expression , so i try to put an initialization into it , and the compiler prompt me an error , this shows initialization is not an expression.
To further prove it , i try the for loop , and i do this for(int num = 3 ; num2 = 4 ; num3 = 5).Surprisingly the compiler give me errors again.
So if an initialization is not an expression , what kind of statement it is??
Thanks for spending time reading my question
In both C and C++, assignment is an expression. E.g. a = 5 is an assignment-expression.
In both C and C++ you can use any expression followed by a semi-colon where statement is required - such as the body of a function. This type of statement is an expression-statement. (Technially, you can leave out the expression entirely. ; is a degenerate expression-statement.)
You can only use a declaration where a declaration is expected, not everywhere where you can use an expression.
The following is not an expression or an expression-statement, it is a declaration. (Technically, in C++, it can form a declaration-statement when used where a statement is expected, in C it is just a declaration.) Note that there is no assignment-expression sub-part to this declaration, = 3 is an initializer for the declared entity num.
int num = 3;
These two common uses of = (initialization and assignment) are sometimes confused. Where = is being used to initialize the entity being declared in a declaration, it is initialization, where it is being used to change the value of an already declared entity, it is assignment.
Here is where C and C++ differ: in C, the parenthesised entity immediately following the while keyword must be an expression so something like while (int num = 0) { /* ... */ } is not valid.
In C++ the entity can be a condition, which allows for a simple declaration with an initializer as well as a simple expression, as in C. In C++, where the condition is in the form of a declaration, the declared entity is initialized on each iteration and implicitly converted to bool to determine whether to execute the loop body.
The for loop is special in both languages. In both languages the first part of the parenthesized list following the for keyword can effectively be either a declaration or an expression-statement.
The for loop takes three expressions in C and C++. The first is executed before the loop is run. The value of the second is used to determine when the loop ends. The third expression is executed at the end of each iteration of the for loop.
You can abuse the intent of the for loop and put whatever expression you want in those three sections.
The while loop while(<expression>) {<body>} is equivalent to the for loop for(;<expression>;) {<body>}.