Generally speaking, a pointer's value inside a function in c is local or can be accessed in main through the pointer?
Example code:
size_t *function(int a, int *b)
{
int d;
size_t *array;
b = &d;
//DO STUFF HERE
printf("%d", *b); //This gets printed right
return array;
}
int main()
{
size_t *array2;
int *b;
array2 = function(a, b);
printf("%d", *b); //This gives seg fault
}
Arguments are local variables, so you are not actually assigning to main's pointer, you are just ignoring the value passed as argument and assigning to the local b in function. You need a pointer to pointer int **b argument in order to assign to the b in main.
Also, the assigned address is that of a local variable d, which ceases to exist when function returns so accessing it afterwards through a pointer would be invalid regardless (undefined behaviour, even if it might happen to work before it gets overwritten on the stack).
edit: If your goal is to get the value of d to main, you don't need a pointer in main, so instead of b you can have int d in main and pass its address &d to function (function(a, &d)), then you can assign to main's d in function with *b = d.
In function main you pass the pointer b to function but b is uninitialized (can contain any value):
array2 = function(a, b);
Thefore this makes no sense. Inside function, If you want to modify b you need to instead call function like this:
int b;
array2 = function(a, &b);
The function can now assign to *b.
As Arkku says Arguments are local variables, you can treat the pointer as an address value like 0x7fff13f1ce3c, then it's pretty easy to understand.
typedef address int*
typedef address2 size_t*
size_t *function(int a, address b)
{
int d;
address2 array;
b = &d;
//DO STUFF HERE
printf("%d", *b); //This gets printed right
return array;
}
int main()
{
address2 array2;
address b;
array2 = function(a, b);
printf("%d", *b); //This gives seg fault
}
Change the value of b in function won't influence the value of b in main. As for the array, function will return An address value.
Related
I am refreshing my memory of C, and I wanted to test pointers.
I did this simple program, where I call a function that returns a pointer to the largest integer among it's arguments
int*function_pointer (int a, int b, int c);
int main ()
{
printf("Testing pointers\n");// line 1
int*pointer = pointer_function(10,12,36);
//pointer_function(10,102,36) is assigned to int*pointer
printf("Okay, what now...\n");//line 3
return 0;
}
the pointer function
int*function_pointer (int a, int b, int c)
{
int x;
int*ptr = &x;
//initially ptr points to the address of x
if(a > b)
{
if(a > c)
{
printf("a is the greatest\n);
ptr = &a;
}
}
if(b > a)
{
if(b > c)
{
printf("b is the greatest\n");
ptr = &b;
//b is 102, so in this scope ptr points to the address of b
}
}
if(c > a)
{
if(c > b)
{
printf("c is the greatest\n");
ptr = &c;
}
}
return ptr;
//function returns the value of ptr which is the address of b
}
at main function function_pointer(10,102,36) is called
inside function_pointer(...), int a, b, c are created for that scope
initially ptr = &x
since b = 102, ptr = &b
the functions returns the value of ptr
at main pointer = ptr, hence pointer = &b
but b is out of scope, and doesn't have any content
so how come *pointer = 102, shouldn't it return a garbage value since b is not withing the scope of the main function
but b is out of scope, and doesn't have any content
Your pointer is technically still valid and it just points to memory area. It your case it, when function_pointer() returns the b still points to memory it was using for local variable (so, in this case on your stack). You should not use the memory any longer, but as memory content your pointer points to is by default not zeroed when no longer used, then you are simply lucky to still have previous value 102 still there, because as your stack did not expand more than since function_pointer() returned as no other code needed to do that.
If you want do to do some tests, you may want to create another function that you call after function_pointer(). If that new function you need to local variables (i. e. array of 150 ints). to make your code to use more stack and overwrite leftovers. Then you will no longer see 102.
I discovered that if you assign a pointer address to another pointer's address in a FUNCTION it won't change the in value in the main,
however by doing the same thing in main, it will change. So what is the reason of this?
void func(int *a, int *b){
b = a;
}
int main(){
int i= 5, k =6, *a=&i, *b=&k;
printf("%d %d\n",*a,*b); //output 5 6
b = a;
printf("%d %d\n",*a,*b); //output 5 5
a=&i;
b=&k;
func(a,b);
printf("%d %d\n",*a,*b); //output 5 6
printf("%d %d\n",*a,*b); //output 5 6
}
In this function
void func(int *a, int *b){
b = a;
}
parameters a and b are local variables of the function. After exiting the function they will be destroyed. The function deals with copies of arguments. If you want that the function would change the original arguments themselves you have to pass pointers to them. For example
void swap(int **a, int **b){
int *tmp = *a;
*a = *b;
*b = tmp;
}
Your function:
void func(int *a, int *b){
b = a;
}
doesn't do anything, it just takes two values representing memory addresses as parameters and assigns one to the other without any external effect whatsoever. It just writes the value of the one to the other (probably not even that, because the compiler will likely detect this is pointless and eliminate it altogether), it doesn't do anything with the information stored at those addresses. You will need to deference the pointer to read or write to the memory address it holds the value of, but in the present form, the function will not assign the pointer to the other, but the value of i to k.
If you want a function to change a parameter outside of it, you should pass by reference, which in C is just pass by pointer, so you need to pass a pointer to the pointer, not the pointer - which will pass a copy of that pointer - the same value, while passing as pointer to pointer will pass the address of the pointer in memory, not the value it holds.
So it should be:
void func(int **a, int **b){
*b = *a;
}
and func(&a,&b) and you will reproduce what you do in main via b = a.
I would just like to confirm that when I have a function of the sort
int subtract(int a, int b)
{
return a-b;
}
I am passing values when i call subtract(3,2) rather than pointers.
Thanks,
Yes you are
a parameter of type int a means pass an integer by value to the function
a parameter of type int* a means pass a a pointer to some integer to the function.
so for this
int subtract(int a, int b)
{
// even if I change a or b in here - the caller will never know about it....
return a-b;
}
you call like this:
int result = substract(2, 1); // note passing values
for pointers
int subtract(int *a, int *b)
{
// if I change the contents of where a or b point the - the caller will know about it....
// if I say *a = 99; then x becomes 99 in the caller (*a means the contents of what 'a' points to)
return *a - *b;
}
you call like this:
int x = 2;
int y = 1;
int result = substract(&x, &y); // '&x means the address of x' or 'a pointer to x'
Yes, C always pass function parameters by value . To pass a pointer you have to specify the star (asterisk) that identify the pointer type.
Bear in mind that C always pass by value function parameters even in the case of a pointer, in that case the address of the pointer is actually copied .
Yes, you are passing values. A pointer would be denoted by an asterisk after the type name and before the variable name.
#include <stdio.h>
#include <stdlib.h>
void foo(int *a, int *b);
void foo(int *a, int *b) {
*a = 5;
*b = 6;
a = b;
}
int main(void) {
int a, b;
foo(&a, &b);
printf("%d, %d", a, b);
return 0;
}
Why a = b (foo) doesn't work? printf outputs "5, 6"
Thank you.
It does work; it just doesn't do what you think it does.
In foo(), a = b changes the pointer a to point to whatever b points to. It has no effect on anything outside of the function; it only changes the pointers.
If you want to change the value of the int pointed to by a to be the same as the value of the int pointed to by b, you need to use *a = *b, similar to how you do the assignments in the function already.
The call to foo() ends with its local variables pointing to the same addres, the one of stored in b. This change is not reflected in main(), the caller.
I you liked to actually do this and make this change pemanent, then you would have to pass a pointer to a pointer to foo() (so you can change them), instead of their simple values:
void foo(int **a, int **b) {
**a = 5;
**b = 6;
*a = *b;
}
I have just observed that your code is incompatible with that modification, anyway, since you cannot change two normal variables to point to each other. You'd have to also modify main() this way:
int main(void) {
int a, b;
int * ptrA = &a;
int * ptrB = &b;
foo(&ptrA, &ptrB);
printf("%d, %d (%d, %d)", *ptrA, *ptrB, a, b);
return 0;
}
Using a pseudo-memory map,
In main(),
a b
--------------
| 5 | 6 | <- data
--------------
[1000] [1004] <- address
In the function foo(),
a b ( local to foo(), different from the a & b in main() )
----------------
| 1000 | 1004 | <- data
----------------
[2000] [2004] <- address
So, when in foo()'s scope,
*a = 5; // store 5 in int variable a
*b = 6; // store 6 in int variable b
a = b; // copies contents of pointer variable b to a
So the final map in foo()'s scope is:
a b
----------------
| 1004 | 1004 | <- data
----------------
[2000] [2004] <- address
In foo, a and b are separate local variables. Setting them to have the same value has no effect on the previous values - the last line of foo currently does nothing, basically.
Within foo, a is initially a pointer to the same location as a in main, and b is a pointer to the same location as b in main. The last line just makes the value of a in foo the same as b - namely a pointer to the same location as b in main. So if you add a line
*a = 7;
at the end of foo, then you'd see output of "5, 7".
(Your code would definitely be easier to talk about if you used different variable names in main and foo, by the way.)
If you're trying to make a and b within main "aliased" to each other, you're not going to be successful. They're separate local variables on the stack, and will remain so. You can't make the stack "shrink" to alias the two, whatever you do.
I'm not sure what you're going after... if it's to get a and b to contain the same value, try *a = *b.
Because when foo is called, the values of the pointers are copied into the function. If you want to change the values of the pointers themselves, you need to pass a pointer to a pointer into the function.
a and b are local to the function foo (they are on the stack), when program returns from the function data on the stack is lost. when you assign b to a, you are only modifying memory addresses on the stack, not their values.
I'm new to C and still trying to grasp the concept of pointers. I know how to write a swap function that works...I'm more concerned as to why this particular one doesn't.
void swap(int* a, int* b)
{
int* temp = a;
a = b;
b = temp;
}
int main()
{
int x = 5, y = 10;
int *a = &x, *b = &y;
swap(a, b);
printf(ā%d %d\nā), *a, *b);
}
You're missing *s in the swap function. Try:
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
That way, instead of just swapping the pointers, you're swapping the ints that the pointers are pointing to.
Your swap() function does work, after a fashion - it swaps the values of the variables a and b that are local to swap(). Unfortunately, those are distinct from the a and b in main() - so you don't actually see any effect from swapping them.
When thinking about pointers, you need to be clear on a few abstractions.
An object in memory. This can be of any type (and size). An integer object, for example, will occupy 4 bytes in memory (on 32 bit machines). A pointer object will occupy 4 bytes in memory (on 32 bit machines). As should be obvious, the integer object holds integer values; a pointer object holds addresses of other objects.
The C programming language lets symbols (variables) represent these objects in memory. When you declare,
int i;
the symbol (variable) i represents some integer object in memory. More specifically, it represents the value of this object. You can manipulate this value by using i in the program.
&i will give you the address of this object in memory.
A pointer object can hold the address of another object. You declare a pointer object by using the syntax,
int* ptr;
Just like other variables, the pointer variable represents the value of an object, a pointer object. This value just happens to be an address of some other object. You set the value of a pointer object like so,
ptr = &i;
Now, when you say ptr in the program, you are referring to its value, which is the address of i. But if you say *ptr, you are referring to not the value of ptr, but rather the value of the object whose address is in ptr i.e. i.
The problem with your swap function is that you are swapping values of pointers, not the values of objects that these pointers hold addresses for. To get to the values of objects, you would have to use *ptr.
C is a pass-by-value language. Your swap routine doesn't dereference the pointers passed to it, so from main's perspective nothing has happened.
The pointers are passed by value. This means a & b are still a and b when the come back from the function;
try something like this
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
The right way to do it:
void swap(int* a, int* b)
{
int temp = *a; // Temp is set to the value stored at a (5)
*a = *b; // value stored at a is changed to the value stored at b (10)
*b = temp; // value stored in address b is changed to 5.
}
It does swap. It swaps local pointers a and b inside swap function. It swaps them perfectly fine, as it should.
If you want to swap the values these pointers are pointing to, you should re-implement your swap function accordingly, i.e. make it swap the pointed values, not the pointers.
Umm maybe using this
void swap(int** a, int** b)
{
int** temp = a;
a = b;
b = temp;
}
int main()
{
int x = 5, y = 10;
int *a = &x, *b = &y;
swap(&a, &b);
printf(ā%d %d\nā), *a, *b);
}
Without using a third variable (temp)
void swap(int* a,int* b)
{
// a = 10, b = 5;
*a = *a + *b; // a now becomes 15
*b = *a - *b; // b becomes 10
*a = *a - *b; // a becomes 5
}
zildjohn1's answer is the easiest and clearest way to do it. However if you insist on swapping the pointers, then you have to pass the pointer to the pointer because the pointer itself is passed by value.
You need to send the address of a and b for swap function so while calling swap function you must call ass swap (&a,&b)
So that you pass the address, and alter the address
#define SWAP(a,b) ((a)=(b)+(a),(b)=(a)-(b),(a)=(a)-(b))
Works good.