|
|
|||||||||
|
|||||||||
| |||||||||
|
|
|
| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
|
|
Stop making mediocre tutorials.The best tutorials are video! Camtasia Studio makes it easy to create engaging, buzz-building screen videos at any size, in any popular format. Download the free trial!
|
|
#1
|
|||
|
|||
|
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.
|
|
#2
|
||||
|
||||
|
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). E.g.: Code:
void foo(char* s)
{
static char *p;
if (s != NULL)
p = s;
// process the char array using p
}
int main(void)
{
char str1[81];
char str2[81];
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
return 0;
}
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. 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. |
|
#3
|
|||
|
|||
|
oh right, i didn't know of strtok()
yeah, that's what i meant. thanks. apart from didn't you mean : Code:
if (p == NULL)
p = s;
or maybe you didn't? not sure. well that's how i used it in anycase. 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: Code:
void foo(static char* s)
{
// process s
}
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. not sure about your 2nd solution. first solution seems much better i think - simpler. yup, thanks |
|
#4
|
|||
|
|||
|
balance,
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: Code:
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. |
|
#5
|
||||
|
||||
|
Quote:
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: Code:
if (p == NULL)
return;
if (s != NULL)
p = s;
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: Code:
static char *p = NULL; Good eye there. Last edited by dwise1_aol : March 22nd, 2003 at 12:54 AM. |
|
#6
|
||||||
|
||||||
|
Quote:
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 Quote:
Quote:
Quote:
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. |
|
#7
|
||||
|
||||
|
Quote:
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.: Code:
void foo(void)
{
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.
}
Quote:
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.). 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. |
|
#8
|
|||
|
|||
|
Quote:
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 ? : Code:
static char *p = s; s being the array pointer passed to the function as in your original code: 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) |
|
#9
|
|||
|
|||
|
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.
|
|
#10
|
||||
|
||||
|
Quote:
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. |
|
#11
|
|||||
|
|||||
|
Quote:
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 Code:
void foo(static char* s)
{
// process s
}
which resulted in the same error, if i remember correctly. Quote:
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. Quote:
yup, got ya. thanks v. much ![]() |
![]() |
| Viewing: Dev Shed Forums > Programming Languages > C Programming > pointer values that hang around in functions? |
| Thread Tools | Search this Thread |
| Display Modes | Rate This Thread |
|
|