I wrote this simple function in C to swap the Value in 2 addresses in memory:
void pointersswap (int *ptr1, int *ptr2)
{
*ptr1 = *ptr1*(*ptr2);
*ptr2 = *ptr1/(*ptr2);
*ptr1 = *ptr1/(*ptr2);
}
I've been told there is an "edge case" that this program can encounter.
You can assume the input is correct (ptr1 and ptr2 actually hold address values and these addresses point to the memory where there's 2 ints which aren't 0). Math always checks out, even if either dereferenced pointer holds a negative number, or both are negative, or fractions.
For reference, this code Shouldn't have the same issue / edge case:
void pointersswap (int *ptr1, int *ptr2)
{
int temp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = temp;
}
What am I missing? are there really any limitations / edge cases in the first function?
Small clarification: assume there's not overflow / loss of information.
Firstly, "expressions" like *ptr1/*ptr2 won't work because /* is interpreted as the beginning of comments in C.
After replacing /* with / *, there are (at least) two cases in which the function won't work:
When the multiplication overflows.
When pointers to the same variable is passed to both a and b.
#include <stdio.h>
void pointersswap (int *ptr1, int *ptr2)
{
*ptr1 = *ptr1*(*ptr2);
*ptr2 = *ptr1/ *ptr2;
*ptr1 = *ptr1/ *ptr2;
}
int main(void) {
int a, b;
a = 999999; b = 888888;
printf("before: a = %d, b = %d\n", a, b);
pointersswap(&a, &b);
printf("after ; a = %d, b = %d\n", a, b);
a = 12345;
printf("before: a = %d\n", a);
pointersswap(&a, &a);
printf("after : a = %d\n", a);
return 0;
}
Output:
before: a = 999999, b = 888888
after ; a = 891245, b = -192
before: a = 12345
after : a = 1
I have been mislead, and so I mislead anyone who tried answering my question and for that I apologize. The two codes had the same edge case, which was that both pointers point to the same address, like MikeCAT suggested in his answer.
So basically I'd like to sum two numbers and return their value while using a void function in C. I know this is easy peasy by using a normal function returning an int or a numeric type but I wanna work on my pointer knowledge.
I tried creating a pointer inside main() and then passing it as an argument to the void function. Then I calculated my sum in a new int variable and assigned the pointer to point to that specific variable. The problem is I can't "retrieve" it or "find" that area of memory in the main function.
Here's what I've tried:
void testFunction(int a,int b, int *x)
{
int c=a+b;
x=&c;
}
int main()
{
int n1=7;
int n2=90;
int *pointerParam;
testFunction(n1, n2, pointerParam);
printf("Value of pointer is %d\n", *pointerParam);
}
It just exits with an error code, it does nothing. If I try to printf *x inside the function, it does work so I know that part at least works.
Any help would be greatly appreciated!
There are multiple problems with the code as it is shown.
The main problem is probably that you misunderstand how emulation of pass-by-reference works in C.
For it to work you need to pass a pointer to the variable that should be set. This is done using the pointer-to operator &. You also need to dereference the pointer, to set the variable the pointer is pointing to.
Putting it together your program should look something like this (simplified):
void testFunction(int a,int b, int *x)
{
// Assign to where `x` is pointing
*x = a + b;
}
int main(void)
{
int n1 = 7;
int n2 = 90;
int result; // Where the result should be written
// Pass a pointer to the `result` variable, so the function can write to it
testFunction(n1, n2, &result);
}
I will show you a program that is no more than a set of printf() and your function. Maybe the program's output helps in showing these pointers, arrays and integers things.
The example
Consider these variables
int n[4] = {10, 20, -30, -40};
int v1 = 0;
int v2 = 0;
int* a_pointer = NULL;
int* is a pointer to an int, that's the meaning of the asterisk in the declaration. In this context the asterisk is called the dereference operator or the indirection operator. But the asterisk also is the multiplication operator in C. ;)
Now a_pointer points to nothing, the meaning of the NULL.
But a_pointer is there to hold an address of something, of an int. The way of getting such address of something is the address of operator, the &, that also has an alternate life as the bitwise and operator in C. Things of life.
In printf() the %p specifier shows an address. This
printf("\naddress of v1 is %p\n", &v1);
printf("address of v2 is %p\n", &v2);
printf("address of array n[0] is %p\n", n);
printf("address of array n[0] is %p\n", 1 + n);
printf("address of array n[0] is %p\n", 2 + n);
printf("address of array n[0] is %p\n\n", 3 + n);
shows (in a 32-bits compilation)
address of v1 is 008FFDA0
address of v2 is 008FFD9C
address of array n[0] is 008FFDA4
address of array n[1] is 008FFDA8
address of array n[2] is 008FFDAC
address of array n[3] is 008FFDB0
And you will see the reason the program prints these lines in the code below...
This line
a_pointer = &v1;
takes the address of v1 and assign it to the pointer a_pointer.
Now a_pointer is pointing to something, to v1, and you can use it in your function. These lines are equivalent
testFunction(n[0], n[3], &v1);
and
testFunction(n[0], n[3], a_pointer);
In these lines
testFunction(n[0], n[3], &v1);
printf("n[0] = %d, n[3] = %d, sum in v1 is %d\n", n[0], n[3], v1);
printf(
"p points to v1. value is %4d, address is %p\n\n", *a_pointer,
a_pointer);
you see the use of the pointer to access the value it points to, using the dereference operator in the printf().
Follow the program along to see a few uses of this.
In particular, see these lines
a_pointer = n + 3;
printf(
"\np points now to n[3]. value is %4d, address is %p\n",
*a_pointer, a_pointer);
to see the thing C is made for: address memory easily. n is int[4], an array of int. a_pointer is a pointer to int. And the language knows that when you write a_pointer = n + 3 that it needs to add to the address of n, an int[], the size of 3 int variables, and assign it to the pointer, so *a_pointer is n[3]and it is used to call testFunction() in
testFunction(n[1], n[2], n + 3);
program output
n[] is [10,20,-30,-40], v1 is 0 v2 is 0
address of v1 is 00CFFA9C
address of v2 is 00CFFA98
address of array n[0] is 00CFFAA0
address of array n[1] is 00CFFAA4
address of array n[2] is 00CFFAA8
address of array n[3] is 00CFFAAC
n[0] = 10, n[3] = -40, sum in v1 is -30
p points to v1. value is -30, address is 00CFFA9C
p now points to v2. value is 0, address is 00CFFA98
n[0] = 10, n[1] = 20, sum in v2 is 30
n[] is [10,20,-30,-40], v1 is -30 v2 is 30
p now points to v1. value is -30, address is 00CFFA9C
n[] is [10,20,-30,-40], v1 is -30 v2 is 30
now makes n[3] = n[1] + n[2] using testFunction()
n[] is [10,20,-30,-10], v1 is -30 v2 is 30
p points now to n[3]. value is -10, address is 00CFFAAC
the code
#include <stdio.h>
show(int[4], int, int);
void testFunction(int, int, int*);
int main(void)
{
int n[4] = {10, 20, -30, -40};
int v1 = 0;
int v2 = 0;
int* a_pointer = NULL;
show(n, v1, v2);
printf("\naddress of v1 is %p\n", &v1);
printf("address of v2 is %p\n", &v2);
printf("address of array n[0] is %p\n", n);
printf("address of array n[1] is %p\n", 1 + n);
printf("address of array n[2] is %p\n", 2 + n);
printf("address of array n[3] is %p\n\n", 3 + n);
a_pointer = &v1;
testFunction(n[0], n[3], &v1);
printf("n[0] = %d, n[3] = %d, sum in v1 is %d\n", n[0], n[3], v1);
printf(
"p points to v1. value is %4d, address is %p\n\n", *a_pointer,
a_pointer);
a_pointer = &v2;
printf(
"p now points to v2. value is %4d, address is %p\n", *a_pointer,
a_pointer);
testFunction(n[0], n[1], &v2);
printf("n[0] = %d, n[1] = %d, sum in v2 is %d\n", n[0], n[1], v2);
show(n, v1, v2);
a_pointer = &v1;
printf(
"\np now points to v1. value is %4d, address is %p\n", *a_pointer,
a_pointer);
show(n, v1, v2);
printf("\nnow makes n[3] = n[1] + n[2] using testFunction()\n");
testFunction(n[1], n[2], n + 3);
show(n, v1, v2);
a_pointer = n + 3;
printf(
"\np points now to n[3]. value is %4d, address is %p\n",
*a_pointer, a_pointer);
return 0;
};
show(int n[4], int v1, int v2)
{
printf(
"n[] is [%d,%d,%d,%d], v1 is %d v2 is %d\n", n[0], n[1], n[2],
n[3], v1, v2);
};
void testFunction(int a, int b, int* sum)
{
*sum = a + b;
return;
}
I will not go into religious discussions here, but you may find easier to understand the meaning of the declarions if you write
int* some_int = NULL;
instead of
int *some_int = NULL;
you declare a name, and the name is some_int. The compiler will tell you that some_int is int*, its type. The fact that *some_int is an int is a consequence of the application of an operator to a variable.
You lacked just to understand how pointers are managed, but you were almost correct:
/* this is almost correct, you could have just said: *x = a + b; */
void testFunction(int a,int b, int *x)
{
int c=a+b;
*x=c; /* the pointed to value is what we are assigning */
}
int main()
{
int n1=7;
int n2=90;
int result; /* vvvvvvv this is the important point */
testFunction(n1, n2, &result); /* you pass the address of result as the required pointer */
printf("Value of pointer is %d\n", result);
}
I'm struggling to create a pointer to pointer on the Heap. Here is my code:
double a = 2.289;
double** ptr = (double*) malloc(sizeof(double*));
double*** ptr_to_ptr = (double*) malloc(sizeof(double*));
I want the ptr variable to keep the address of a and ptr_to_prt the address of ptr. How can I then dereference the values. I want to do something like this:
printf("%lf", **ptr_to_ptr);
Thx in advance
this show how to point and check addresses of pointer on the stack
#include <stdio.h>
int main(){
double X = 2.25;
double* pX = &X;
double** ppX = &pX;
printf("Addr X: %8X\n", &X);
printf("Addr pX: %8X\n", &pX);
printf("Addr ppX: %8X\n", &ppX);
printf("Val X: %f", **ppX);
}
and this show how to point and show addresses on the heap
#include <stdio.h>
#include <stdlib.h>
int main(){
double X = 2.25;
double** pX = (double**) malloc(sizeof(double**));
double*** ppX = (double***) malloc(sizeof(double***));
*pX = &X;
*ppX = &*pX;
printf("Addr X: %8X\n", &X);
printf("Addr pX: %8X\n", &*pX);
printf("Addr ppX: %8X\n", &*ppX);
printf("Val X: %f", ***ppX);
}
you will get a space from heap and store address in them so you need pointer to pointer just for save address of 'X'
Edit 1:
for better answer to comment i put code here
below code show use & operator
'&' operator just get address of variable, so *& get value of address that variable
now look at below code bot set value of x and both correct
#include <stdio.h>
int main(){
int X;
*&X = 10;
printf("X: %d\n", X);
X = 20;
printf("X: %d\n", X);
}
You need an extra asterisk to have the correct type:
double a = 2.289;
double** ptr = (double**) malloc(sizeof(double*));
double*** ptr_to_ptr = (double***) malloc(sizeof(double**));
To dereference you will need as many asterisks as the amount of levels you want to go down. See the example:
int x = 5;
int *p = &x;
int **p2 = &p;
printf("%p %p\n",*p2, p); //If you use 1 asterisk you get to p
printf("%d", **p2); // If you use 2 asterisks you get what p points to, which is an int in this case
Trying to double dereference and print them (TOP TWO ARE EXAMPLES):
printf ("a's value = %d \n", a) ;
printf ("a's address = %p \n", &a) ;
printf ("a_ptr_ptr deref'ed defer'ed =d% \n",
What would go after the \n", for a_ptr_ptr deref'ed defer'ed
If you want the address of the address of a, you're going to have to store a's address in a pointer variable, and take the address of that. But having done so, yes, you can double-dereference that pointer with **, and get a's value back. Something like this:
int a = 5;
int *ip = &a;
int **ipp = &ip;
printf("ipp = %p\n", ipp);
printf("*ipp = %p, ip = %p, &a = %p\n", *ipp, ip, &a);
printf("**ipp = %d, *ip = %d\n", **ipp, *ip);
Theoretically you can continue this as long as you like:
int ***ippp = &ipp;
int ****ipppp = &ippp;
int *****ippppp = &ipppp;
printf("*****ippppp = %d\n", *****ippppp);
But by now this is mostly a game; there's no practical use in a real C program for a 5-level pointer, and at some point (after 8 or 10 levels, I think) the compiler's allowed to say "All right, enough, game over!".
In a homework project, I have to subtract the address of one pointer from another.
Here is a piece of code I tried to write to subtract the heap of void* type, from a given metadata address. It's wrong somewhere.
metadata_t* getBuddy(metadata_t* ptr)
{
metadata_t* offset = ptr - (char)heap;
int h = (char)heap;
#ifdef DEBUG
printf("ptr : %p\n", ptr);
printf("heap : %p\n", heap);
printf("offset: %p\n", offset);
printf("char : %d\n", h);
#endif
return NULL;
}
Here is the output I get:
ptr : 0x7fe7b3802440
heap : 0x7fe7b3802200
offset: 0x7fe7b3802440
char : 0
Here is the output I EXPECTED:
ptr : 0x7fe7b3802440
heap : 0x7fe7b3802200
offset: 0x000000000240
char : 0x7fe7b3802200
Questions:
1) Why would the char output be zero? (Is this not what I am doing: casting the a pointer in single bytes, and then storing it into an int)
2) If this is not how you properly do the pointer arithmetic, how else would you accomplish the offset?
Edits:
1) Heap is defined as a int*, I think. This is the given piece of code that returns its value.
#define HEAP_SIZE 0x2000
void *my_sbrk(int increment) {
static char *fake_heap = NULL;
static int current_top_of_heap = 0;
void *ret_val;
if(fake_heap == NULL){
if((fake_heap = calloc(HEAP_SIZE, 1)) == NULL) {
return (void*)-1;
}
}
ret_val=current_top_of_heap+fake_heap;
if ((current_top_of_heap + increment > HEAP_SIZE)
|| (current_top_of_heap+increment < 0)) {
errno=ENOMEM;
return (void*)-1;
}
current_top_of_heap += increment;
return ret_val;
}
Pointer arithmetic only makes sense for a specific type. In this example, the int type is size 4 but the pointer subtraction is only 1.
#include <stdio.h>
int array[2];
int *a, *b;
int main(void){
a = &array [0];
b = &array [1];
printf ("Int size = %d\n", sizeof(int));
printf ("Pointer difference = %d\n", b-a);
return 0;
}
Program output:
Int size = 4
Pointer difference = 1
Pointers arithmetic doesn't support the operation (pointer + pointer). The only operation allowed is (Pointer + Integer) so the result is a pointer.
To get the offset you need to cast both pointers to an integer type. And the resulting value is an integer not a pointer.
Example:
int offset = (int)ptr - (int)heap;
printf("ptr : %p\n", ptr);
printf("heap : %p\n", heap);
printf("offset: %d\n", offset);
Also the value of heap is too much large to be stored in a single byte and that's why casting it into a char type returns the value zero.