0

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 ?

stack_A
  • 713
  • 4
  • 13
  • 21
  • 1
    Since `argv[0]` is shorter than 9 bytes, `*argv + 9`, which is equivalent to `&argv[0][9]` invokes undefined behaviour. It happens to not crash (in your case), and whatever is stored there is printed. – Daniel Fischer Jul 12 '13 at 14:26
  • 1
    This code is so broken it hurts my eyes. – ams Jul 12 '13 at 14:28
  • It's just a note, but working as a root user is potentially dangerous. – awesoon Jul 12 '13 at 14:31
  • This will help you further: [Two Dimensional Array Implementation Using Double Pointer](http://stackoverflow.com/questions/13974001/two-dimensional-array-implementation-using-double-pointer) Specially the diagram given by [Mohamed](http://stackoverflow.com/a/13974651/1673391) – Grijesh Chauhan Jul 12 '13 at 16:07

4 Answers4

10

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.

Tom van der Woerdt
  • 29,532
  • 7
  • 72
  • 105
1

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.

tuckermi
  • 839
  • 6
  • 17
1

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 a b c 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.
Jan Spurny
  • 5,219
  • 1
  • 33
  • 47
0

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.

Yury Schkatula
  • 5,291
  • 2
  • 18
  • 42