C's pointer arithmetic (Was Re: Setting effective UID for a shell script)
>>> execv( argv[1], argv + sizeof( argv[1] ) );
>> Could you explain this? Why would this line be *more* correct than the
precedent?
> The second version makes the pointer arithmetic explicit and has the
> correct type for the second argument. The first involves an implicit
> cast from char* to char**.
Correct.
[snip]
> cast takes place from char* to char**. Now it so happens that argv[2]
> is the beginning of an array pointers which is just argv with the
> first two items in it cut off, which is the array of arguments I want
> the pass to execv. I could make the cast explicit, but gcc is happy
> to do it implicitly, so I let it.
gcc -Wall -ansi -pedantic rules :)
execv (argv[1], (char**) argv[2]);
> Moreover, argv + sizeof (argv[1]) is equal to argv[4] (as sizeof (char*) =
4) ...
> No. If that were so then you could not access the list of arguments
> to a main function as argv[0], argv[1], argv[2] etc. The compiler
> knows that the type of argv is char**, or char*[], an array of
> pointers to chars, and it knows that sizeof( char* ) is 4 (on the
> platforms we're talking about). It is almost an axiom that
> argv[1] == argv[0] + sizeof( argv[0] ), since this is the address of
> the next element in the array. So argv[4] = argv + 4*sizeof( argv[1]).
Wrong. We are talking about pointers, not about integers nor unsigned.
When you write
argv + 1, the compiler will understand : compute the address
of argv, and add one time the size of the type which is pointed by argv.
I remember to you that argv[1] = argv + 1. Brackets are only syntactic
sugar, which allows us not seeing we are dealing with pointer arithmetic.
Examples :
--
corwin@dagobah:/tmp/test$ cat main.cc
#include <iostream>
int
main (int argc, char** argv)
{
std::cout << "argv = " << argv << std::endl
<< "sizeof (argv[1]) = " << sizeof (argv[1]) << std::endl
<< "content = " << *(argv + sizeof (argv[1])) << std::endl;
return 0;
}
[1]+ Done emacs main.cc
corwin@dagobah:/tmp/test$ g++ -Wall -ansi -pedantic --static main.cc
corwin@dagobah:/tmp/test$ ./a.out "first" "second" "third" "lost"
argv = 0xbffffd04
sizeof (argv[1]) = 4
content = lost
corwin@dagobah:/tmp/test$
--
leslie% cat test2.cc
#include <iostream>
int
main (int argc, char** argv)
{
std::cout << "argv = " << argv << std::endl
<< "argv[1] = " << &(argv[1]) << std::endl
<< "argv + 1 = " << argv + 1 << std:: endl
<< "argv + sizeof (char*) = " << argv + sizeof (char*) <<
std::endl;
return 0;
}
leslie% g++ -Wall -ansi -pedantic test2.cc
leslie% ./a.out "one"
argv = 0xbffffbe4
argv[1] = 0xbffffbe8
argv + 1 = 0xbffffbe8
argv + sizeof (char*) = 0xbffffbf4
leslie%
--
That's why Nicos Gollan was perfectly right, if we were on a 64 bits
architecture,
we would have argv + sizeof (char*) = argv + 8 = argv[8]
Regards,
Perceval.
--
To UNSUBSCRIBE, email to debian-user-request@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster@lists.debian.org
Reply to: