Beginner C programming passing pointers to function is giving unpredicted result - c

I am learning C as a part of my curriculum, and I am still learning the concepts of pointers. The following example gives unpredicted results for me.
#include <stdio.h>
void Calculate(int *x, int *y, int *k, int *m) {
k = *x * *y;
m = *x + *y;
}
int main() {
int *k;
int *m;
int g = 10;
int h = 11;
Calculate(&g, &h, k, m);
printf("%d\n", m);
printf("%d", k);
}
Each execution is giving me different results, like
-1155180448
0
or
253276384
0
or
591649904
0
but if I change the code to
#include <stdio.h>
void Calculate(int *x, int *y, int *k, int *m) {
*k = *x * *y;
*m = *x + *y;
}
int main() {
int k;
int m;
int g = 10;
int h = 11;
Calculate(&g, &h, &k, &m);
printf("%d\n", m);
printf("%d", k);
}
it prints the correct values like
21
110
Isn't using int *k; int *m; and passing it to a function as somefunc(k, m) the same as int k; int m; somefunc(&k, &m)?
Kindly explain what is wrong here.
Thank you.

The function should be:
void Calculate(int *x, int *y, int *k, int *m) {
*k = *x * *y;
*m = *x + *y;
}
*k means an int stored in memory being pointed to by k. You don't want to modify k, you want to modify what is stored in the space k points to.
Then you call like this:
int a, b;
int g = 10;
int h = 11;
Calculate(&g, &h, &a, &b);
You tell the Calculate function whereabouts in memory the variables a and b are which will hold the result of the calculation.
Note: I used different variable names because it is confusing to use the same name k for an int in one place, and k for an int * in another place. Another plan of course would be to use k,m in main and use pk or pm in the function (meaning "pointer to k", etc.)
Also you don't need to use pointers to pass g and h and in fact this is a bad idea, unless you are planning to change those in the function too.

If you really want to test this call Calculate(&g, &h, k, m); as in your first example, passing integers g and h and integer pointers *k and *m, first make sure that the pointers really point at something, so they can be treated likewise as addresses of integer variables by your Calculate() function, or whichever function of syntax alike.
#include <stdio.h>
#include <stdlib.h> //add this header for malloc
void Calculate(int *x, int *y, int *k, int *m) {
*k = *x * *y;
*m = *x + *y;
}
int main()
{
int *k = malloc(sizeof(int)); //initialize the pointer to point at something
int *m = malloc(sizeof(int)); //initialize the pointer to point at something
int g = 10;
int h = 11;
Calculate(&g, &h, k, m);
printf("%d\n", *m);
printf("%d\n", *k);
free(k); //free the space pointed to by pointers!
free(m);
return 0;
}
This is not a very practical solution (at least as your example is concerned), but is here only to show how you should treat your pointers as function arguments from within your caller function.

Related

