简体   繁体   中英

behaviour of pointer ; char ** argv

when I was testing double pointer behaviour I got a result that I don't understand well.

==> code 1 :

int main (int argc , char **argv)
{

if(*argv+1 ==NULL)
{
    printf("NULL pointer \n");
    exit(0) ;
}
else
{ 
    printf("test double pointer[] : %s \n ",*argv+1);  

}

return(0);
}

====> result 1

root@root:/home/aa/test# ./geip 1255
test double pointer[] : /geip 
root@root:/home/aa/test#

===> code 2 :

int main (int argc , char **argv)
{

if(*argv+9 ==NULL)
{
    printf("NULL pointer \n");
    exit(0) ;
}
else
{ 
    printf("test double pointer[] : %s \n ",*argv+9);
}
 return(0);
 }

==> result 2 :

root@root:/home/aa/test# ./geip 1255
test double pointer[] : 55 
root@root:/home/aa/test#

==> result 3 :

root@root:/home/aa/test# ./geip 
test double pointer[] : ELL=/bin/bash 
root@root:/home/aa/test#

it seems that printf display from n th word (1 and 9) how we can explain this behaviour of pointer ?

You're using it wrong.

*argv+1 will be interpreted as (argv[0])+1 and since argv[0] is "./geip" you get "/geip".

*argv+9 will be interpreted as (argv[0])+9 but since argv[0] only has length 6 the outcome is undefined.

In your case, argv is probably stored as :

.  /  g  e  i  p \0  1  2  5  5 \0
0  1  2  3  4  5  6  7  8  9 10 11

Which explains why +9 gets you "55"

But you should really forget that because it's never going to be useful! This is undefined behavior and should not ever be used.

char **argv is a pointer to a char * (sometimes referred to more simply as a string). You dereference this pointer when you do *argv . The result of this dereference is a char * or in other words it is the address of a char . When you do addition with the result, your code is computing a new address. So, for example while *argv would be the address of the first character in your string, *argv+1 is the address of the second character in your string.

When you add in a number that is longer than the length of your string you are stepping out of "safety". Remember that C will let you do pointer arithmetic that takes you past the end of your string. In your second example you are asking printf to go 9 bytes past the start of *argv and print characters from there to the next \\0 (or NULL) byte. You are effectively reading arbitrary memory from your program's process space, which explains what is being printed.

There are actually more than one problem.

  1. please, please, do not work as a root. Just don't.
  2. your syntax ( *argv + 9 ) means literally: "defeference argv and move pointer 9 chars", and really, if you move 9 characters from ./geip 1255 you'll arrive to 55 . So either use argv[i] ( i = 1..N denotes argument index) or if you want to do it the hard way, you must add parentheses: *(argv + i) .
  3. try to format your code better - it will be more readable not only for stackoverflow guys, but also for you.

For example when you run ./geip abc 123 :

  • argv[0] is string holding program name - ./geip
  • argv[1] is string holding the first argument - a
  • argv[2] is string holding the second argument - b
  • argv[3] is string holding the third argument - c
  • argv[4] is string holding the fourth argument - 123
  • argv[5] is NULL as argc will bw 5 (see comments)
  • argv[>5] is not a good idea, because there are no more arguments. So you better check argc to see how many arguments there are.

You just do a pointer arithmetics: **argv is a pointer to list of pointers *argv is a head of the list

//char **argv is given from outthere
char *p;
p = *argv; // the same as "p = *argv[0]"
for (int i = 0; i < 100) {
  printf("Next: %s\n", p+i);
}

Try to run it and see the dump of memory, from head of the list to next 100 bytes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM