It is modifiable, and gdb
with -std=11
shows what happens
ISO C11, the 2011 revision of the ISO C standard. This standard is substantially completely supported’. So, let us safely assume that the gcc compiler supports most of the features proposed by the C11 standard documentation. The option –std=c11 of gcc will compile programs in C11 standard.
argv[]
is just array of string pointers
like arguments of any other function they are
treated as local variables and are modifiable.
Since they belong to main() function they will last until program
exits..
char **argv
(pointer to pointer) and int argc
are arguments to main()
function and thus created on a stack.
If we run this code and stop at breakpoint at main():
:~/proba$ gdb --args proba BBBBBBB CCCCCCC
#include <stdio.h>
int main(int argc, char **argv)
{
char buf[20] = "AAAAAAA";
argv[0] = buf;
return 1;
}
Starting program: /home/drazen/proba/proba BBBBBBB CCCCCCC
Breakpoint 1, main (argc=3, argv=0x7fffffffdef8) at main9.c:5
If we dump stack we see:
(gdb) x/32gx $sp
0x7fffffffddb0: 0x00007fffffffdef8 0x0000000300000000
0x7fffffffddc0: 0x0000000000000000 0x0000000000000000
0x7fffffffddd0: 0x0000000000000000 0x0000000000000000
.......
We recognize value of argv
0x00007fffffffdef8
and value of argc
0x00000003
on top of a stack.
Since we passed one argument argc
is 3 as expected.
But argv
holds address of the array of char pointers.
So at address 0x00007fffffffdef8
is actually address of the first pointer argv[0]
with value 0x00007fffffffe25c
,
what should be an address where program name with absolute path is.
And at address 0x7fffffffdf00
is second pointer argv[1]
with value 0x00007fffffffe275
what should be an address where first program argument is.
And at address 0x7fffffffdf08
is third pointer argv[2]
with value 0x00007fffffffe27d
what should be an address where second program argument is.
We can see that at the stack:
........
0x7fffffffdef0: 0x0000000000000003 0x00007fffffffe25c<argv[0]>
0x7fffffffdf00: 0x00007fffffffe275<argv[1]> 0x00007fffffffe27d<argv[2]>
So argv[0]
holds the address of program name:
(gdb) x/s 0x00007fffffffe25c
0x7fffffffe264: "/home/drazen/proba/proba"
And at address 0x00007fffffffe275
is second argument argv[1]
which holds address of a program argument BBBBBBB
:
(gdb) x/s 0x00007fffffffe275
0x7fffffffe27d: "BBBBBBB"
And at address 0x00007fffffffe27d
is third argument argv[2]
which holds address of a program argument CCCCCCC
:
(gdb) x/s 0x00007fffffffe27d
0x7fffffffe27d: "CCCCCCC"
We see that string literals these char *argv[]
pointers points to are at consecutive addresses:
(gdb) x/3s 0x00007fffffffe25c
0x7fffffffe25c: "/home/drazen/proba/proba"
0x7fffffffe275: "BBBBBBB"
0x7fffffffe27d: "CCCCCCC"
Now let's step few instructions where we initialize local string
variable on stack and reassign pointerargv[0]
:
(gdb) s
6 char buf[20] = "AAAAAAA";
(gdb) s
7 argv[0] = buf;
(gdb) s
8 return 1;
If we dump the stack now we notice it has slightly changed.
We see that local variable buf[]
was initialized on stack too (string AAAAAAA
is HEX 0x0041414141414141
) right after
main()
function arguments:
(gdb) x/32gx $sp
0x7fffffffddb0: 0x00007fffffffdef8 0x0000000300000000
0x7fffffffddc0: 0x0041414141414141 0x0000000000000000
0x7fffffffddd0: 0x0000000000000000 0x5315d27018aa8e00
.....
.....
0x7fffffffdef0: 0x0000000000000003 0x00007fffffffddc0<argv[0]>
0x7fffffffdf00: 0x00007fffffffe275 0x00007fffffffe27d
Value 0x00007fffffffdef8
of argv
hasn't changed, but value of argv[0]
has changed to 0x00007fffffffddc0
:
.....
0x7fffffffdef0: 0x0000000000000003 0x00007fffffffddc0<argv[0]>
0x7fffffffdf00: 0x00007fffffffe275 0x00007fffffffe27d
(gdb) x/s 0x00007fffffffddc0
0x7fffffffddc0: "AAAAAAA"
(gdb) p argv[0]
$1 = 0x7fffffffddc0 "AAAAAAA"
pointer argv[0]
now points to the new memory location where string literal "AAAAAAA" is allocated on a stack.
argv[n]
is non-modifiable but does not provide any justification for that assertion – Emptyargv
can be modified I take that to mean thatargv[n]
can be. (Of course theargv
pointer itself can be modified, it's just a function-local argument.) – Purposiveargc
can be modified, that same "of course" applies to it? I think they're just talking about the local variable, not the pointers. – Headedargv[n]
is not a string; it's a pointer that points to the first character of a string. – Emptyargc
andargv
explicitly at all... – Purposiveargc
andargv
explicitly , but maybe there's historical justification that I'm not aware of. Maybe it's relevant in the case ofmain
being called recursively. – Emptyargv[n]
not be modified. – Acheargv
nor any of pointersargv[x]
differently from any automatic local variables or function arguments created on stack, and thus are modifiable e.g, reassignable. it makes perfectly sense, since C is meant to be powerful and efficient, and with great power comes great responsibility which is placed on programmer. C expects that you know what you are doing and it is fine that way. – Fist