This question already has answers here:
Using a variable with the same name in different spaces
(4 answers)
Closed 6 years ago.
I have following code:
int X = 1;
if (int X = X)
{
printf("%d\n", X);
if (int X = X)
{
printf("%d\n", X);
}
}
My expectation is X should be 1, 1. However, the output is:
1818935350
32767
Anyone know what's going on here? Compiled with clang-800.0.42.1
Edit: I tried the following code with a bit tweak, and now it behaves as I expected.
int X = 1;
if (int Y = X)
{
printf("%d\n", Y);
if (int Z = X)
{
printf("%d\n", Z);
}
}
One guess is when you use variable on RHS of a declaration inside if statement, it might not refer to the variable with the same name declared at parent scope, instead it's referring to the variable that's being defined...
When you say int X = X, both X's refer to the same int. That is, the one you are declaring right there in that line. So you are initializing X with itself, which is undefined behavior, since it was (of course) not already initialized. The X that you initialized with 1 is never printed in your code, since it is declared in a parent scope and shadowed by the ones in the inner scopes.
In C, this if (int X = X) is plain wrong because the if statement expects a control expression - but NOT a declaration.
6.8.4.1 The if statement
The controlling expression of an if statement shall have scalar type.
I'm not sure about clang, but gcc gives this code an obvious error (not a warning) even without any compiler flag (ie without -Wall -Wextra)
error: expected expression before ‘int’
Change all the
( Int X =X) to (X)
It is creating new variables and possibly returning old data stored in that location.
Related
Can we have a function calling at the left side of the expression?
This code snippet works well but how? How can a function calling can be at left side and please elaborate how this snippet is executing and working well and what if i wouldn't have used static int in function definition.Thanks in advance.
#include<iostream>
using namespace std;
int &fun()
{
static int x;
return x;
}
int main()
{
fun() = 10;
/* this line prints 10 on screen */
printf(" %d ", fun());
getchar();
return 0;
}
Any expression that returns a non-const lvalue can be on the left side of the assignment and function call is also an expression like any other. Since lvalue historically means exactly that - value on the left side this turns into a recursive definition. So instead you can consider an lvalue anything that you can take address of:
int x = 5;
&x; //valid, takes the address of the variable
&5; //invalid, integer literal has no address
int func1();
&func1(); //invalid, can't take the address of the temporary value
int &func2();
&func2(); //valid, since the function returned reference
//which itself is almost the same as the address
So any expression that results in something addressable can be assigned to. You can even do something like this:
int x = 0;
int y = 0;
int z = 5;
(z > 5 ? x : y) = 10;
As for your second question, if you remove static from your function you would return a reference to a local variable of the function. Local variables stop existing when the function exits, so you would return a reference to a variable that is already destroyed. This, however, will compile and run, but the results of that execution would be unpredictable that's why this is called undefined behavior.
In the following code, 2 is printed.
int x = 1;
int f(int y)
{
return x;
}
int main() {
x = 2;
printf("%d", f(0));
}
How is it happening if we have static scoping in C? Why isn't 1 printed?
Printing 2 in this case isn't a dynamic scoping, is it?
I thought that in static scoping it should take the nearest x to the function definition.
It does take the nearest x, but since you only have one x it doesn't really matter.
If you change the code to
int x = 1;
int f(int y)
{
return x ;
}
int main() {
int x=2;
printf("%d", f(0));
}
so you have 2 x, the global one and the local one in main you will see 1 getting printed.
Those are usually called dynamic and lexical scoping.
Lexical scoping is determined entirely at compile time, dynamic scoping at runtime.
You only have one variable named "x", so scope is irrelevant to your program.
Here's a program that would be different depending on the scoping rules:
int x = 0;
int f()
{
return x;
}
int main()
{
int x = 1;
printf("%d\n", f(x));
}
Under lexical scoping, f returns the value of the x that is lexically "nearest" - the global one.
So it would print 0;
Under dynamic scoping, f would return the value of the newest x, which is the one in main.
So it would print 1.
The scoping is moot here since you have not declared an x locally that would have otherwise shadowed the global x.
2 is printed.
x is assigned in main to 2 immediately before f is called with the parameter 0.
(Conceptually int x = 1; is ran before main is entered.)
It is the way the compiler generates the assembly/machine code.
first global variable X is stored in memory location "abc"
next main is executed: global variable X at "abc" is changed to 2
Now function f() is called:
function f returns the value of global variable X at "abc": being 2
the return value of f() is printed.
So if you wanted a different X in the main-function scope, you should have made a new object, like in the answer by nwp.
This code compiles, but I have a run time error in Visual Studio:
Run-time check failure #3 - the variable 'x' is being used without being initialized...
int x = 15;
int main()
{
int x = x;
return 0;
}
I don't understand that behavior... in the error box when I click continue the program resumes and x has a corrupted content (like -8556328 instead of 15).
Why does this code work without a problem, and the int array is well declared?
const int x = 5;
int main()
{
int x[x] = {1,2,3,4};
return 0;
}
x is defined at the left of =.
so in x[x], [x] refer to the global one,
whereas in x = x;, x hides the global x and initializes from itself -> UB.
When you declare a new variable, its name becomes visible right here
int x =
// ^- there
because it is at that point the variable is fully declared, and as such; its name means something. At this point in time any other (previously declared variable) in a surrounding scope will be hidden.
There is no scope resolution operator in C, so you may not be able to use
int x = x;
in your program.
please use SRO( Scope resolution operator ::) to tell compiler which x is real x in your mind. As user defined names are mangled( Names are decorated) something like this to avoid ambiguity at it's level, these are just names used by compiler that best suits it
int x = 15;// Real name = gui_x
int main()
{
int x = x;// lui_x
return 0;
}
In this way run-time will know which version you are using but to avoid ambiguity it expects from you to use specific names. Sometimes above problem arise where you don't know that you are using already used names. For this C++ has created SRO.
Now in case of array x is address & not integer that stores something, that's why compiler didn't jumbled. You need to write
namespace abc //now all global variables are belongs to this ns abc
int x = 15;// Real name = gui_x
int main()
{
int x = abc::x;// lui_x
return 0;
}
This question already has answers here:
Modifying a const int in C++ [duplicate]
(2 answers)
Closed 7 years ago.
I have this piece of code:
#include <iostream>
using namespace std;
class X {
public:
const int x;
X(int i) : x(i) { }
int getX() const { return x; }
};
int main()
{
const X d(45);
const_cast<X *>(&d)->x = 47;
cout << d.getX() << endl;
const int j = 3; // j is declared const
int* pj = const_cast<int*>(&j);
*pj = 4;
cout << *pj << endl; //should not work, like above
return 0;
}
As I found here, Even though const_cast may remove constness or volatility from any pointer or reference, using the resulting pointer or reference to write to an object that was declared const or to access an object that was declared volatile invokes undefined behavior. They even proceed to provide examples below, the second one I gave, stating that it should give undefined behavior.
However, on compiling the code and running (here), the second one gives no error, and prints out 4 consistently. Whereas the first one throws error:
assignment of read-only member 'X::x'
const_cast<X *>(&d)->x = 47;
Of course, removing the const from declaration of x in X makes it work fine. However, it is also of the same type of mischief as the first one, changing a const thing through pointer after casting it const_ptr<>. But the first one works while the second one doesn't. Why so?
Both demands undefined behavior which unfortunately could mean working sometimes.
int* pj = const_cast<int*>(&j);
*pj = 4;
Also, Not all compilers are smart enough to figure out this kind of indirect manipulation.
Const-casting anything other than an actual const ptr* is probably a terrible idea, even if it does actually work most of the time.
That being said, the reason why your code doesn't compile properly is pretty straightforward: you remove the constness of the X object, but you fail to also remove the constness of the x member you're trying to modify.
Try this:
*const_cast<int*>(&(const_cast<X*>(&d)->x)) = 47;
I came across code similar to that below which is legal, albeit not very clever. Two stack variables in the same function in scope at the same time with the same name is legal but it can cause problems. (Read: I just wasted half an hour debugging this). At warning level 4 on VS2010 (the highest level), I would have hoped it would have caught this kind of thing. Am I missing something, or is it time to hit to whole code base with lint for a once over? Would a static analysis tool such as lint even pick up name clashes like this?
char *x = strchr(Buffer,' ');
if (x)
{
*x = 0;
x++;
char *x = strchr(x,' ')
if (x)
*x = 0;
}
PC-Lint will detect this. The following code:
main (int argc, char *argv [])
{
char *x = 0;
if (x)
{
char *x = 0;
}
}
Gives a warning:
main.cpp 6 Warning 578: Declaration of symbol 'x' hides symbol 'x' (line 3)
Edit: I didn't notice this when I wrote the original answer (below). The code you've posted is illegal, and causes undefined behavior. The offending line is this one:
char *x = strchr(x,' ');
Here the x within the strchr call does not refer to the x defined in the enclosing scope, but to the x defined previously on the same line. Hence that line reads from an uninitialized variable, which results in undefined behavior. From the C++ standard,
§3.3.2/1 [basic.scope.pdecl]
The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below. [ Example:
int x = 12;
{ int x = x; }
Here the second x is initialized with its own (indeterminate) value. —end example ]
GCC does complain if the corresponding line in the example below is changed to
int x = 21 + x; // generates "warning: x is used uninitialized in this function"
And duplicating your strchr example on VS2012 generates this warning (at /W1 and above):
warning C4700: uninitialized local variable 'x' used
Original answer follows (not entirely accurate):
There's nothing illegal about the code. You've introduced a new scope by adding braces, and you're allowed to define variables within the new scope even if those variable names have been previously defined in the enclosing scope.
All references to the variable after the new definition will refer to the local variable instead of the one in the enclosing scope, until the lifetime of the local variable ends. The following code produces no warnings on GCC even when compiled with -pedantic -Wall -Wextra
#include <iostream>
int main()
{
int x = 42;
{
std::cout << x << '\n';
int x = 21;
std::cout << x << '\n';
}
std::cout << x << '\n';
}
Output:
42
21
42
I don't know whether lint or another static analysis tool will pick out such things either. It is legal, but not advisable.