How are arrays scoped in C? When do they ever get destroyed? (Note, also talk about if they can be passed even in p_threads)
They're scoped just like normal variables:
// in a function
int arrayA[300];
{
float arrayB[100];
// arrayA and arrayB available here
}
// arrayB out of scope, inaccessible.
// arrayA still available.
If you were to pass the array to a function, it would be valid as long as the array was still in scope at the calling site.
Arrays are scoped like any other primitive, struct or union. Nothing ever gets destroyed in C, though arrays can go out of scope.
Also, just like other types, arrays can be allocated on the heap by calling malloc() to allocate enough space to hold the desired number of elements, and treating the returned void * as a pointer to the first element. Such an array will be valid until you call free().
WRT Pthreads, again the rules are just as for any other type. If you define an array as an automatic (function-scope) variable, it will go out of scope as soon as the function returns; you cannot safely pass a pointer to such an array to another thread. But if you allocate an array on the heap, then you can pass a pointer to this array (to anything inside the array) anywhere you please, including another thread. Of course, you still need to ensure thread-safe access to the contents using appropriate synchronisation mechanisms.
There's absolutely no difference in scoping and lifetime rules between arrays and any other named entities in C language. I.e. arrays are not special in any way when it comes to scope and lifetime. They behave in that regard just like an ordinary int variable would.
Related
I have a main function and it has global array
unsigned int MainArray [800];
then the program calls function which has local
unsigned int FunctionArray [400];
and I have not enough space in memory.
However the MainArray is not used while the function is called and inside data is not important, also FunctionArray is not required after function is used.
Is any way how FunctionArray can be declared over same memory allocation that the MainArray uses?
When I declare MainArray [800]; inside main then later on other functions can’t access the data.
If you want the data from the mainArray on the later state of the program, i.e, after the execution of the function, then, you can't say the "data of the mainArray is not important while the function is called" because it's important afterwards.
If you are thinking of a way for "FunctionArray can be declared over same memory allocation that the MainArray uses", then even if there WOULD HAVE BEEN a way, the data of mainArray would have been destroyed which you will be needing in later program as you said.
If you don't need the data of main in later state, you can do one thing,
define the array as a pointer outside the main(),
unsigned int * MainArray;
then allocate it dynamically with required size in main(). When the need of the array is finished, just free the memory. The space will be available for farther allocations.
If you need the mainArray after the execution of the function having the functionArray,and not before; just allocate the memory for the mainArray after the function has been executed. and use the local functionArray as the pointer as well, in the function and free the memory before the control gets back from the function. This way your program doesn't occupy the space for the mainArray while executing that function, and when the function is done executing, functionArray is not occupying any space.
But if you need mainArray, both before and after the function execution, I think there is no way you could solve the memory problem..
If you declare a variable inside main(), this doesn't make it a global variable, it's a variable local to main(). Unless you pass a pointer to it around, other functions can't access it.
You seem to ask for a global array. Just declare it outside main() and every function can access it.
Global variables, however, should be carefully considered since they vulnerate the rule of information hiding/encapsulation (that may be the reason nobody taught you they exist), nevertheless there are sometimes good reasons to use them (especially on devices where memory is a scarce resource which seems to be the case for you).
you can use the arrays base pointer to access the array's memory space in other functions.
you declare a array
unsigned int MainArray [800];
Then if you pass MainArray as parameter to function and receive it as,
returnType somefunction(unsigned int * FunctionArray, ...)
{
}
Then you can use the same memory in both main function and array. but in function make sure that you access FunctionArray only within its size limit of 400. This will enable you to access same memory in both functions as array.
You can even allocate memory to arrays dynamically, if they are needed in program in sequence and not at same time. you can use malloc or alloca.
In my window app made in c (using gtk) I first had to make a pointer to pointer that I sent to a callbackfunction.
Since i sent the pointer to another function I thought I had to allocate memory on the heap for it that is:
GtkWidget **entry;
entry = malloc(5 * sizeof(GtkWidget));
entry[0] = entry_a;
entry[1] = entry_s;
entry[2] = entry_t;
entry[3] = entry_v;
entry[4] = entry_r;
the GtkWidget variable is a local variable
But someone told my that this is not neccessary since it could be declared as static instead
static GtkWidget *entry[5];
correct - the program works using a static GtkVidget-pointer instead. My question is why and what does this static mean in this context?
All variables with a static storage class will have a program execution lifetime and internal linkage; its scope, however, depends on where it is declared.
To address the question you asked, whether to use a static array or mallocing an array is really something that must determined on a case by case basis. For the most part, however, memory is cheap, so you shouldn't have to worry about performance issues one way or the other, unless your array size becomes excessive (an int array size of 5 is rather insignificant). Protecting the integrity of an array is much more of a concern. That is why, as a rule of thumb, you should make a variable's scope as small as possible.
They do different things.
If you allocate an array (or any object) using malloc, that memory is allocated at run time when malloc is called, and it continue to exist until free it (i.e., pass the pointer value returned by malloc to the free function). (realloc can also deallocate malloced space, but that's not relevant here.)
If you define an array object using the static keyword, then the object exists during the entire run time of your program.
The meaning of the static keyword is different depending on where it appears. On a local declaration (inside a function), it gives the object static storage duration, meaning that it exists for the entire execution of the program rather than being deallocated when the function returns. This means it can retain its previous value across calls to the function. An object defined outside any function already has static storage duration; in that case, the static keyword changes its linkage, so it's not visible from other source files.
Which is better, static allocation or malloc? It's impossible to say without more information.
malloc is more flexible. It will report an allocation failure by returning a null pointer; if you declare a static object that's too big, chances are your program will just crash. For an array of just 5 pointers, though, you probably don't need to worry about that (nevertheless, you should always check the value returned by malloc).
Defining a static object only lets you define a single object for each name. malloc lets you build dynamic structures. It also lets you decide at run time how many elements an array needs.
A third alternative is to define an object locally, inside some function definition, without the static keyword. In that case the object will exist only inside that function (or even inside a block), and will be automatically deallocated when the function returns.
Without knowing what you're going to do with your pointer array, we can't tell you how it should be declared and allocated. If you can declare it as a local variable inside some function, you probably should. If you can't, well, don't.
I'm programming C on a microchip that doesn't support any memory allocation commands, but it does like pointers (of course). So my question is:
Is there a way to define an array within a function, and pass the pointer to that array back to a global variable?
This would be a way to have a dynamic memory use WITHOUT malloc, realloc, or calloc. Essentially stack memory being passed back to global WITHOUT it destroying itself. I'm assuming that the alloc commands are specifically needed to ensure it doesn't get destroyed, but I wanted to check and see if there was a way around this.
Yes you can declare arrays in functions. The memory for the array will be on the call stack - though be careful, no malloc is often accompanied by a small stack.
Yes, you can give the address of a locally declared array to a globally declared pointer.
Yes it can be a handy source of dynamic memory in some circumstances, but whether you are declaring a local array or calling the much maligned alloca function the result it the same.
But, the memory is only safe until you return from the function the array is in, so you can't turn this into a malloc style thing, but rather only generate memory/scratch for your call children.
You would need to define a huge global array to reserve a big chunk of memory then use that array instead. If you prefer you can also write some simple alloc/free function to allocate/free blocks from that array.
Stack memory will be reused by the next function call. So it is not possible for you to keep anything after the function returns. Of course, if you know your function won't return while that variable is used (for example, a local variable of the main function), then it's safe to pass the pointer to that variable around.
You could define the array as static in the function and assign the value to a global pointer. Not sure I would call this a good programming practice.
Note that this only gets you 1 copy of the array so subsequent calls to your function won't create additional instances of your array. In which case I would ask why don't you just make the array global in the first place?
Do you mean something like this?
char* x;
int main(int argc, char** argv) {
static char foo[80];
x = foo;
// ...
}
This puts your buffer in the BSS segment. If you want it to remain on the runtime stack, get rid of the static.
foo has automatic storage (basically, it's size is fixed), but you now have a globally visible pointer to it.
It will hold until main returns, which presumably, is the end of your process and you don't need it anymore.
If you want to have truly dynamic memory, you'll have to write your own memory allocator, as suggested in the comments.
It's possible to store the address of an object with automatic storage duration (your array "on the stack") in a global variable, but this does not in any way increase the lifetime of the object. It still ceases to exist when execution of the block in which it's declared ends. And after it ceases to exist, any further use of the pointer you stored in your global variable would result in undefined behavior.
The main problem is function calls and how calls affect stack. On IBM architecture, simply, current EBP pushed to stack, caller stack frame is saved to EBP and callee parameters pushed to stack(generally). On return pushed EBP is poped and stack allocated parameters could be overwritten by caller, that area is free to use since callee is returned.
When you some how dynamically allocate some space on stack, it's a possibility to overwrite that space somewhere in time at a function call which has some wide veriaty of parameters or recursive calls. This is why all dynamic allocations happens in Heap and heap management is at the hands of operating system. Since malloc (etc) is o.s. wrappers for heap allocations you do not need to worry about that management, o.s. will take it care for you.
If you want to achieve dynamic allocations on stack you need to go with assembly. Make sure allocate enough space before a function call at the caller site and take that space back when caller will be returned to its caller. And that organisation would be a brainfk i guess..
A simple way to allocate memory on the "stack", pass its address to a global memory.
A potential reason to do so would be to create a "State" (Set of data), but to not have to pass it to sub-functions as the nesting could be very deep and stack savings may be had. The price in that multi-threaded applications could not use Function() safely.
Notice that anything that calls Function() should not use State.
static char *State;
static int FunctionFoo_Helper(void) {
if (*State != '\0') {
// Do _something_ more interesting than simply print
printf("%c", *State++);
FunctionFoo_Helper();
}
}
void Function(size_t n) {
char Array[n]; // Variable size array
// As to if the system put this on the stack or elsewhere is system dependent.
Populate Array(Array);
Array[n-1] = '\0';
State = Array;
FunctionFoo_Helper();
}
When using some library functions (e.g. strftime(), strcpy(), MultiByteToWideChar()) that deal with character arrays (instead of std::string's) one has 2 options:
use a fixed size array (e.g. char buffer[256];) which is obviously bad because of the string length limit
use new to allocate required size which is also bad when one wants to create a utility function like this:
char * fun(void)
{
char * array = new char[exact_required_size];
some_function(array);
return array;
}
because the user of such function has to delete the array.
And the 2nd option isn't even always possible if one can't know the exact array size/length before using the problematic function (when one can't predict how long a string the function will return).
The perfect way would be to use std::string since it has variable length and its destructor takes care of deallocating memory but many library functions just don't support std::string (whether they should is another question).
Ok, so what's the problem? Well - how should I use these functions? Use a fixed size array or use new and make the user of my function worry about deallocating memory? Or maybe there actually is a smooth solution I didn't think of?
You can use std::string's data() method to get a pointer to a character array with the same sequence of characters currently contained in the string object. The character pointer returned points to a constant, non-modifiable character array located somewhere in internal memory. You don't need to worry about deallocating the memory referenced by this pointer as the string object's destructor will do so automatically.
But as to your original question: depends on how you want the function to work. If you're modifying a character array that you create within the function, it sounds like you'll need to allocate memory on the heap and return a pointer to it. The user would have to deallocate the memory themselves - there are plenty of standard library functions that work this way.
Alternatively, you could force the user to pass in character pointer as a parameter, which would ensure they've already created the array and know that they will need to deallocate the memory themselves. That method is used even more often and is probably preferable.
I'm reading The C Book to try and get a better foundation in C. While I think I'm generally getting the concept of pointers, one thing sticks out to me is that it seems like it's generalizing whatever it's pointing to into a global variable (e.g. the ability to use pointers to return values from void functions), which naturally carries with it all the attendant dangers, I assume.
Aside from the fact that a pointer references a specific variable or index in an array, what is the difference between a pointer and a global variable?
They're quite different beasts. To better explain, let me define both.
Pointers:
A variable holds some piece of data. A pointer is a type of data that refers to another piece of memory. Think of it as a sign that says "Over there ---->" pointing at an object of some sort. For example, strings in C are just a pointer to a character, and by convention, you know there's more characters following it until a \0 character. C uses pointers extensively, since there's no other mechanism for sharing common information between parts of the program, except for....
Global Variables:
In a program, you have variables in each function. These can be the parameters to the function, and ones defined inside. As well, you have what are known as global variables. These variables store information that all the functions in a file can access. This can be useful to pass things like a global state around, or configuration. For example, you might have one called debug that your code checks before printing some messages, or to store a global state object, like the score in a video game.
What I think is confusing you: Both can be used to share information between parts of code. Because function arguments are passed by value in C, a function can't modify the variables of what calls it. There are two ways to "fix" that problem. The first (and correct) way is to pass a pointer to the variable into the function. That way, the function knows where to modify the parent's variable.
Another approach is to just use a global variable. That way, instead of passing around pointers, they just edit the global variables directly.
So you can use both of them to accomplish the same thing, but how they work is quite seperate. In fact, a global variable can be a pointer.
A global variable is any variable that is accessible in any scope. A pointer is a variable that contains the address where something lives.
They aren't directly related to each other in any way.
A pointer variable can be in global or local scope and can also point to a variable that is in global, local, or no scope (as if it were coming off of the heap or addressing some DIO lines).
There's a huge difference. Aside from the "other" uses of pointers (which include dealing with strings and arrays, and building dynamic data structures like trees and linked lists), using a pointer to give another function access to a local variable is much more flexible and controlled than sharing a global variable between these two functions.
Firstly, it allows the called function to be provided access to different variables at different times. Think how much more laborious it would be to use scanf() if it always saved its results into the same global variables.
Secondly, passing a pointer to another function makes you much more aware of the fact that that function will be able to modify the object. If you use a global variable for the same purpose, it is easy to forget which functions modify the global and which do not.
Thirdly, global variables consume memory for the life of your program. Local variables are released when their containing function ends, and dynamically-allocated data is released when it is freed. So global variables can at times be a considerable waste of memory.
Using pointers leads to the danger of referring to variables that no longer exist, so care has to be taken. But this is most often a problem when there are complicated global or long-lived data structures which in itself is often a design weakness.
Globals just get in the way of good, modular program design and pointers often provide a better way to achieve the same things.
"Pointer" is a variable that tells you how to get to a value: it's the address of the value you care about. You dereference it (with *) to get to the value.
"Global" defines the scope of the variable: anywhere in the program can say the name and get the value.
You can have local pointers, or global non-pointers. The concepts are completely orthogonal.
The term pointer refers to a variable's type; it is a variable used to refer to another. The term global refers to a variables scope - i.e. its visibility from any part of a program. Therefore the question is somewhat nonsensical since they refer to different kinds of variable attribute; a pointer variable may in fact have global scope, and so have both attributes simultaneously.
While a pointer may indeed refer to an object that is not directly in scope (which is what I think you are referring to), it still allows restricted control of scope, because the pointer itself has scope (unless of course it is a global pointer!).
Moreover a global variable always has static storage class. Whereas a pointer may refer to a static, dynamic, or automatic variable, and because it is a variable, the pointer itself may be static, or auto, or in the case of a dynamically allocated array of pointers - dynamic also.
I think perhaps that you are considering only a very specific use of pointers when in fact they have far greater utility and can be used in many ways. For example, you would almost invariably use pointers to implement the links in a linked list data structure; a global variable will not help you do that.
Clifford
Completely different concepts. You can have pointers to both global and local variables. There's nothing associating the two.
Also, from a function, you can certainly return a pointer to a variable scoped within that function. But that's a bad idea since the variable existed on the function's stack and now that's gone.