Which code would you prefer and why? Program to swap values using pointers [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
This is a program to swap two numbers using pointers.
#include<stdlib.h>
#include<stdio.h>
void swap(int *x, int *y){
int temp = *x;
*x = *y;
*y = temp;
}
int main(int argc, char const *argv[])
{
int *a = (int *) malloc(sizeof(int));
int *b = (int *) malloc(sizeof(int));
*a =1;
*b =2;
printf("Nos are: %i %i\n", *a, *b);
swap(a,b);
printf("Swapped: %i %i\n", *a, *b);
free(a);
free(b);
return 0;
}
Would you prefer this or,
#include<stdlib.h>
#include<stdio.h>
void swap(int *x, int *y){
int temp = *x;
*x = *y;
*y = temp;
}
int main(int argc, char const *argv[])
{
int a= 1;
int b= 2;
printf("Nos are: %i %i\n", a, b);
swap(&a,&b);
printf("Swapped: %i %i\n", a, b);
return 0;
}
Which one is better in terms of programming standards? or which one would you prefer? (pls give some theoretical explanation as well)
Output for both the codes are same i.e it swaps and returns 2 1
I would
prefer first case if I am swapping some heavy data, lets say some struct x, so we pass address of struct which is a fixed size depends on system.
prefer second case for normal data like int or char etc..
There is no need to allocate memory and free.
I would not prefer swap function using pointers.
This task is best done by the macros:
#include <stdio.h>
#define SWAP(a,b,type) do{type c__c__c; c__c__c = (a); (a) = (b); (b) = c__c__c;}while(0)
struct s
{
int a;
char x[100];
double w[100];
};
int main()
{
double a = 5.0, b = 6.0;
int c = 5, d = 6;
struct s x = {.a = 1},y = {.a = 2};
SWAP(a, b, double);
SWAP(c, d, int);
SWAP(x, y, struct s);
printf("%f %f\n", a, b);
printf("%d, %d\n", c, d);
printf("%d, %d\n", x.a, y.a);
return 0;
}
and the code will every efficient. You also do not have to write dozens of functions for every type.
Of course you can write "generic" swap function
void *swap(void *a, void *b, size_t size)
{
unsigned char temp[size];
memcpy(temp, a, size);
memcpy(a, b, size);
memcpy(b, temp, size);
return a;
}

Changing **array + a to *array[a]

What my program does is it finds 2 numbers of an array that are closest to the average, one is bigger, one is smaller. It works fine, however I need to change for example **array+a to *array[a].
However, when I load the program, it crashes after I input the numbers. If I try to print *array[0], *array[1], etc. it works fine. When I try to print or just do something with *array[a], *array[b], it crashes. Thank you for your help.
#include <stdio.h>
#include <stdlib.h>
int input (int *t, int *array[]);
void calculation (int *array[], int *t, int *x, int *y);
void output (int *x, int *y);
int main()
{
int *array, t, x, y;
input (&t, &array);
calculation (&array, &t, &x, &y);
output (&x, &y);
return 0;
}
int input (int *t, int *array[])
{ int n, *ptr;
printf ("How big is the array?");
scanf ("%d", &n);
ptr = (int*) malloc(n * sizeof(int));
int k;
printf ("Enter the numbers:");
for (k=0; k<n; k++)
{ scanf ("%d", ptr + k);
}
*t=n;
*array=ptr;
return 0;
}
void calculation (int *array[], int *t, int *x, int *y)
{ float sum=0, avg;
int min, max;
int more, less;
int a, b, c;
for (a=0; a<(*t); a++)
{sum=sum+ **array + a;
}
avg=sum/(*t);
min= *array[0];
max= *array[0];
for (b=0; b<(*t); b++)
{ if (max < (**array + b)) max=(**array + b);
if (min > (**array + b)) min=(**array + b);
}
more=max;
less=min;
for (c=0; c<(*t); c++)
{ if (((**array + c) < avg) && ((**array + c) > less)) less=(**array + c);
if (((**array + c) > avg) && ((**array + c) < more)) more=(**array + c);
}
*x=less;
*y=more;
}
void output (int *x, int *y)
{ printf("Number that is less than the average:%d\n", *x);
printf("Number that is more than the average:%d\n", *y);
}
It would be better to rethink your function prototypes a bit. It makes sense to pass a pointer to array to the input() function since you are allocating memory for it, and you want to be able to access it when you return. But you don't need to pass in the pointer to int t; instead, just return the value of n, and assign it to t in main.
There is no reason to pass a pointer to array to the function calculation(), since you are not changing the array allocation. You can also pass in the value of t from main(), since you only use this value in calculation(), but do not change it.
Similarly, the output() function only needs copies of x and y, since it does not change them.
The rule of thumb here is that you pass a pointer to a value into a function when you want to modify the value inside the function and have access to the modified value in the calling function. But you can also return a value instead of using a pointer to it.
These changes do not alter the functionality of your code, but they substantially improve its readability. You even get a sense of what is being modified in each function just by looking at the function prototypes. Well, the changes do alter the functionality in that your original **array + a was incorrect, and needed to be either *(*array + a) or (*array)[a]. But sorting that problem out should help you to appreciate the virtue of the simpler function prototypes. Here is the modified code:
#include <stdio.h>
#include <stdlib.h>
int input(int *array[]);
void calculation(int array[], int t, int *x, int *y);
void output(int x, int y);
int main(void)
{
int *array, t, x, y;
t = input(&array);
calculation(array, t, &x, &y);
output(x, y);
return 0;
}
int input(int *array[])
{ int n, *ptr;
printf("How big is the array?");
scanf("%d", &n);
ptr = (int*) malloc(n * sizeof(int));
int k;
printf("Enter the numbers:");
for (k=0; k<n; k++)
{ scanf("%d", ptr + k);
}
*array=ptr;
return n;
}
void calculation(int array[], int t, int *x, int *y)
{ float sum=0, avg;
int min, max;
int more, less;
int a, b, c;
for (a=0; a<t; a++)
{sum=sum+ array[a];
}
avg=sum/t;
min= array[0];
max= array[0];
for (b=0; b<t; b++)
{ if (max < array[b]) max=array[b];
if (min > array[b]) min=array[b];
}
more=max;
less=min;
for (c=0; c<t; c++)
{ if ((array[c] < avg) && (array[c] > less)) less=array[c];
if ((array[c] > avg) && (array[c] < more)) more=array[c];
}
*x=less;
*y=more;
}
void output(int x, int y)
{ printf("Number that is less than the average:%d\n", x);
printf("Number that is more than the average:%d\n", y);
}
Just like BLUEPIXY and Some programmer dude said, it's supposed to be (*array)[a]

Trouble of pointers as function arguments

I have created a function that does the euclidean division in C and putting the quotient and remainder as function arguments.
code listing 1:
#include<stdio.h>
#include<stdlib.h>
void euclidean(int a, int b, int * q, int * r);
int main(int argc, char ** argv){
int * q;
int * r;
euclidean(5,4, q, r);
printf("q = %d, r = %d", *q, *r);
return 0;
}
void euclidean(int a, int b, int * q, int * r){
q = (int*)malloc(sizeof(int));
r = (int*)malloc(sizeof(int));
*q = a/b;
*r = a % b;
//printf("q = %d, r = %d", *q, *r); //this will show
return;
}
code listing 2:
#include<stdio.h>
#include<stdlib.h>
void euclidean(int a, int b, int * q, int * r);
int main(int argc, char ** argv){
int * q;
int * r;
euclidean(5,4, q, r);
printf("q = %d, r = %d", *q, *r);
return 0;
}
void euclidean(int a, int b, int * q, int * r)
{
*q = a / b;
*r = a % b;
//printf("q = %d, r = %d", *q, *r); //this won't show
return;
}
Both version aren't working. I compiled and ran the code on windows and the program is killed on runtime without printing anything (i.e. "q = 1, r = 4"). And my guess is if I had to compile and run it on linux, the terminal would gave me a "segmentation fault" error (not sure). I really don't see why it isn't working, especially with code listing 1. For code listing 2 one can argue that since the result of the operation are some sort of constant variable inside a function in which they were created, they could not be kept at the end of the function (I need confirmation on that too). Thanks
Keep It Simple, Stupid (there is such a principle).:)
#include<stdio.h>
#include<stdlib.h>
void euclidean(int a, int b, int * q, int * r);
int main(int argc, char ** argv){
int q;
int r;
euclidean(5,4, &q, &r);
printf("q = %d, r = %d", q, r);
return 0;
}
void euclidean(int a, int b, int * q, int * r)
{
*q = a / b;
*r = a % b;
}
If you want indeed to allocate memory in the function then the code will look like
#include<stdio.h>
#include<stdlib.h>
void euclidean(int a, int b, int * *q, int * *r);
int main(int argc, char ** argv){
int * q;
int * r;
euclidean(5,4, &q, &r);
printf("q = %d, r = %d", *q, *r);
free( q );
free( r );
return 0;
}
void euclidean(int a, int b, int * *q, int * *r){
*q = (int*)malloc(sizeof(int));
*r = (int*)malloc(sizeof(int));
**q = a/b;
**r = a % b;
}
You are not getting values for listing_2 because:-
void euclidean(int a, int b, int * q, int * r)
{
*q = a / b; <<<<<<<<<<<<<<<<<
*r = a % b;
//printf("q = %d, r = %d", *q, *r); //this won't show
return;
}
Neither you have allocated memory for q,r in main nor in euclidean. You were getting error as you are trying to deference a pointer not initialized to anything.
What you want is known as pass-by-reference, which allows the callee to modify the object the caller provides.
As C is purely pass-by-value, that is simulated with pointers:
The caller passes the address of the object the callee should modify, and the callee dereferences the received pointer to modify the intended target.
#include<stdio.h>
#include<stdlib.h>
void euclidean(int a, int b, int * q, int * r)
{
// Modify the target-objects q and r point to
*q = a / b;
*r = a % b;
}
int main() {
int q, r; // Not pointers, the objects themselves!
euclidean(5, 4, &q, &r); // Passing the addresses of q and r
printf("q = %d, r = %d", q, r);
}
No dynamic allocation at all.

C - input 2 values, return 2 values to MAIN. swapping

I need to make a program to arrange 4 numbers in ascending order, like 9 2 8 3 to 2 3 8 9.
So i thought of the logic by using swap. I would be using if/else or switch statements but first i need to solve this problem below.
I want to input 2 integers (to compare later), then swap them and return it to main function. How do i do this. Please provide the best solution though i haven't been taught pointers, structs etc.
#include <stdio.h>
int swap(int x, int y)
{
int c;
c = x;
x = y;
y = c;
return x, y;
}
int main()
{
int a = 5, b = 7;
printf("a=%d b=%d\n", a, b);
swap(a, b);
printf("a=%d b=%d\n", x, y);
return 0;
}
I want final output as 7, 5. Thanks!
return x, y;
You can not return more than one value from a function, you can pass a pointer and then modify his content:
#include <stdio.h>
void swap(int *x, int *y)
{
int c;
c = *x;
*x = *y;
*y = c;
}
int main()
{
int a = 5, b = 7;
printf("a=%d b=%d\n", a, b);
swap(&a, &b);
printf("a=%d b=%d\n", a, b);
return 0;
}
Pass Address of variables a and b
void swap(int *x, int *y)
{
int c;
c = *x;
*x = *y;
*y = c;
}
call from main swap(&a,&b);
print a and b values in main.

C program for sorting 3 random numbers , void reorder3(int a, int *b, int **c);

This code is working but its not exactly what I want. Is anyone have any idea how to make it correct and without q sort?. The idea is to understand how to use pointers.
The three numbers should be random between -3 and 12. The code below is something similar, and the closest I have found. Any help would be much appreciated. Thanks in advance!!.
#include <stdio.h>
#include <stdlib.h>
//functions
int compare(const void *a, const void *b)
{
const int *ia = a;
const int *ib = b;
if (*ia < *ib)
return -1;
else if (*ia > *ib)
return +1;
return 0;
}
//qsort function
void sort3(int *a, int *b, int *c)
{
int temp[3];
temp[0] = *a;
temp[1] = *b;
temp[2] = *c;
qsort(temp, 3, sizeof(int), &compare);
*a = temp[0];
*b = temp[1];
*c = temp[2];
}
//random function
int rand_int(int a, int b)
{
return rand()%(b-a+1)+a;
}
int main(void)
{
//declaration of variables
int a,b,c;
int rand_int(int a, int b);
srand(time(0));
a = rand_int(-3,12);
b = rand_int(-3,12);
c = rand_int(-3,12);
printf("%i %i %i\n", a, b, c);
sort3(&a, &b, &c);
printf("%i %i %i\n", a, b, c);
return 0;
}
You don't need the compare() function if you don't want to use qsort().
You can rewrite sort3() like this:
void compare_and_swap(int *a, int *b) {
int t;
if (*a > *b) {
t = *a;
*a = *b;
*b = t;
}
}
void sort3(int *a, int *b, int *c) {
compare_and_swap(a, b);
compare_and_swap(a, c);
compare_and_swap(b, c);
}
This is actually a "bubble sort".
This is a lot of trouble to go for to sort 3 integers. Use if statements.
If the goal is actually to understand pointers, they seem intimidating but they're not so bad. Basically, they're a number that happens to be an address. You can manipulate like them numbers, but if you dereference them (with *), you can get the value there. This cuts both ways, though, because there's not much stopping you from dereferencing a value - which probably crashes your program (or more scarily, maybe not).
As long as you keep in mind what's an address and what's a value, you should be OK.

Resources