I understand that when you pass by reference through a function in C, the parameters of the function take in the address of the pointer that will be modified. I am extremley boggled on why this example of pass by reference is not working. Can anyone point me in the right direction....
This should output a swap but when i compile the swap does not occur why is this pass by reference not working?
#include <stdio.h>
void swapnum(int *i, int *j) {
int temp = i;
i = j;
j = temp;
}
int main(void) {
int a = 10;
int b = 20;
swapnum(&a, &b);
printf("A is %d and B is %d\n", a, b);
getchar();
getchar();
return 0;
}
You forgot to dereference your pointers inside the function. Thus you end up reassigning the local pointer values rather than changing the actual value being pointed to and it has no effect.
So, use the * dereference operator:
int temp = *i;
*i = *j;
*j = temp;
I'm wondering why you didn't get any compiler warning/error. You need to dereference your reference in the function:
void swapnum(int *i, int *j) {
int temp = *i;
*i = *j;
*j = temp;
}
The reason is i and j inside swapnum() are addresses to original variables when the function is called. So when you use only i or j, you're getting the address of the variable, not the content. Here is an idea of what is going on:
int a = 10;
int b = 20;
-----------------
0x1000 | 10 | <-- a
-----------------
-----------------
0x1004 | 20 | <-- b
-----------------
swapnum(&a, &b);
Then, inside swapnum(int *i, int *j):
-----------------
0x2000 | 0x1000 | <-- i (*i == 10)
-----------------
-----------------
0x2004 | 0x1004 | <-- j (*j == 20)
-----------------
In the swapnum function, you are only assigning the variables i and j which are local to this function. This won't have any effect outside of this function. You should try:
void swapnum(int *i, int *j) {
int temp = *i;
*i = *j;
*j = temp;
}
It's (hopefully) crashing because in this function:
void swapnum(int *i, int *j) {
int temp = i;
i = j;
j = temp;
}
i and j are pointers, and temp is an int. You cannot assign a pointer to an int. If you want to swap the values in i and j do this:
void swapnum(int *i, int *j) {
int temp = *i;
*i = *j;
*j = temp;
}
You want:
void swapnum(int *i, int *j) {
int temp = *i;
*i = *j;
*j = temp;
In swapnum, you are swapping the pointers (which are also int values). Try this instead:
void swapnum(int *i, int *j) {
int temp = *i;
*i = *j;
*j = temp;
}
Your implementation of swapnum() is a bit improper. The function takes 2 (int *) parameters. That is, i and j are integer pointers storing references of a and b. when you do int temp = i; you are actually assigning a pointer to integer variable (which is incorrect) and then instead of swapping the values, the code snippet plays around with addresses. This is what you need
void swapnum(int *i, int *j) {
int temp = *i;
*i = *j;
*j = temp;
}
Related
Why doesn't this program compile with a warning message that "uninitialized pointers were used"? If I change pTemp to an int variable instead of an int pointer variable, is it okay? Please explain why.
void Swap(int *x, int *y) {
int *pTemp;
pTemp = x;
x = y;
y = pTemp;
}
Here would be a simple example of swap without using ptemp as pointer but as simple local int as it would be easier to think. Having c as an int variable is not more right or more wrong, it is just different. If u have a ptemp int, then u should work with the content of the variables, which means that u have to access the addess of &x using *x as i used inside the swap. If u worked with ptemp pointer then u should work by memory addresses which is overkill for this example I think.
#include <stdio.h>
void Swap(int *x, int *y)
{
int c;
c = *x;
*x = *y;
*y = c;
}
int main()
{
printf("Hello World\n");
int x = 3;
int y = 5;
Swap(&x,&y);
printf("X: %d, Y: %d", x,y);
return 0;
}
As posted, the code swaps the values of the function arguments, which has no effect outside the function. You should instead dereference the pointers to swap the values they point to, which requires a temp variable with type int.
Here is a modified version:
void Swap(int *x, int *y) {
int temp;
temp = *x;
*x = *y;
*y = temp;
}
If you change a pointer variable to a variable, the function loses the ability to swap two numbers
void Swap(int *c, int *d) {
int *temp;
temp = *c;
*c = *d;
*d = temp;
}
I hope you can help me! I added this function to my array.c to shuffle the array elements and it works with static Item *a; static int dim; in my array.c.
static Item *a;
static int dim = 3;
a=malloc( dim * sizeof(Item);
void random_array() {
int i , j;
Item t;
for (i = dim - 1;i > 0; i--)
{
j = rand() % (i + 1);
t = a[i];
a[i] = a[j];
a[j] = t;
//swap(a[i], a[j]);
}
}
item.h
typedef void *Item;
item-int.c
#include <stdio.h>
#include <stdlib.h>
#include "item.h"
Item inputItem(){
int *p;
p=malloc(sizeof(int));
scanf("%d",p);
return p;
}
void outputItem(Item item){
int *p;
p=item;
printf("%d ",*p);
}
int cmpItem(Item item1,Item item2){
int *p1,*p2;
p1 = item1;
p2 = item2;
return *p1 - *p2;
}
So I tried with a function swap (a[i], a[j]) from the file utils.c but it doesn't work.
void swap (Item pa, Item pb) {
Item t;
t = pa;
pa = pb;
pb = t;
}
It works with these instructions:
void swap (Item *pa, Item *pb)
{
Item t;
t = *pa;
*pa = *pb;
*pb = t;
}
I know that with "typedef void *Item' Item t is like void *t and Item *a is like void **a, right?
So with double pointers I have a dynamic array with many pointers thanks to a=malloc(numberelements*(sizeof(Item)); and with a[i]=malloc(sizeof(Item) every pointer points to a memory location with many bytes?
Here a image.
So for t I don't need malloc because with t = a[i] t points to memory location pointed from a[i], right?
If yes, why do I have to use in my swap function t = *pa etc. instead of t = pa ? I have several doubts about double pointers as function parameters. I hope you can resolve that. Thanks in advance!
Ok, let's start from here:
typedef int Item; // Always get this backwards, need to check...
void swap (Item *pa, Item *pb)
{
Item t;
t = *pa;
*pa = *pb;
*pb = t;
}
void foo()
{
Item i= (Item), j=(Item)2; // These casts are not needed, but help later explanations
// Must take address so swap can change original values of i and j.
swap(&i, &j);
Item *ip = &i;
Item *jp = &j;
// This also works because we do the dereference above.
swap(ip, jj);
}
Either are fine. What about?
typedef int******* Item;
void swap (Item *pa, Item *pb)
{
Item t;
t = *pa;
*pa = *pb;
*pb = t;
}
void foo()
{
Item i= (Item)1, j=(Item)2;
// Must take address so swap can change original values of i and j.
swap(&i, &j);
int *ip = &i;
int *jp = &j;
// This also works because we do the dereference above.
swap(ip, jp);
}
Again, the type doesn't matter. It's how it's used. If you were to forget the &, the compiler would warn you about type mismatch.
First post on StackOverflow. I'm supposed to create a function:
int sumsort(int *a, int *b, int *c)
This function should arrange the 3 values in the memory locations pointed to
by a, b, and c in ascending order and also return the sum of the contents of
the memory locations a, b, and c.
Here's my function:
int sumsort(int *a, int *b, int *c) {
int sum = *a + *b + *c;
int sorted[] = {*a, *b, *c};
for (int i = 0; i <= 2; i++) {
if (sorted[0] > sorted[1])
{
int temp = sorted[1];
sorted[1] = sorted[0];
sorted[0] = temp;
} // end if
if (sorted[1] > sorted[2])
{
int temp2 = sorted[2];
sorted[2] = sorted[1];
sorted[1] = temp2;
} // end if
} // end for
return sum;
} // end sumsort function
How can I access the sorted[] array in main? I need to print the 3 variables in ascending order but don't really see how I can do that since the sumsort function has to return the sum and the actual sorting has to happen in the sumsort function too.
I tried creating a new array variable in main and assigning it sorted[] after I call the sumsort function, but that doesn't work because it's out of scope?
You are correct that you cannot access your sorted variable from main. But you don't need to. The point of the function is that it modifies the values pointed by its parameters.
For instance:
int main()
{
int x = 5, y = 1, z = 3;
int sum = sumsort(&x, &y, &y);
// now x == 1 , y == 3 , z == 5
}
This is possible. Inside sumsort you need not to create a new array, but to modify the values pointed by it's paramters.
For instance, if you had to sort just two numbers this is what you would do
void foo(int* a, int *b)
{
if (*a > *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
}
You can declare sorted[] as global variable outside of main:
int sorted[3];
main()
{
int a=20, b=15, c=22, sum;
sum= sumsort(&a,&b,&c);
printf("%d",sum);
printf("%d", sorted[0]);
printf("%d", sorted[1]);
printf("%d", sorted[2]);
}
And in your function you can use it as shown below:
int sumsort(int *a, int *b, int *c) {
int sum = *a + *b + *c;
sorted[0] = *a;
sorted[1] = *b;
sorted[2] = *c;
for (int i = 0; i <= 2; i++) {
if (sorted[0] > sorted[1])
{
int temp = sorted[1];
sorted[1] = sorted[0];
sorted[0] = temp;
} // end if
if (sorted[1] > sorted[2])
{
int temp2 = sorted[2];
sorted[2] = sorted[1];
sorted[1] = temp2;
} // end if
} // end for
return sum;
} // end sumsort function
You may have to check your sorting logic.
Hope this helps :)
I am trying to take a user entered array and swap the 0th value with the 7th, 8th value with the 3rd and the 0th with the 14th value. I have to use a function to swap which is where i think i messed up. When i compile it says to few arguments for function swap. also, its my 1st time using pointers so i wouldn't be surprised if there errors with that,. this is what i have, thanks!
#include <stdio.h>
void swap (int a[15], int *p, int *q, int *r ,int *s , int*t) {
int temp;
p = &a[0];
q = &a[7];
r = &a[8];
s = &a[3];
t = &a[14];
temp = *p;
*p = *q;
*q = temp;
temp = *r;
*r = *s;
*s = temp;
temp = *t;
*t = *p;
*p = temp;
}
int main (int argc, char *argv[]) {
int a[15], i;
printf(" Enter 15 integers: ");
for (i=0; i <15; i++)
swap(a);
printf(" Swapped array:\n %d", a[15]);
return 0;
}
Its not an error related to pointers.
You called swap() with one argument, like this swap(a);
And while defining it you have more then one arguments. Like
void swap (int a[15], int *p, int *q, int *r ,int *s , int*t) {
...
You do not need those extra arguments in the function definition.
Just change it to,
void swap (int a[15]) {
int temp;
int* p = &a[0];
int* q = &a[7];
int* r = &a[8];
int* s = &a[3];
int* t = &a[14];
...
A much better approach would be define a general function swap() and call it with proper required arguments multiple times when required.
void swap(int *p, int *q)
{
int tmp = *p;
*p = *q;
*q = tmp;
}
Call the above API something like
swap (&a[0], &a[7])
swap (&a[8], &a[3])
...
..
Sorry, another C pointer question.. I have a function func() that sorts an array, then get the largest and smallest integers. I'm trying to put them inside pointer variables in main() but the values are only correct inside the func() function. I don't understand why :(
#include <stdio.h>
void func(int arr[], int *s, int *l, int n){
int i = 1;
for(; i < n; i++){
int temp = arr[i];
int n = i;
while( n > 0 && arr[n-1] > temp){
arr[n] = arr[n-1];
n--;
}
arr[n] = temp;
}
l = &arr[n-1];
s = &arr[0];\
printf("%d %d\n",*l,*s);
}
int main(void){
int arr[] = {1,2,9,3,58,21,4};
int *s, *l;
int size = 7;
func(arr,s,l,size);
printf("%d %d\n",*l,*s);
}
When you pass a pointer as an argument to a function in C, a copy of the pointer is made. Thus, changing the value of the pointer has no effect outside of that function. However, changing the value at the memory referenced by the pointer will take effect everywhere, as you want. In your case, you would need to do this:
void func(int arr[], int *s, int *l, int n){
// sorting code..
// l = &arr[n-1]; WRONG - these change the value of the pointer,
//s = &arr[0];\ without changing the value of the memory they reference
*l = arr[n-1]; // CORRECT - changes the value at the referenced memory
*s = arr[0];
printf("%d %d\n",*l,*s);
}
Of course, the way you're using the pointers in main is also incorrect; they're uninitialized and likely to cause a segmentation fault. Since there appears to be no reason to use actual int* variables over ordinary int variables there, we can take another approach to passing them "by reference":
int main(void){
int arr[] = {1,2,9,3,58,21,4};
// int *s, *l; WRONG - we don't need pointers, we need to pass regular ints
int s, l;
int size = 7;
// Get the address of our variables with the address-of (&) operator
// This effectively creates int* variables out of our int variables
func(arr, &s, &l,size);
printf("%d %d\n",*l,*s);
}
Note that the term "by reference" here is not correct in the true sense of the phrase, since you are still receiving a copy of the address associated with the variable. Most languages provide a true by-reference faculty by removing this distinction and only allowing you access to the variable and its value, with the copying somewhat out of sight of the programmer. You can think of this as being "by reference with respect to l and s inside main", in the sense that their values can change due to the called function.
You need to pass the address of the pointer variables if you want to change what they are pointing at, otherwise a copy of the pointer variable is being changed inside the function (and is why it is correct within the function):
void func(int arr[], int** s, int** l, int n){
/* snip */
*l = &arr[n-1];
*s = &arr[0];
}
func(arr, &s, &l, size);
This would leave s and l pointing to elements of the array arr. If you just wanted the values of integers then the alternative would be to define int variables in main() and pass their addresses to func() and copy the relevent values from the array:
void func(int arr[], int* s, int* l, int n){
/* snip */
*l = arr[n-1];
*s = arr[0];
}
int s, l;
func(arr, &s, &l, size);
See this question from the C FAQ.
Your pointers are not initialized. You have two solutions:
use integers in main function (and eventually, although useless, make pointers point to them in the same function);
dynamically allocate memory for your pointer.
Easiest code:
#include <stdio.h>
int main(void)
{
int arr[] = {1, 2, 9, 3, 58, 21, 4};
int s, l;
int size = 7;
func(arr, &s, &l, size);
printf("%d %d\n", l, s);
}
In the current code, you don't need to make l and s point to the case of the array. So, as Dan F stated, you can just do integer's assignment.
void func(int arr[], int *s, int *l, int n)
{
int i = 1;
for(; i < n; i++){
int temp = arr[i];
int n = i;
while( n > 0 && arr[n-1] > temp){
arr[n] = arr[n-1];
n--;
}
arr[n] = temp;
}
*l = arr[n-1];
*s = arr[0];
printf("%d %d\n", *l, *s);
}