Afaik, every pair of { } in the code creates a new scope. Even if it's used just for the sake of it without any if, for, function or other statement that demands it:
void myFun(void)
{
int a;
{
int local;
}
}
I started wondering - when the if statement is written without using the braces (with 1-line body) does it still create a new scope?
voidmyFun(int a)
{
int b;
if (a == 1)
int tmp; // is this one local to if?
else
int tmp2; // or this one?
b = 2; // could I use tmp here?
}
N4140 [stmt.select]/1 reads:
The substatement in a selection-statement (each substatement, in the else form of the if statement) implicitly defines a block scope
So, the code
if (a == 1)
int tmp; // is this one local to if?
else
int tmp2; // or this one?
is equivalent to
if (a == 1)
{
int tmp; // yes, this one is local to if
}
else
{
int tmp2; // and this one as well
}
In short - yes. It's a single line scope.
In other words, writing:
if (someCondition)
int i = 7;
Is identical, scope-wise, to writing:
if (someCondition)
{
int i = 7;
}
Yes! tmp are local to if and tmp2 is local to else. If you try using tmp or temp2 outside, you should get variable not defined error. It is because,
if(<condition>) <my-statment>
if(<condition>)
{
<my-statment>
}
For compiler, both of them are equal.
Yes, even if the if and for do not have {}, the variables declared in it are local to it.
So, if you try something like
if ( something )
int a = 3;
std::cout << a; // there is no other identifier called a in your program
it will not compile, because it is the same as
if ( something )
{
int a = 3;
}
std::cout << a;
and you will get a variable not declared in this scope error.
So,
voidmyFun(int a)
{
int b;
if (a == 1)
int tmp; // is this one local to if? Ans:- Yes
else
int tmp2; // or this one? Ans:- It is local to else block
b = 2; // could I use tmp here? Ans:- No
}
So, the variable inside the else ( tmp2 ) is local to else and not to if.
Related
I have encountered the following binarySearch program
int binarySearch(int a[],int b, int c)
{
int start=0,end=b-1;
while(start<=end)
{
int mid=start+(end-start)/2;
if(a[mid]==c)
return mid;
else if(a[mid]>c)
end=mid-1;
else
start=mid+1;
}
if(start>end)
return -1;
}
in which mid variable is initialized in the loop which will be executed if the condition start<=end becomes true.
I am new to programming and i have learnt that redefinition of variable is not valid in C. But i have encountered binarySearch program in which loop will be executed when start<=end will be true and will be initializing an int variable named mid again and again till the condition will be true and thus redefinition will take place. I want to know "are redefinition valid inside loops?" or something else i am missing.
A variable itself is a compile-time concept, it's a label in the source code, a name which refers to an actual object that will exist at runtime.
Since int mid is only spelled once in your code, there's no redefinition. Even if it was spelled multiple times, if the variables are in different places, it can be legal (the variables will shadow one another):
int a = 1;
int main()
{
std::cout << a << '\n'; // 1
int a = 2;
if (true)
{
int a = 3;
std::cout << a << '\n'; // 3
}
std::cout << a << '\n'; // 2
}
Sorry if the question is hard to understand but I wasn't sure how to word it.
Say for example I had a struct like the following,
struct Days {
int counter;
};
And in main I had
Days *d = new Days;
d.counter = 0;
If I then use d in a loop like this inside main
do {
int num = rand()%900+1000;
d = add(d, num);
} while(user decides to continue}
delete d;
where the function add is as follows
Days *add(Days *d, int num) {
Days *temp2 = new Days;
temp2.counter = 0;
if (d.counter > 0)
temp2.counter = d.counter;
temp2.counter += num;
return temp2;
]
Do I need to delete d after each iteration of the do-while loop since its copying over?
If so, would it be in the add function in the if statement like this
if (d.counter > 0) {
temp2.counter = d.counter;
delete d;
}
Or would it be in the loop in main?
Actually, you don't need to allocate anything yourself.
In the main function, just declare your variable as:
// Create a Days object with counter initialized to zero
Days d {0};
Then, you can define your add function like that:
void add(Days & d, int num)
{
d.counter += num;
}
Or if you really want to use pointers instead of references:
void add(Days * d, int num)
{
d->counter += num;
}
Finally, you can just call it as follows:
do
{
int num = whatever();
add(d, num);
// add(&d, num); if you used the pointer version
}
while(condition);
If I may give you an advice, since add() is supposed to operate on a Days object, it may make sense to make it a member function of Days so that you wouldn't need to pass a Days as argument and get rid of the pointers/references stuff ^^
In that case,
add(d, num);
Would become:
d.add(num);
I would like the function to return different types depending on different parameter values, but how can I print the variable the void pointer points to
in main()?
#include <iostream>
#include <string>
using namespace std;
void * func(int a)
{
if (a == 1)
{
int param = 5;
return ¶m;
}
else if (a == 2)
{
double param = 5.5;
return ¶m;
}
else if (a == 3)
{
string param = "hello";
return ¶m;
}
else
{
return nullptr;
}
}
int main()
{
void *ptr = func(3);//
cout << ptr;// print the address not the value
getchar();
return 0;
}
param is an automatic variable. You cannot return it and use it outside its scope.
param exists only within func, if you return it, the result is Undefined Behaviour.
To fix it you can either:
allocate param on the heap dynamically. After you do that, you can safely return param address but you have to remember to free it when you don't need it.
Here is correction of your code
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
void * func(int a)
{
if (a == 1)
{
int *param = new int(5);
return param;
}
else if (a == 2)
{
double *param = new double(5.5);
return param;
}
else if (a == 3)
{
char *param = new char[50];
strcpy(param, "test");
return param;
}
return nullptr;
}
int main()
{
int *ptr = (int*)func(1);
cout << *ptr << std::endl; // print the int value
delete ptr;
double *ptr2 = (double*)func(2);
cout << *ptr2 << std::endl; // print the double value
delete ptr2;
char *ptr3 = (char*)func(3);
cout << ptr3 << std::endl; // print the string
delete[] ptr3;
getchar();
return 0;
}
If you can use C++17, you can easily solve it by using a std::variant instead of a void *:
#include<iostream>
#include<string>
#include<variant>
std::variant<int, double, std::string, void *> func(int a) {
if (a == 1) {
int param = 5;
return param;
} else if (a == 2) {
double param = 5.5;
return param;
} else if (a == 3) {
std::string param = "hello";
return param;
} else {
return nullptr;
}
}
int main() {
std::visit([](auto v) {
std::cout << v << std::endl;
}, func(3));
}
See it up and running on wandbox.
In C++11/14 you can do the same with a tagged union. The basic idea is that what you return contains enough information so that the caller can get out of it the original type.
Alternatives exist.
As an example, you could erase the type and return a pair that contains both the original (erased) variable and a pointer to function filled with an instantiation of a function template. The latter will be able to reconstruct the original variable from a void * for it knows its type.
Well, pretty much a great machinery you can avoid to use with a tagged union or a std::variant (more or less a type-safe version of a tagged union at the end of the day).
What you're returning is the address of a local variable. That variable goes out of scope when the function returns, meaning that the memory it was using could be reused. Attempting to dereference that pointer (i.e. access the memory it points to) invokes undefined behavior.
Even if you were returning a valid pointer, the fact that your function returns a void * means that any type information regarding what that pointer was pointing to is lost. You could print one or more bytes starting at that address, but it won't tell you what the original type was.
Even if that pointer were valid, you simply can't have enough information to force safely a cast to something and then print it.
No information of its size, no information of its internal layout. So,you simply can not print what's pointed by a void*, unless you have some information prepared by hand somewhere, and force a static_cast to the known type.
For example:
double x = 1.2;
int y = 5;
int f(void** output) {
static int x;
if ( x++ ) {
*output = &x;
return 1;
}
*output = &y;
return 2;
}
...
void* out;
int r = f(&out);
if ( r == 1 ) cout << *(static_cast<double*>(out));
else if ( r == 2 ) cout << *(static_cast<int*>(out));
I'm using MingW as my compiler. I have declared a variable, strl, but it says that it wasn't declared at the line right under it.
struct idstruct {
char * path;
lua_State **state;
};
idstruct ids[] = {};
int nids = 0;
static char* getPath(lua_State **state) {
std::cout << state;
for (int on = 0; on < nids; on++)
idstruct strl = ids[on];
if (strl.state == state) {
return strl.path;
}
}
}
You've left off a brace on your for loop, so it's just a one-liner, despite your indentation. Thus the variable is not in scope in the if statement below it.
Try this:
for (int on = 0; on < nids; on++) { // add a brace here
idstruct strl = ids[on];
if (strl.state == state) {
return strl.path;
}
} // and here
You're missing a curly brace at the start of your for loop's body. By the time you reach the following if statement, strl has gone out of scope.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Declaring and initializing a variable in a Conditional or Control statement in C++
Instead of this...
int value = get_value();
if ( value > 100 )
{
// Do something with value.
}
... is it possible to reduce the scope of value to only where it is needed:
if ( int value = get_value() > 100 )
{
// Obviously this doesn't work. get_value() > 100 returns true,
// which is implicitly converted to 1 and assigned to value.
}
If you want specific scope for value, you can introduce a scope block.
#include <iostream>
int get_value() {
return 101;
}
int main() {
{
int value = get_value();
if(value > 100)
std::cout << "Hey!";
} //value out of scope
}
Can you declare a variable and compare it within the if() statement? No.
Can you declare a variable and compare it in such a way that the scope is tightly-bound to the if() block? Yes!
You can either declare a variable:
if (int x = 5) {
// lol!
}
or you can do things with one:
int x = foo();
if (x == 5) {
// wahey!
}
You can't do both!
You can cheat a little where the only thing you need to do is compare with true, because the declaration itself evaluates to the value of the new object.
So, if you have:
int foo()
{
return 0;
}
Then this:
if (int x = foo()) {
// never reached
}
is equivalent to:
{
int x = foo();
if (x) {
// never reached
}
}
This final syntax, using a standalone scope block, is also your golden bullet for more complex expressions:
{
int x = foo();
if (x > bar()) {
// wahooza!
}
}
Put it in a function:
void goodName(int value) {
if(value > 100) {
// Do something with value.
}
}
//...
goodName(get_value());
How about using for instead?
for (int value = get_value(); value > 100; value = 0) {
//...
}
If you want to go C++11 on it, you can use a lambda:
[](int value = get_value()) {
if (value > 100) {
//...
std::cout << "value:" << value;
}
}();
Or you could just add an extra set of braces for a nested scope, although it's not exactly pretty:
{
int value = get_value();
if ( value > 100 )
{
// Do something with value.
}
}
//now value is out of scope
You can write a small function which can do the comparison for you and return the value the if comparison returns true, else return 0 to avoid executing the if block:
int greater_than(int right, int left)
{
return left > right ? left : 0;
}
Then use it as:
if ( int value = greater_than(100, get_value()))
{
//wow!
}
Or you can use for as other answer said. Or manually put braces to reduce the scope of the variable.
At any rate, I would not write such code in production code.
Don't write code for machines. Write code for humans. Machines will understand anything as long as you follow their grammar; humans understand what is readable to them. So readability should be your priority over unnecessary scoping.
In this particular case, you can bodge it:
if (int value = (get_value() > 100 ? get_value() : 0)) {
...
}
I don't really recommend it, though. It doesn't work for all possible tests that you might want to perform, and it calls get_value() twice.