I have a function that has a variable called static const int initial_var = some_var so that on subsequent runs to the function, initial_var is guaranteed to not change. The issue is however the function may be called for different some_vars and because initial_var is used in calculations, this can screw things up.
func() is meant to operate on DIFFERENT variables, all named some_var. Their state needs to be remembered so I use a static const variable, but that will only remember the state for ONE variable.
void func()
{
static const int initial_var = some_var;
some_var = initial_var; // This is the part where things may screw up if some_var
// is a different variable
}
What's an elegant way to fix this?
You say you need "Their state needs to be remembered" so you can just put them in an array.
int array[10]; // 10 elements.
int count = 0;
void storeVariable(int temp)
{
array[count] = temp;
count++;
// Reset if full.
if(count >= 10)
count = 0;
}
That seems fairly simple enough.
Related
I am writing a toy compiler, which compile a c/c++ like language to c++.
I am using bison, but in this structure is hard to handle when variable became out of scope.
In the source lanugage in the whole main function there can be only one variable with the same name, it is good, but there is a problem what I cannot solve.
I cannot make c++ code like this, because c++ compiler throw semantical error:
'var' was not declared in this scope.
int main()
{
if (true)
{
int var = 4;
}
if (true)
{
var = 5;
}
}
The source language has while, if and if/else statements.
I have to throw semantical error if a declared variable is assinged in out of scope.
For example:
This should be semantical error, so I cannot generetad this code:
int main()
{
while(0)
{
int var = 1;
}
if (1)
{
var = 2;
}
}
This also have to be semantical error:
int main()
{
if (0)
{
int var = 1;
}
else
{
if (1)
{
var = 5;
}
}
}
And this is allowed, I can generate this code:
int main()
{
if (0)
{
}
else
{
int var = 1;
if (1)
{
while (0)
{
while (0)
{
var = 2;
}
}
}
}
}
I tried lot of things, but I cannot solve when there is nested if, if/else or while.
I read tons of tutorials about symbol table, but none of them can explain properly how to manage a variable if it is become out of scope.
If you familiar with this topic and with bison, please do not just give me hints, like "use stack, and mark a variable if it become out of scope". I found lot of article about it.
Instead of please give me pseudocode or concrate implementation sketch.
I think it cannot be so much difficult, because in the whole main function there can be one variable with the same name as I wrote.
Symbol table:
struct SymbolType
{
int lineNumber;
std::string identifier;
int identifierValue;
Type type;
int functionArgumentNumber;
Type functionReturnType;
Type markType;
bool outOfScope;
};
class Symbol
{
public:
void AddVariable(int _lineNumber, std::string _identifier, int _identifierValue, Type _type, int _functionArgumentNumber, Type _functionReturnType, Type _markType, bool _outOfScope);
void AddMarker(int _lineNumber, std::string _scopeName, Type _markType);
bool FindVariable(std::string _identifier);
int FindVariableValue(std::string _identifier);
void Remove();
void Print();
std::vector<SymbolType> symbolTable;
private:
int lineNumber;
std::string identifier;
int identifierValue;
Type type;
int functionArgumentNumber;
Type functionReturnType;
Type markType;
bool outOfScope;
};
Now let's assume the following: While you are in a nested scope you cannot add a variable to a parent scope. So we can work e.g. with a stack like structure (push/pop at the end only suffices, but with read access to all entries – the latter requirement disqualifying std::stack, so we'd operate e.g. on std::vector instead).
Encountering the declaration of a new variable:Run up the entire stack to see if that variable exists already. If so, issue an error ('duplicate declaration/definition').
Encountering accessing a variable: Run up the entire stack to see if that variable exists; if not, issue an error ('not declared/defined' – I wouldn't differentiate between the variable not having been defined ever or having left the scope).
On leaving a scope, run up the stack and remove any variable that resides in that scope.
To be able to do 3. you have (at least) two options:
With every stack entry provide an identifier for the respective scope, could be simple counter. Then delete all those variables that have the same counter value. If you fear the counter might overflow, then reduce it by 1 as well (then it would always represent current scope depths).
Have a sentinel type – that one would be pushed to the stack on opening a new scope, compare unequal to any variable name, and on leaving a scope you'd delete all variables until you encounter the sentinel – and the sentinel itself.
This processing makes your outOfScope member obsolete.
Your addVariable function takes too many parameters, by the way – why should a variable need a return type, for instance???
I recommend adding multiple functions for every specific semantic type your language might provide (addVariable, addFunction, ...). Each function accepts what actually is necessary to be configurable and sets the rest to appropriate defaults (e.g. Type to Function within addFunction).
Edit – processing the example from your comment:
while(condition)
{ // opens a new scope:
// either place a sentinel or increment the counter (scope depth)
int var = 1; // push an entry onto the stack
// (with current counter value, if not using sentinels)
if (true)
{ // again a new scope, see above
var = 2; // finds 'var' on the stack, so fine
} // closes a scope:
// either you find immediately the sentinel, pop it from the stack
// and are done
//
// or you discover 'var' having a counter value less than current
// counter so you are done as well
} // closing next scope:
// either you find 'var', pop it from the stack, then the sentinel,
// pop it as well and are done
//
// or you discover 'var' having same counter value as current one,
// so pop it, then next variable has lower counter value again or the
// stack is empty, thus you decrement the counter and are done again
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 months ago.
I would like to know how I can make a function's variable public to other functions.
Example:
void InHere
{
int one = 1; // I want to be public
}
int main()
{
InHere(); // This will set int one = 1
one = 2; // If the variable is public, I should be able to do this
return 0;
}
Does anyone know how to do this? The only things I find when searching is for classes, as you can see nothing is in a class and I don't want them to be in one.
Any help is really appreciated!
A variable defined locally to a function is generally inaccessible outside that function unless the function explicitly supplies a reference/pointer to that variable.
One option is for the function to explicitly return a reference or pointer to that variable to the caller. That gives undefined behaviour if the variable is not static, as it does not exist after the function returns.
int &InHere()
{
static int one = 1;
return one;
}
void some_other_func()
{
InHere() = 2;
}
This causes undefined behaviour if the variable one is not static since, as far as the program as a whole is concerned, the variable only comes into existence whes InHere() is called and ceases to exist as it returns (so the caller receives a dangling reference - a reference to something that no longer exists).
Another option is for the function to pass a pointer or reference to the variable as an argument to another function.
void do_something(int &variable)
{
variable = 2;
}
int InHere()
{
int one = 1;
do_something(one);
std::cout << one << '\n'; // will print 2
}
The downside is that this only provides access to functions CALLED BY InHere(). Although the variable does not need to be static in this case, the variable still ceases to exist as InHere() returns (so if you want to combine option 1 and option 2 in some way, the variable needs to be static)
A third option is to define the variable at file scope, so it has static storage duration (i.e. its lifetime is not related to the function);
int one;
void InHere()
{
one = 1;
}
void another_function()
{
one = 2;
}
int main()
{
InHere();
// one has value 1
some_other_function();
// one has value 2
}
A global variable can be accessed in any function that has visibility of a declaration of the variable. For example, we could do
extern int one; // declaration but not definition of one
int one; // definition of one. This can only appear ONCE into the entire program
void InHere()
{
one = 1;
}
And, in other source file
extern int one; // this provides visibility to one but relies on it
// being defined in another source file
void another_function()
{
one = 2;
}
int main()
{
InHere();
// one has value 1
some_other_function();
// one has value 2
}
Be careful with that though - there are numerous down-sides of global/static variables, to the extent they are usually considered VERY BAD programming technique. Have a look at this link (and pages linked to from there) for a description of some of the problems.
Just set the variable as a global variable. Then you can access it from other functions.
int one;
void InHere()
{
one = 1; // I want to be public
}
int main()
{
InHere(); // This will set int one = 1
one = 2; // If the variable is public, I should be able to do this
return 0;
}
if you want it inside a class, then try the code below
#include <iostream>
using namespace std;
class My_class
{
// private members
public: // public section
// public members, methods or attributes
int one;
void InHere();
};
void My_class::InHere()
{
one = 1; // it is public now
}
int main()
{
My_class obj;
obj.InHere(); // This will set one = 1
cout<<obj.one;
obj.one = 2; // If the variable is public, I should be able to do this
cout<<obj.one;
return 0;
}
void Animation::playAnimation() const
{
static const int index = 0;
const std::string& animationFileName = m_animationContainer.getAnimationName(index);
static const int zOrder = -1;
static bool isLooping = false;
AnimationBank::play(animationFileName,
zOrder,
isLooping);
}
what are pros and cons to define constant local variables as static?
what is an overhead of defining index, zOrder, isLooping as static. Is there any benefit to do this?
In general case if you declare a static variable inside of a function then it will be initialized during first use. In order to achieve this behavior another global static variable of boolean type will be created by the compiler. It will be initially set to false and then set to true after related static variable is initialized.
In your case there is no point to declare any variables as static.
Yes, you will have a little bit overhead when using static variables in function, since each time your program execute that function it has to check whether these static variables initialized.
Let's start with the easy one.
const:
const doesn't give you any ovehead and the only advantage it give you is the variable can't be changed during its life time. It is interesting because:
Correctness.
If want a that show clearly show what the variable, use const make clear that variable won't/can't be changed.
You may think, why I don't use a #define for example. Well, define will make the compiler replace it to fix values and in some cases it is not and advantage like strings or objects.
Protection.
If someone else qill use your function you make clear this variable can be changed and you protect its value.
Static:
Static give you a overhead because after create the variable for the first time it will exist during the lifetime of your program and the advantage is exactly that. When the variable is create you give it an value. Because it stay alive after that, no matter what happens, it can't get again a value as it the is the first time.
Lets see an example with class.
Suppose you want a class to manager an addition to one int and this int need to accumulate this additions including a new object of this class is created and or destroyed:
#include <iostream>
using namespace std;
class ClassAcInt {
public:
void Print_iVar();
void Add_iVar();
private:
static int iVar;
};
int ClassAcInt::iVar = 10; //iVar = 10
void ClassAcInt::Print_iVar() { //Show iVar
cout << iVar << '\n';
}
void ClassAcInt::Add_iVar() { //Add 1 to iVar
iVar++;
}
int main () {
ClassAcInt* oC1 = new ClassAcInt(); //iVar = 10
oC1->Print_iVar(); //print iVar
oC1->Add_iVar(); //iVar = iVar + 1
oC1->Print_iVar(); //Print iVar
delete oC1; //Bye what we did... Are you sure?
ClassAcInt* oC2 = new ClassAcInt(); //iVar = 10? Are you sure?
oC2->Print_iVar(); //Print iVar.... What a hack!!!!
oC2->Add_iVar(); //iVar = iVAr + 1
oC2->Print_iVar(); //omgosh...
delete oC2;
}
You can think the result will be:
10
11
10
11
but 'surprisingly' the result is:
10
11
11
12
The key is the lines static int iVar; and int ClassAcInt::iVar = 10;. Try to suppress the static word and see what happens :)
One can use static array in method for performance if the method frequently called like
static char [1024];
What I want to ask is , if the array size is small like 128 or 64 which one is more advantageous from the samples one and two.
Sample 1:
void foo(){
static mArr char[128];
memset(mArr,0x0,128);//not sure if this line is necessary but I think its a must , any commends appriciated.
}
Sample 2:
void foo(){
char mArr[128];
}
Sample 3:
void foo() {
char mArr[128] = {0};
}
Little actual difference, the latter basicly just adds 128 to the stack-pointer.
if you only must do the clearing at first run, there can be a saving in:
static char mArr[128] = {0} ;
the memset is only necessary if the array is need to be zeroed-out every time, there's nothing 'magic' with static;
Version 1:
void foo() {
static char a[128];
memset(a,0x0,128);
// use a
}
Allocates a on the heap and provides memory which is persistent over all function calls. a works a bit like a global variable with all the problems of global variables. For example, this version will be problematic if the function is called from multiple threads.
Version 2:
void foo() {
char a[128] = {0};
// use a
}
Allocates a on the stack each time the function is called. ={0} initializes with 0 ( every time the function is called). Use this if you do not need the memory to be persistent over several function calls.
Definitely sample 2 - sample 1 would not compile (first char, then variable name ;)
Anyway, static means the array is set on a fixed position in memory while in sample 2 the array is put on the stack. This is not about advantageous - it's about what you need.
Use 1) if you want to call foo more than once and you always want to use the same array and it should keep it's contents between the calls (without the memset).
Use 2) if you want to use the array just in this function and have a "fresh" array every time you call it.
You do not need the memset - it would just clear the array every time you call foo. While that may be a good thing, it definitely is pointless in combination with static, except you do:
void foo()
{
static mArr char[128];
static bool firstrun = true;
if(firstrun)
{
memset(mArr,0x0,128);
firstrun = false;
}
}
In this case, firstrun would be used to initialize your function at the first run and leave it as is in the following runs.
For using "static" have a look at this article.
I would choose Sample 1 but you maybe need to reconsider memset.
Lets review these senarios:
a) You need to empty the array each time foo() is called.
b) You do not need to empty the array each time foo() is called.
For a:
void foo()
{
char mArr[128] = {0};
}
For b:
void foo()
{
static mArr[128] = {0};
}
Fairly new programmer here, and an advance apology for silly questions.
I have an int variable in a program that I use to determine what the lengths of my arrays should be in some of my structures. I used to put it in my header as a const int. Now, I want to fork my program to give the variable different values depending on the arguments given in, but keep it read-only after I assign it at run-time.
A few ideas I've had to do this. Is there a preferred way?
Declare a const int * in my header and assigning it to a const int in my main function, but that seems clunky.
Make it a plain int in my main function.
Pass the variable as an argument when the function is called.
Something else I haven't thought of yet.
I'd use a function-static variable and a simple function. Observe:
int GetConstValue(int initialValue = 0)
{
static int theValue = initialValue;
return theValue;
}
Since this is a function-level static variable, it is initialized only the first time through. So the initialValue parameter is useless after the first run of the function. Therefore, all you need to do is ensure that the first call of the function is the one that initializes it.
C++ doesn't have a built-in solution for this, but if you really want to make sure that your int is only assigned once, you can build your own special int class:
class MyConstInt
{
public:
MyConstInt(): assigned(false) {}
MyConstInt& operator=(int v)
{
assert(!assigned);
value = v;
assigned = true;
return *this;
}
operator int() const
{
assert(assigned);
return value;
}
private:
int value;
bool assigned;
};
MyConstInt mi;
// int i = mi; // assertion failure; mi has no value yet
mi = 42;
// mi = 43; // assertion failure; mi already has a value
int* array = new int[mi];
When exactly do you know the correct value? If you read it from a file or whatever, you can just say:
const int n = determine_correct_value();
I'm tempted to say that what you want doesn't make sense. A constant is something that doesn't change its value, not something that maybe changes its value once or twice. If you want a global variable, just make it non-constant.
On the other hand, if you have scope-constant values, you would just declare and initialize them at the same time, following the general C++ guideline to declare as close to the usage site as possible. For example, mark the use of constants in the following local scope:
for (auto it = v.begin(), end = v.end(); it != end; ++it)
{
const Foo & x = *it;
const std::size_t n = x.get_number_of_bars();
// use x and n ...
const bool res = gobble(x, zip(n));
if (res && shmargle(x)) { return 8; }
}
Here the compiler may even choose not to generate any special code for the variables at all if their value is already known through other means.