two output values through pointer - c

I had to write the following function, which returns two output values.
In order to do so I used a pointer for the second output value of the quotient. However when I wanted to test it with an input it seemed to be crushing. The code is:
#include <stdio.h>
int div( int n, int m, int *quotient)
{
int d = 0;
while (n >= m) {
n = n - m;
d++;
}
*quotient = d;
return n;
}
int main(void)
{
int *p;
int rest;
rest = div(7, 2, p);
printf("n - %i, d - %i", rest, p);
return 0;
}
would be happy to know how to fix it and why it happened at first place
Thanks for your help

Change this:
int *p;
int rest;
rest = div(7, 2, p);
To this:
int p;
int rest;
rest = div(7, 2, &p);
The problem with your code is that p points some random unallocated place (or is a null pointer if you're lucky). The updated version allocates space for the integer and then passes its address to the function. The function then has a pointer to this address and can write the value there. The memory is allocated on the stack (local variable) and so everything is fine.

Related

How do I print an actual number from this program that contains a function that returns a pointer?

#include <stdio.h>
int *max(int *, int *);
int main()
{
int *p, i, j;
p = max(&i, &j);
printf("%d\n", i);
return 0;
}
int *max(int *a, int *b)
{
if(*a > *b)
return a;
else
return b;
}
This is a program intended to return an integer that is bigger. A function "max" returns a pointer, as you can see. I want to print an actual integer here, but I'm stuck and cannot find a proper way to accomplish it. Can somebody help or give some hint to solve my problem?
Also, I would love to know that why there should be an asterisk in front of the function "max". Should there always be an asterisk when a function returns a pointer? The book that I am currently studying lacks information about this specific part, so can someone scratch my back? ;)
Last question first - max returns the value of either a or b. Since both a and b have type int * (pointer to int), then the return type of max also needs to be int *.
To access the integer value, you would need to dereference the result of max:
int main()
{
int *p, i, j;
/**
* The values of i and j are indeterminate at this point;
* you need to assign valid values to them before calling
* max.
*/
i = some_value();
j = some_other_value();
p = max(&i, &j);
printf("%d\n", *p); // Dereference p here to print the int value
return 0;
}
Another way to look at it is that the expressions *a, *b, *p, and *max( &i, &j ) all have type int.
If you want max to return an int rather than an int *, then you will need to dereference a and b in the return statements:
int max( int *a, int *b )
{
if ( *a > *b )
return *a;
else
return *b;
}
Although...
It's not clear why you're passing pointers as arguments to max; you're not attempting to modify the values of a or b, so there's really no need to use pointers at all. Just define max as
int max( int a, int b )
{
if ( a > b )
return a;
return b;
}
and call it as
int m = max( i, j );
or even
printf( "max( %d, %d ) = %d\n", i, j, max( i, j ) );

Scope of a pointer in memory

I have been studying C for the past weeks, but I can't fully understand how memory manages pointers.
My question arises from this example obtained from here(page 17 of 19): C-Pointer-Basics
Example code:
#include <stdio.h>
void F(int, int *);
int main()
{
int m = 3;
int n = 5;
F(m, &n);
printf("main: %d, %d\n", m, n); // print 3 7 (Where does the 7 came from?)
return 0;
}
void F(int a, int *b)
{
/*
* `a` being a local variable, gets cleaned after `F()` ends
* BUT how does `b` retain the value of `&a`?
*/
a = 7;
*b = a; // `*b = 7`
b = &a; // `b` points to `a`
*b = 4; // `a = 4` and why `*b` doesn't return 4?
printf("F: %d, %d\n", a, *b); // print 4 4
}
The question here is:
Why when main() prints the values of m and n, It showsm = 3 and n = 7?
My assumptions:
As I know, a pointer goes beyond the scope of the function where it is declared, so in void F(int a, int *b) when the function is no longer needed, it gets destroyed, same with his parameters, BUT the value of int *b remains in memory right(even though int *b no longer exists)? So if this is true, we can 'recover' it from memory and use it in main().
Best,
For the question why m and n print 3,7 is because the first parameter is passed by value hence it is only getting copied, therefore no modification of the original m is happening and in the case of n, you're passing its address so when you do *b=a the value of a gets copied to n. And then when you do b=&a the pointer b now starts pointing to the address of a instead of that of n. Which is why the second time you do *b=4, you are not modifying n but a.

Sum all integers within a range [p,q] where p and q can be entered in any order

Just started learning C, and it would be great if you could help me with the following:
I just wrote a program that calculates the sum of all the integers within a range [p, q]. Both p and q are entered in any order the user wants. So far, the program works fine when p < q, but doesn't when p > q. To reorder the values of both p and q I am using function reorder_range(), but it doesn't seem to work.
Also, I am not sure if the way I have organised the code is the proper one: a main() function that calls all the subprograms to run, rather than having everything within main().
I am looking forward to reading any suggestions to improve this piece of code!
#include <stdio.h>
#include <stdlib.h>
main() {
int sum, range, i, p, q, aux;
printf("Enter two integers:");
range = scanf("%d%d", &p, &q);
check_if_valid_value(range);
reorder_range(p, q, aux);
dothesum(p, q, i, sum);
}
check_if_valid_value(range) {
if (range != 2) {
printf("You have not entered two integers.\n");
exit(1);
}
}
int reorder_range(int p, int q, int aux) {
if (p > q) {
aux = p;
p = q;
q = aux;
}
}
int dothesum(int p, int q, int i, int sum) {
for (i = p; i <= q; ++i) {
sum = sum + i;
printf("%d\n", sum);
}
}
There are more than one problem we are looking at here. For example, there are variables (p and q) which should be passed by reference (as mentioned in other answers), there are variables (aux, i, sum) which are not required to be passed, the return type of the functions (check_if_valid_value(range)) are not correct and some local variables (sum) were not initialized before being used.
Here is the program that does the job for two positive numbers:
#include <stdio.h>
#include <stdlib.h>
void check_if_valid_value(int range)
{
if (range != 2)
{
printf("You have not entered two integers.\n");
exit(1);
}
}
void reorder_range(int *p, int *q)
{
int aux;
if (*p > *q)
{
aux = *p;
*p = *q;
*q = aux;
}
}
void dothesum(int p,int q)
{
int i, sum;
sum = 0;
for (i = p; i <= q; ++i)
{
sum=sum+i;
printf("%d\n", sum);
}
}
int main(void)
{
int range, p, q;
printf("Enter two integers:");
range=scanf("%d%d",&p,&q);
check_if_valid_value(range);
reorder_range(&p, &q);
dothesum(p,q);
return 0;
}
In many programming problems, especially those involving mathematics like this one, the best solution requires a mathematical analysis as well. In this case, as correctly noticed by #phuclv, you are calculating the sum of an arithmetic progression. So the actual solution requires just an immediate formula application.
The reason why your solution doesn't work, anyway, is a conceptual mistake. I'll explain it so that it comprehension will help you in the future
In C function parameters are passed by value. It means that the value of the parameter is stored within a copy of it, and then used in the function.
As a consequence, any change performed on a parameter will "live" until the function returns, when the parameters copies will be lost. So the original parameters will be unchanged.
Your function
int reorder_range(int p, int q, int aux)
{
if (p>q)
{
aux=p;
p=q;
q=aux;
}
}
has exactly this issue. The values will be swapped inside the function, but nothing will live outside it.
The solution
In order to actually affect from a function external variables you have to use pointers: passing addresses will make possible changing their contents.
int reorder_range(int *p, int *q)
{
if (p>q)
{
int aux = *p;
*p = *q;
*q = aux;
}
}
From your main (), just call the function passing the addresses of the variables containing the limits of your range:
reorder_range( &p, &q);
In reorder_range function, changed p,q values don't affect p,q values in main method.
When you passed an argument in a method with values, it doesn't change the value in the first place.
As a solution, you can pass the reference to your p, q variables.
In the main method before calling reorder_range,
int *pp = &p;
int *pq = &q;
then change your reorder_range function to take arguments as references.
then it will work.
for more information about pointer use following link.
TutorialsPoint c - pointers
Or you can create global variables for p and q then change them in your reorder_range function
The main problem in your code is in the reorder_range function: you only swap the values inside this function, without any side effect on the variables in the calling function. Arguments are passed by value in C, so changing the arguments inside a function does nt change the variables in the calling function. Passing pointers to the variables to reorder is a way to fix this problem.
There are other problems:
omitting the return type when defining a function is an obsolete syntax. main should be defined as int main() or int main(void), reorder_range should have a return type of void.
do_the_sum() should only take the range boundaries, not the index and sum variables. You should define these as local variables.
you should define or at least declare the functions before calling them.
Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
void check_if_valid_value(int res) {
if (res != 2) {
printf("You have not entered two integers.\n");
exit(1);
}
}
int reorder_range(int *p, int *q) {
if (*p > *q) {
int aux = *p;
*p = *q;
*q = aux;
}
}
int dothesum(int p, int q) {
int i, sum = 0;
for (i = p; i <= q; ++i) {
sum = sum + i;
}
return sum;
}
int main() {
int res, p, q;
printf("Enter two integers:");
res = scanf("%d%d", &p, &q);
check_if_valid_value(res);
reorder_range(&p, &q);
printf("%d\n", dothesum(p, q));
return 0;
}
Note however that you do not really need more than a single function for your problem:
#include <stdio.h>
int main() {
int p, q, i, sum;
printf("Enter two integers: ");
if (scanf("%d%d", &p, &q) != 2) {
printf("You have not entered two integers.\n");
return 1;
}
if (p > q) {
int aux = p;
p = q;
q = aux;
}
sum = 0;
for (i = p; i <= q; i++) {
sum += i;
}
printf("%d\n", sum);
return 0;
}
Finally, the for loop can be omitted and the result computed directly this way:
printf("%d\n", (p + q) * (p - q + 1));
Using this simple expression, even reordering the range is no longer necessary:
#include <stdio.h>
#include <stdlib.h>
int main() {
int p, q;
printf("Enter two integers: ");
if (scanf("%d%d", &p, &q) != 2) {
printf("You have not entered two integers.\n");
return 1;
}
printf("%d\n", (p + q) * (abs(p - q) + 1));
return 0;
}
Your error is in function reorder_range: you are changing the values within the function but, when you return to the main, these values return to their original value. What you have to do is pass the memory address to change them inside the function.
A recommendation I give you is:
the functions you have do not return anything, so you should place void instead of int
the prototypes of the functions must be declared before the main
the check_if_valid_value parameter is not declared

C pointer arithmetic palindrome

I'm a java student who's currently learning about pointers and C.
I tried to make a simple palindrome tester in C using a single array and pointer arithmetic.
I got it to work without a loop (example for an array of size 10 :*(test) == *(test+9) was true.
Having trouble with my loop. School me!
#include<stdio.h>
//function declaration
//int palindrome(int *test);
int main()
{
int output;
int numArray[10] = {0,2,3,4,1,1,4,3,2,0};
int *ptr;
ptr = &numArray[0];
output = palindrome(ptr);
printf("%d", output);
}
//function determine if string is a palindrome
int palindrome(int *test) {
int i;
for (i = 0; i <= (sizeof(test) / 2); i++) {
if (*(test + i) == *(test + (sizeof(test) - i)))
return 1;
else
return 0;
}
}
The Name of the array will itself acts as a pointer to an first element of the array, if you loose the pointer then there is no means for you to access the element of the array and hence you can send just the name of the array as a parameter to the function.
In the palindrome function:
you have used sizeof(test)/2. what happens is the address gets divided which is meaningless and hence you should not use that to calculate the mid element.
sizeof the pointer will be the same irrespective of the type of address that gets stored.
Why do you copy your pointer in another variable?
int *ptr;
ptr = &numArray[0];
Just send it to you function:
palindrome(numArray);
And sizeof(test) give you the memory size of a pointer, it's not what you want. You have to give the size in parameter of your function.
int palindrome(int *test, int size){
...
}
Finally your code must look like this:
#include<stdio.h>
int palindrome(int *test, int size);
int main()
{
int output;
int numArray[10] = {0,2,3,4,1,1,4,3,2,0};
output = palindrome(numArray, 10);
printf("%d", output);
}
//function determine if string is a palindrome
int palindrome(int *test, int size) {
int i;
for (i = 0; i < size / 2; i++) {
if (*(test + i) != *(test + (size - 1) - i))
return 0;
}
return 1;
}

How can I test this C function

I got a weird question to do as an exercise :
Write a function which take a pointer of a pointer of a pointer of a pointer of a pointer of a pointer of a pointer of a pointer of a pointer of an int as a parameter and assign a value to it.
I think the function I wrote is right (please correct if it's not) but how can I test it ?
void function(int *********anInt)
{
*********anInt = 5;
}
I tried :
int main(void) {
int *********nbr = malloc(sizeof(int));
function(nbr);
printf("%d", *********nbr);
}
But I get a segfault, I just learned about malloc and pointers so I don't fully understand it.
Of course, you can test it, although it looks weird.
#include <stdio.h>
void function(int *********anInt)
{
*********anInt = 5;
}
int main()
{
int n = 0;
int *p1 = &n;
int **p2 = &p1;
int ***p3 = &p2;
int ****p4 = &p3;
int *****p5 = &p4;
int ******p6 = &p5;
int *******p7 = &p6;
int ********p8 = &p7;
function(&p8);
printf("%d\n", n);
return 0;
}
Try
int main() {
int *********nbr;
nbr = malloc(sizeof(int********));
*nbr = malloc(sizeof(int*******));
**nbr = malloc(sizeof(int******));
***nbr = malloc(sizeof(int*****));
****nbr = malloc(sizeof(int****));
*****nbr = malloc(sizeof(int***));
******nbr = malloc(sizeof(int**));
*******nbr = malloc(sizeof(int*));
********nbr = malloc(sizeof(int));
function(nbr);
printf("%d", *********nbr);
}
You'll need a ridiculous main program to go with the assignment from hell!
int main(void)
{
int l0 = 0;
int *l1 = &l0;
int **l2 = &l1;
int ***l3 = &l2;
int ****l4 = &l3;
int *****l5 = &l4;
int ******l6 = &l5;
int *******l7 = &l6;
int ********l8 = &l7;
printf("%d %d %d %d %d %d %d %d %d\n", l0, *l1, **l2, ***l3, ****l4, *****l5,
******l6, *******l7, ********l8);
function(&l8);
printf("%d %d %d %d %d %d %d %d %d\n", l0, *l1, **l2, ***l3, ****l4, *****l5,
******l6, *******l7, ********l8);
return 0;
}
Untested: maybe I didn't count something right, but the general idea is about correct. This is a torture test — for innocent C programmers and for compilers.
An int** is a pointer that points to a pointer:
int myInt;
int* pInt = &myInt;
int** ppInt = &pInt;
An int*** is a pointer that points to a pointer that points to a pointer:
int*** pppInt = &ppInt;
To test your function, you need to carry this on and on, the right number of times.
See md5's solution, however it lacks explaination
Explained:
The reason your test program didn't work is because malloc returns a void* which is simply a memory address (a pointer). You assigned this to an int*****... which means when the program tries to dereference down to the actual int what it's doing is first taking the memory address of the int and dereferencing it (which is okay) but after this since your value (5) is now the value it then derefences that, which should come back with your segfault.
Think of the assignment as nested dereferences:
int ********p8 = *anInt; // p8 == 5
int *******p7 = *p8; // This breaks since dereferencing memory
// address 5 results in a segfault
What was done to avoid this was we actually nested the pointers that way when dereferencing for assignment we have memory addresses (pointers) to dereference to eventually get to the memory address which stores the value.

Resources