C Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me

The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.

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:
  #1  
Old March 26th, 2003, 09:35 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: 11
[c] passing a pointer to pointer to a function (i think)

getting in a muddle with passing pointers to pointers, at least i think that's what i'm getting in a muddle with.

basing my code on this code from the book i'm following:
Code:
...
main (int argc, char *argv[])
{
	...
	...
	while (--argc > 0 && (*++argv)[0] == '-')
		while (c = *++argv[0])
			...
			...


i want to do much the same (roughly/basically) as that but a main difference is, instead of dealing with argc and argv in main, i'm trying to pass them to another function and then use them from that function.

this is a stripped down version of one of my many efforts:

Code:
#include <stdio.h>

void test(int *argc, char **argv)
{
	int c;
	
	printf("function call   ");
	
	(*argc)--;	/* knock the value of argc down 1 (to know when end in main) */
	argv++;		/* intended to step to the next string */
	while(c = *argv++[0])	/* intended to step through chars of string */
		putchar(c);
	
	putchar('\n');
}

main (int argc, char **argv)
{
	while(argc > 0)		/* not call function if no more strings in argv */
		test(&argc, **argv);
}



example of intened result:

enter this on command line:

./a.out 123 45 6789

and the hoped for output from that is:

a function call 123
a function call 45
a function call 6789

i'm sure there's some other flaws (i've tried this many different ways and am going round in circles with it) that's stopping that happening, but the important thing right now i'd like to get sorted is to be able to get into the situation where i can deal with argv in my test function in the same way as the book code deals with argv in it's main code. in other words pass argv to the test function so that in that function it's in the same form as the form as it's in, in the book's main.

at the moment the above code's error is:
passing arg 2 of `test' makes pointer from integer without a cast

another version didn't result in that error but then it didn't seem as if i'd passed argv as i hoped so i'm not sure.

further small question: *argv[] is the same as **argv right? pretty sure it is, just want to check.

any help much 'preciated

[xtra] i've just realised that this test version of the code that i've posted above doesn't allow the argv pointer to increment/remember where it got to in the test function - so it'll always start from the start instead of from where it left off last. but forget that - doesn't matter - it's the **argv passing that's the problem [/xtra]

Last edited by balance : March 26th, 2003 at 10:00 AM.

Reply With Quote
  #2  
Old March 26th, 2003, 10:33 AM
Jason Doucette's Avatar
Jason Doucette Jason Doucette is offline
jasondoucette.com
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Feb 2003
Location: Canada
Posts: 378 Jason Doucette User rank is Private First Class (20 - 50 Reputation Level)Jason Doucette User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 7 h 23 m 8 sec
Reputation Power: 11
Re: [c] passing a pointer to pointer to a function (i think)

After scanning over this really quick:

1. Q: further small question: *argv[] is the same as **argv right?

Yes. Test this out yourself with a program that uses argv properly, and change it, and it'll still work.

2. Your function is defined as:
void test(int *argc, char **argv)
and you call it like so:
test(&argc, **argv);

It wants 1. a pointer to an int and 2. an array of pointers, but you are passing it 1. a pointer to an int and 2. a pointer to a pointer to a type, which is of type array of pointers. Just call the function like:
test(&argc,argv);

I hope I got this right, since I only skimmed over it very quickly.

Last edited by Jason Doucette : March 26th, 2003 at 10:36 AM.

Reply With Quote
  #3  
Old March 26th, 2003, 12:52 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: 11
yup, you're absolutely right. good grief. why didn't i just ask this question earlier? got in a big mess with this.

it's now working nearly completely ok, and that [xtra] bit i added isn't actually the case - it does carry on.

but yes, call the function without any *s with argv. that's the answer i was after. thanks very much

Last edited by balance : March 26th, 2003 at 12:54 PM.

Reply With Quote
  #4  
Old March 26th, 2003, 02:53 PM
Jason Doucette's Avatar
Jason Doucette Jason Doucette is offline
jasondoucette.com
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Feb 2003
Location: Canada
Posts: 378 Jason Doucette User rank is Private First Class (20 - 50 Reputation Level)Jason Doucette User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 7 h 23 m 8 sec
Reputation Power: 11
Re: Re: [c] passing a pointer to pointer to a function (i think)

Quote:
Originally posted by Jason Doucette
...you are passing it 1. a pointer to an int and 2. a pointer to a pointer to a type, which is of type array of pointers.
Actually, I am wrong. You are dereferencing the pointer twice, and this value is what you are passing in. I should avoid answering questions right after I just wake up! The compiler didn't catch this, and explain what was wrong?

Reply With Quote
  #5  
Old March 26th, 2003, 03:03 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: 11
but it works!? in fact that's what i'm going to ask now: how come it works?!...

further confusion on the same thing, but different question.
Code:
#include <stdio.h>

void test(int *argc, char **argv)
{
	char c;
	
	(*argc)--;	/* knock argc down 1 to know when to stop in main */
	argv++;		/* step to the next string */
	
	printf("%d: ", *argc);
	
	while(c = *argv[0]++)	/* step through chars in the string */
		putchar(c);
		
	putchar('\n');
}

main (int argc, char **argv)
{
	while(argc > 1)		/* not call function if no more strings in argv */
		test(&argc, argv);
}


how come this is working? the part i'm talking about is that each time the function test is called the pointer manages to pick up from where it last left off, and i haven't made any concessions for that at all, and yet it is doing that. it's great that it is, but i can't see how or why?

so when it's called with say:

./a.out abc de fghi

the output is:

3: abc
2: de
1: fghi

i thought it would be like this, in an eternal loop:

3: abc
3: abc
3: abc
3: abc
...
...

but it isn't. why does the pointer not need remembering in the function? or how is it getting remembered?

Last edited by balance : March 26th, 2003 at 03:12 PM.

Reply With Quote
  #6  
Old March 26th, 2003, 08:18 PM
Jason Doucette's Avatar
Jason Doucette Jason Doucette is offline
jasondoucette.com
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Feb 2003
Location: Canada
Posts: 378 Jason Doucette User rank is Private First Class (20 - 50 Reputation Level)Jason Doucette User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 7 h 23 m 8 sec
Reputation Power: 11
Sorry, I should have made it clear. I was correct in my answer to what was wrong in your program. But my explanation of what you were passing in was incorrect... the fix for this incorrect parameter which I stated you should try was correct.

Reply With Quote
  #7  
Old March 26th, 2003, 08:21 PM
Jason Doucette's Avatar
Jason Doucette Jason Doucette is offline
jasondoucette.com
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Feb 2003
Location: Canada
Posts: 378 Jason Doucette User rank is Private First Class (20 - 50 Reputation Level)Jason Doucette User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 7 h 23 m 8 sec
Reputation Power: 11
To answer your question:

Quote:
Originally posted by balance
how come it works?!...
The reason it works, is because you are passing in a pointer to argc. So, when you dereference this pointer, you are accessing the original argc (thus, if you change it, the real one changes - there is no other copy of it in the function).

Reply With Quote
  #8  
Old March 26th, 2003, 09:43 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: 11
Quote:
But my explanation of what you were passing in was incorrect...

i see. phew - that was going to throw me into even further confusion

Quote:
The reason it works, is because you are passing in a pointer to argc. So, when you dereference this pointer, you are accessing the original argc (thus, if you change it, the real one changes - there is no other copy of it in the function).

ah but there's a bit more to it than that. yes, i stupidly missed that it won't be an eternal loop because of argc stopping it, but argv manages to step successfully. it doesn't repeat the same line. argc only determines if that function gets called or not. the value in argc is not used to effect the argv pointer at all. not directly in either function. so how does argv manage to pick up from where it got to each time? i think i've worked it out:

the only thing that effects which string argv points to is the argv++; line, hense my confusion on why it's working. argv++; is an accumalative thing so there must be something global/external going on. it must be because argv is viewed to have been defined externally? therefore global. i think that must be it. argv, because it comes from outside main must be an external variable.

but also i've used this code in the thing i want it for, and it *does not remember where it's got to*. when the function's called repeatedly, argv always starts from the start - never moves off the first line. it's the same basic structure of code - the only difference is that the called function (the equivelent of the function 'test' above) is in another file, so argv must be an static external variable. locally global to the file that main is in.

wow, this problem, which is only an exercise from a book, has really had me going in circles thanks for the help

[actualy i'm having doubts about that now - why does argc and argv need to be mentioned in main's arguments. but there must be something global going on. i don't know whatever]

Last edited by balance : March 26th, 2003 at 09:56 PM.

Reply With Quote
  #9  
Old March 26th, 2003, 10:52 PM
3dfxMM 3dfxMM is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2002
Posts: 272 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: 6 Days 17 h 57 m 24 sec
Reputation Power: 17
It doesn't have anything to do with global variables.

What really happens in most environments is this. The entire command line is given to the program as a single string. Before it is passed to main, the string is chopped up like this.

./a.out\0abc\0de\0fghi

In case that isn't clear each part of the command line has the space after it replaced by a '\0'. argv[0] gets the address of "./a.out", argv[1] gets the address of "abc", and so on.

In test() you are using argv[1], also known as *argv after the argv++. You also happen to always be incrementing the value of argv[1] to step through the string. This continues until you hit the '\0' and you fall out of the loop, but not before incrementing argv[1] again which puts it pointing at the next character in the original string. When you come back into test() you once again use argv[1] but it now points to the next string.

I apologize for not being able to make this more clear. It would be a lot easier to see if you step through it in a debugger.

Reply With Quote
  #10  
Old March 27th, 2003, 06:48 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: 11
i understand that the single string entered on the command line gets split by it's spaces and put into seperate strings, argv being an array of pointers to these strings.

the part i do not understand is that the pointer that's being used to step though the different argv strings, it's value is being retained between seperate function calls and i can't see how or why that's happening. (maybe it's something very simple and obvious but i can't see it right now )

obviously, pointers point to things. if you change what a pointer points to within a function, that change will stay with what you've changed, even when the function ends. but..
argv++; /* step to the next string */
..in 'test' doesn't seem to me to increment anything external to 'test', and yet argv's position is mirraculously (to me) retained function call after function call.

as i say, i could easily be missing something obvious and silly - that's usually the case maybe argv++; is changing something external? that would explain it rather than argv being global.


Quote:
When you come back into test() you once again use argv[1] but it now points to the next string.
so it is an external to 'test' variable, therefore an external change? :/

Last edited by balance : March 27th, 2003 at 06:56 AM.

Reply With Quote
  #11  
Old March 27th, 2003, 07:29 AM
3dfxMM 3dfxMM is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2002
Posts: 272 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: 6 Days 17 h 57 m 24 sec
Reputation Power: 17
Incrementing argv in test() isn't what is doing it. Incrementing *argv is where it is happening. Your function doesn't step through the strings. It steps through a single string that just happens to contain all of the strings you are interested in. If the program loader actually created new strings in which to place the command line parameters your code would not work. As long as the new strings weren't adjacent to each other in memory.

Reply With Quote
  #12  
Old March 27th, 2003, 07:58 AM
3dfxMM 3dfxMM is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2002
Posts: 272 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: 6 Days 17 h 57 m 24 sec
Reputation Power: 17
Code:
command line - ./a.out abc de fghi

                 argv
                  /
                 /
          ______/__________________________________
          | argv[0] | argv[1] | argv[2] | argv[3] |
          -----------------------------------------
          /            /          |          |
  _______/___    _____/___     ___|__    ____|____
  | ./a.out |    |  abc  |     | de |    | fghi  |
  -----------    ---------     ------    ---------

In test() you are incrementing test's copy of argv so that argv now
points to argv[1].  You then go through your loop that increments the
value in argv[1] to point to each character successively until you
reach the '\0'.  When your loop is finished argv[1] points to the character
just past the '\0'.  The value in argv[1] that you have been changing is
the value in the original argv[1] since that is the copy that argv points
to.  You then call test() again and once again you use the value in argv[1]
to traverse the string.  argv[1] points to the character just past the '\0'
from the last call to test().  This just happens to be the next parameter.
If you look at the values of argv[1] and argv[2] after the first call to
test() you will see that they are the same.  You continue with this process
until you have processed all of the parameters.  I think the part that you
are missing is that you never actually traverse the list of parameters.  If
the program loader actually placed the parameters in non-adjacent memory
locations you would see that your code would only correctly print out the
first one.

Reply With Quote
  #13  
Old March 27th, 2003, 08:29 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: 11
Quote:
Incrementing *argv is where it is happening.

which is external to test rather than internal hense it's continued existence. right.
Quote:
Your function doesn't step through the strings. It steps through a single string that just happens to contain all of the strings you are interested in.

right. i see. that is a very important point that i'd missed.

ok, thanks for your explenation. - this has caused me the most trouble so far, in c, for some reason. thanks.


oh, you've posted further explenation - great. haven't digested it yet. this was in response to the previous one

Last edited by balance : March 27th, 2003 at 08:32 AM.

Reply With Quote
  #14  
Old March 27th, 2003, 08:50 AM
Jason Doucette's Avatar
Jason Doucette Jason Doucette is offline
jasondoucette.com
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Feb 2003
Location: Canada
Posts: 378 Jason Doucette User rank is Private First Class (20 - 50 Reputation Level)Jason Doucette User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 7 h 23 m 8 sec
Reputation Power: 11
Just as you were changing the variable argc outside of the function test() from within the function test(), you are doing the same thing with the strings pointed to by argv (the array of pointers to char). (It may make more sense to you to use this notation:
int main (int argc, char *argv[])
so you can easily see that it is an array of pointers to char.)

3dfxMM mentioned this here:

Quote:
Originally posted by 3dfxMM
... The value in argv[1] that you have been changing is
the value in the original argv[1] since that is the copy that argv points to....

Remember that arrays are passed into function as pointers (which you are doing explicitly, since you use the notation char **argv), but all that is passed in is a single pointer. As soon as you dereference this pointer, you are accessing the same data as the original pointer.

I just wanted to make sure you understood this, because this can cause tons of problems and headaches if you don't understand.

Reply With Quote
  #15  
Old March 27th, 2003, 12:25 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: 11
yup, the fact that the strings in this are actually best looked at as *a* string. multidimensional array is a pretty misleading phrase/concept in this situation - not helpful at all.

(this is *the* key one: )
also the fact that argv++, which amounts to argv[1], all the time, repeatedly, in test(), is being used to store the pointer throughout the whole thing.
(the stepping always starting off from the same place that kept confusing me, is here - but it's actually good that it's always the same place! quite amazing luck that.)

those 2 main points i failed to get, especially the second one, even though they'd been pointed out to me several times!

it is amazing the code worked seeing as i didn't have a clue what was actually happening.

so at last i think i can finally say i understand it thanks v. much to both of you for your various replies.

phew.

Last edited by balance : March 27th, 2003 at 12:28 PM.

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesC Programming > [c] passing a pointer to pointer to a function (i think)

Developer Shed Advertisers and Affiliates



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

Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 


Powered by: vBulletin Version 3.0.5
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.

© 2003-2013 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap