Pointer modified when passing it as an argument?
Pointer modified when passing it as an argument?
I have a pointer: struct regs *r and pass this pointer as an argument to a function. In this function, the value of r is modified, but when the function returns, the original value of r is still the same. Is this a property of the compiler or a bug in my code?
Candamir
Candamir
Re:Pointer modified when passing it as an argument?
Any changes to arguments are done on a copy of that variable that is made on the stack (optimisations nonewithstanding). Changes done to the thing pointed to are done on the actual thing pointed to as the value of the pointer is not changed.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Pointer modified when passing it as an argument?
in other words, what you pass to a function through an argument in C is _always a value_. even when you have pointers around, you always give the _value_ of the pointer, never the variable itself.
e.g. you have
and you do
all are correct invocation, and the resulting text will be "hhhww". note the construct "(msg+6)" and "("world")" where the value is compiled right before you call the function. How could print_one_char know it now no longer operate from a variable but rather on a computed expression ?
the answer is it doesn't need to care. print_one_char operates on its argument which is placed in a memory location that isn't used for anything else.
If that still seems weird to you, just grab the K&R and a book explaining the stack in assembly, then get a look at how a simple example is compiled into assembly by GCC...
e.g. you have
Code: Select all
void print_one_char(char* str) {
putc(*str); // print first char
str++; // advance pointer to next char
}
Code: Select all
char* msg="hello world";
print_one_char(msg); print_one_char(msg); print_one_char(msg);
print_one_char(msg+6); print_one_char("world");
the answer is it doesn't need to care. print_one_char operates on its argument which is placed in a memory location that isn't used for anything else.
If that still seems weird to you, just grab the K&R and a book explaining the stack in assembly, then get a look at how a simple example is compiled into assembly by GCC...
Re:Pointer modified when passing it as an argument?
Hmm, it seems pretty the same as Java: Primitives in method arguments are modified without changing the original and objects are modified...
(Well, it's more like the other way round: Java is like C )
Thanks,
Candamir
(Well, it's more like the other way round: Java is like C )
Thanks,
Candamir
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Pointer modified when passing it as an argument?
"passing arguments by value" and "passing arguments by variable" are there since the first high-level languages, afaik.
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Pointer modified when passing it as an argument?
That's "passing arguments by reference", ain't it?
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
Re:Pointer modified when passing it as an argument?
Well, if you need to modify the pointer itself (i.e. make it point to another variable) instead of the pointee (the struct), you need to pass a double pointer:
This could be used to implement, for example, PHP-like iteration functions (na?vely and w/o bound checks in this snippet):
Code: Select all
void alterPointer(char** ptr)
{
*ptr = "Another one";
}
int main(void)
{
char* myString = "A string";
cout << myString << endl; // Prints 'A string'
alterPointer(&myString); // Notice the double indirection: &(char*) = char**
cout << myString << endl; // Prints 'Another one'
return 0;
}
Code: Select all
int next(int** ptrToIntArray)
{
*ptrToIntArray++; // Move the array pointer to the next int
return **ptrToIntArray; // Return the now-current element
}
void otherFunc(void)
{
int* arr = new int[5]
// Fill the array
int item = next(&arr); // 1st item
item = next(&arr); // 2ns item
return;
}
Re:Pointer modified when passing it as an argument?
If you use a c++ compiler you can also pass a reference to the pointer:
Code: Select all
void modify(char *&x) {
x = "hello world";
}
int main(...) {
char *t = NULL;
modify(t);
printf("%s", t);
}
Re:Pointer modified when passing it as an argument?
Code: Select all
int next(int** ptrToIntArray)
{
*ptrToIntArray++; // Move the array pointer to the next int
return **ptrToIntArray; // Return the now-current element
}
thus p++ is functionally the same as "int t = p; ++p; return t;", just any current compiler will know to optimize this by reorderoing such that the temp is unneccessary in most cases.
what you want is:
Code: Select all
int next(int** ptrToIntArray)
{
(*ptrToIntArray)++; // Move the array pointer to the next int
return **ptrToIntArray; // Return the now-current element
}
Code: Select all
int next(int** ptrToIntArray)
{
++(*ptrToIntArray); // Move the array pointer to the next int
return **ptrToIntArray; // Return the now-current element
}
Code: Select all
int next(int* &ptrToIntArray)
{
++ptrToIntArray; // Move the array pointer to the next int
return *ptrToIntArray; // Return the now-current element
}
Code: Select all
int next(int*&ptrToIntArray)
{
return *++ptrToIntArray; // Move the array pointer to the next int and Return the now-current element
}
Re:Pointer modified when passing it as an argument?
Well, thanks for your extensive answers. This was indeed one of the problems in my scheduler. However, I think I also have the same problem with my ASM code, but due to the nature of the stack in ASM I think maybe there the situation might be different...
This is my code:
I already tried it out, but didn't quite understand the codes behaviour... IIUC, pop eax should then restore esp to 'something', shouldn't it?
Candamir
PS: Maybe I'm wrong in the first place and all that misses is a mov esp, eax after pop eax...
This is my code:
Code: Select all
irq_common_stub:
pushad
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push eax
mov eax, irq_handler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popad
add esp, 8
iret
Code: Select all
void irq_handler(struct regs *r)
{
r = (struct regs *)something;
...
Candamir
PS: Maybe I'm wrong in the first place and all that misses is a mov esp, eax after pop eax...
Re:Pointer modified when passing it as an argument?
you are indeed right, as the msdn doc states, but then my c++ compiler is quite broken (m$vc++ 5), since it allows that kind of construct with the behaviour i described... maybe i should update to vs.net 2005 and vc++ 8.0 (or even get g++ ^_^)proxy wrote:
this example is BROKEN, *p++ does not increment what p points to. ++ has a higher precidence than (yes both versions do) just postfix ++ returns the original value, not the new one.
Re:Pointer modified when passing it as an argument?
Quite apart from anything else, MSVC++ 5 might compile something but it isn't C++. C++ wasn't standardised until after MSVC++6, IIRC. (Although I'm open to correction if I'm as wildly wrong as I may be).Habbit wrote:you are indeed right, as the msdn doc states, but then my c++ compiler is quite broken (m$vc++ 5), since it allows that kind of construct with the behaviour i described... maybe i should update to vs.net 2005 and vc++ 8.0 (or even get g++ ^_^)
Regards,
Angus [Óengus] 'Midas' Lepper
Angus [Óengus] 'Midas' Lepper
Re:Pointer modified when passing it as an argument?
AFAIK none of the current compilers can be said to compile standard C++ code, as there's lots of things in there that are hard to build into the compiler or that simply aren't used enough to be a priority.
Blatently going against standard operator precedence like that is definately something that needs fixing though.
Blatently going against standard operator precedence like that is definately something that needs fixing though.