SunQuest
           C Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming LanguagesC Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
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  
Old March 21st, 2003, 05:21 PM
balance balance is offline
.
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2002
Posts: 296 balance User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 6
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.

Reply With Quote
  #2  
Old March 21st, 2003, 06:21 PM
dwise1_aol's Avatar
dwise1_aol dwise1_aol is online now
Contributing User
Dev Shed Expert (3500 - 3999 posts)
 
Join Date: Jan 2003
Location: USA
Posts: 3,803 dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level) 
Time spent in forums: 1 Month 11 h 41 m 43 sec
Reputation Power: 437
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.

Reply With Quote
  #3  
Old March 21st, 2003, 07:38 PM
balance balance is offline
.
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2002
Posts: 296 balance User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 6
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

Reply With Quote
  #4  
Old March 21st, 2003, 10:43 PM
7stud 7stud is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2001
Posts: 1,327 7stud User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 4 h 44 m 50 sec
Reputation Power: 9
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.

Reply With Quote
  #5  
Old March 22nd, 2003, 12:52 AM
dwise1_aol's Avatar
dwise1_aol dwise1_aol is online now
Contributing User
Dev Shed Expert (3500 - 3999 posts)
 
Join Date: Jan 2003
Location: USA
Posts: 3,803 dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level) 
Time spent in forums: 1 Month 11 h 41 m 43 sec
Reputation Power: 437
Quote:
Originally posted by balance
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.


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.

Reply With Quote
  #6  
Old March 22nd, 2003, 06:25 AM
balance balance is offline
.
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2002
Posts: 296 balance User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 6
Quote:
A pointer is an address, so when you pass it to a function, there is no starting up again where you left off.

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:
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.
i'm changing it, so i will
Quote:
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
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.




Quote:
No, I did mean "if (s != NULL)". Look at the logic. If s is a valid address, ..
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.

Reply With Quote
  #7  
Old March 22nd, 2003, 12:35 PM
dwise1_aol's Avatar
dwise1_aol dwise1_aol is online now
Contributing User
Dev Shed Expert (3500 - 3999 posts)
 
Join Date: Jan 2003
Location: USA
Posts: 3,803 dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level) 
Time spent in forums: 1 Month 11 h 41 m 43 sec
Reputation Power: 437
Quote:
Originally posted by balance
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.

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:
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.

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.

Reply With Quote
  #8  
Old March 22nd, 2003, 06:17 PM
balance balance is offline
.
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2002
Posts: 296 balance User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 6
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.

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)

Reply With Quote
  #9  
Old March 22nd, 2003, 09:04 PM
3dfxMM 3dfxMM is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2002
Posts: 266 3dfxMM User rank is Sergeant (500 - 2000 Reputation Level)3dfxMM User rank is Sergeant (500 - 2000 Reputation Level)3dfxMM User rank is Sergeant (500 - 2000 Reputation Level)3dfxMM User rank is Sergeant (500 - 2000 Reputation Level)3dfxMM User rank is Sergeant (500 - 2000 Reputation Level) 
Time spent in forums: 3 Days 19 h 1 m 34 sec
Reputation Power: 12
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.

Reply With Quote
  #10  
Old March 23rd, 2003, 12:34 AM
dwise1_aol's Avatar
dwise1_aol dwise1_aol is online now
Contributing User
Dev Shed Expert (3500 - 3999 posts)
 
Join Date: Jan 2003
Location: USA
Posts: 3,803 dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level) 
Time spent in forums: 1 Month 11 h 41 m 43 sec
Reputation Power: 437
Quote:
Originally posted by balance
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)


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.

Reply With Quote
  #11  
Old March 23rd, 2003, 07:53 AM
balance balance is offline
.
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2002
Posts: 296 balance User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 6
Quote:
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.

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:
You can also initialize a pointer to point to a variable or function

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:
"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.

yup, got ya.

thanks v. much

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesC Programming > pointer values that hang around in functions?


Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump