March 21st, 2003, 05:21 PM
pointer values that hang around in functions?
a very usual thing done with pointers is to pass one that points to an array to a function, and use it within the function to modify the array it points to. obviously wherever the pointer ends up, the actual pointer variable itself gets thrown away at the end of the function. how can you make this pointer variable hang around in the function, so when you call the function again with the same call, it picks up from where it left off? like when you define a static variable in a function, that variable's value stays with the function on successive calls to that function.
March 21st, 2003, 06:21 PM
Kind of like strtok() does, right?
Here's an idea:
1. Define a static variable to store the pointer in between function calls.
2. Pass the pointer to the function, which stores it in that static variable and uses that variable for all the pointer operations in the function. That way, any subsequent changes to the pointer (eg, p++ to step through the array) will be stored in that static variable between calls.
NOTE: If you need to keep track of both the beginning of the array and where you last left off, then you would need two static variables.
3. In subsequent calls to the function, pass an invalid value for the pointer, such as NULL. This will tell the function to use the value(s) stored in the static variable(s).
4. If you want to start working on a different array, then call the function with a valid (eg, non-NULL) value. This will tell the function to load the static variable(s).
Another idea you might want to use, depending on the application, is to make a copy of the array for the function to work on, rather than have it work on the original data. For one thing, it leaves the original data intact and, for another, it protects you from having the function work on data that no longer exists.
void foo(char* s)
static char *p;
if (s != NULL)
p = s;
// process the char array using p
foo(str1); // call foo for the first time & have it work on str1
foo(NULL); // subsequent call to work on str1
foo(NULL); // yet another call to work on str1
foo(str2); // now have foo start working on str2
foo(NULL); // subsequent call to work on str2
foo(NULL); // yet another call to work on str2
strtok() illustrates that idea. It scans the string being tokenized and then, when it finds a delimiter character, it replaces it with a NULL and returns a (char*) to that string. In the meantime, the original string is getting changed. So if you had a need to keep the original string intact, you would have to have made a copy first. Also, you cannot delete that string (eg, free(str) ) nor exit from the function that defines it before you have finished tokenizing it -- I haven't ever tested that, but I'm pretty sure you'd end up trying to tokenize garbage as well as clobbering something in the stack, like a return address.
Hope that helps.
Last edited by dwise1_aol; March 21st, 2003 at 06:27 PM.
March 21st, 2003, 07:38 PM
oh right, i didn't know of strtok()
yeah, that's what i meant. thanks. apart from didn't you mean :
or maybe you didn't? not sure. well that's how i used it in anycase.
if (p == NULL)
p = s;
i thought/hoped there might be a way without using another variable. i really thought this was going to work until i tried it. the function like this:
but the compiler wasn't having any of that. i really thought it would have worked because function parameters and function variables are very similar, but obviously not in this case.
void foo(static char* s)
// process s
not sure about your 2nd solution. first solution seems much better i think - simpler.
March 21st, 2003, 10:43 PM
A pointer is an address, so when you pass it to a function, there is no starting up again where you left off. The next time you call the function, the address you send to the function is the same, so you wouldn't need to make the pointer a static variable. If you were stepping through an array that was pointed to by the pointer, and you wanted to start up at the index position where you left off, then you could declare a static integer variable in your function to retain the index value:
void a_function(int* pnumbers)
static int index_pos = 0;
for(int i=0; i<3; i++)
cout<<*(pnumbers + index_pos + i);
index_pos += 3;
Last edited by 7stud; March 22nd, 2003 at 01:00 AM.
March 22nd, 2003, 12:52 AM
No, I did mean "if (s != NULL)". Look at the logic. If s is a valid address, ie non-NULL, then we do want to use it to start working on a new array. If s is equal to NULL, then we do not want to change the value of p, but rather keep on using it picking up where we left off.
HOWEVER, you did catch a bug there. If we call foo() for the very first time with a pointer value of NULL, then p had never been initialized and we'll undoubtedly get a segmentation error. We have to trap against that, most likely with something like:
Depending on what return value you have foo return, it should indicate that an error was encountered: eg, -1 for int or NULL for a pointer type. Also, even though a static pointer variable should automatically initialize to NULL, I prefer to make those things explicit:
if (p == NULL)
if (s != NULL)
p = s;
Good eye there.
static char *p = NULL;
Last edited by dwise1_aol; March 22nd, 2003 at 12:54 AM.
March 22nd, 2003, 06:25 AM
i know a pointer is an address. if you're stepping that pointer along the array in the funciton then there is starting up from where you left off. all i was after is that the function should retain the pointer value rather discard it, like what static allows with function variables. - which is what i got
i'm changing it, so i will
oh yeah, that's probably better than making a static version of the pointer - it takes less space to store an int than a pointer. that's probably the best way to do it i guess.
oh right. the logic i was using is, if the static internal pointer isn't set yet, make the internal static pointer equal the pointer that's been passed to the function. otherwise don't touch the static internal pointer. i see what you mean - you're checking that the passed pointer is actually a pointer value. well, when i changed it to how i suggested it worked, but then i wasn't testing for valid pointer. but it worked.
static char *p = NULL;
is that ok? because what it looks like to me that you're setting what *p points to, if it points to anything, to NULL, not the pointer p to NULL.
but in anycase, i think the best way to do it is as 7stud mentioned - don't step the actual pointer, use a seperate static int and add it to the pointer that was passed to the function.
March 22nd, 2003, 12:35 PM
Yes, it is, because it is a declaration, not an assignment statement. The static char * part declares the variable p's type while the = NULL part defines the value that it is to be initialized to.
Actually, my own trepidation at such declarations in a function is that the variable would be initialized every time the function is called, but that is only the case with auto variables, not static ones; e.g.:
Yes, that would also work. My approach included the ability to use the function to process several arrays in sequence (ie, when you're done with array1, reinitialize foo's static variable to process array2, then array3, etc.).
char *auto_p = NULL; // auto_p gets initialized to NULL every time foo is called
static char *p = NULL; // p only gets initialized when the program starts up
// and retains its most-recently-assigned value thereafter.
So, you could pass the function the index you want it to start at. If the index is valid ( >= 0 ), then reinitialize your processing at that index. If the index is invalid (e.g., == -1), then continue with the index value in the static variable.
March 22nd, 2003, 06:17 PM
hmm, yup you're right that does seem to be fine, but how come this line in the same place in the code doesn't work then ? :
s being the array pointer passed to the function as in your original code:
static char *p = s;
initializer element is not constant
seems a bit strange that it should work with NULL but not with another address (which is obviously what s is in the case). why does it matter what form the value is in? (just being curious - doesn't matter that much)
March 22nd, 2003, 09:04 PM
I'm not completely sure of this answer but here goes anyway. It would seem that static variables that are initialized in their declaration would have to be done at compile time so they can't use the value of a parameter since that parameter has no value at that time.
March 23rd, 2003, 12:34 AM
Initialization is handled in the start-up code, which ends with a function call to main() -- id est, it's all handled before your code even begins to run.
Therefore, initialization values must be known at compile time. In your example, the variable s will not have a value until [relatively] long after the start-up code has finished running.
The value of NULL is known at compile time, at least after the preprocessor has run. In MinGW, it is defined in stddef.h thus:
#define NULL ((void *)0)
You can also initialize a pointer to point to a variable or function, because that address would be known at compile time. Be advised that "compile time" includes the link step, since the address in question could be in another module and so would have to be fixed up first. But I trust you understood what I meant.
Last edited by dwise1_aol; March 23rd, 2003 at 12:36 AM.
March 23rd, 2003, 07:53 AM
yup, that makes total sense - i never take the compiler errors in properly, but the compiler error and your explanation there makes it clear. it also explains the problem i had with attempting to attach 'static' to the pointer within the function definition line
which resulted in the same error, if i remember correctly.
void foo(static char* s)
// process s
right i was about to say NULL is the only value possible there then, but there's that as you say. i'm just at function pointers in my book - haven't covered them yet.
yup, got ya.
thanks v. much :)