I want to create a recursive Factorial using the Pass By Reference method.
int recursiveFactorialByValue(int x){
if (x==0||x==1) return 1;
else if (x<=0) return -1;
else return x * recursiveFactorialByValue(x-1);
}
void recursiveFactorialByReference(int *x){
int minusOne = *x - 1;
int *ptr = &minusOne;
if (*x==0||*x==1) *x = 1;
else if (*x <= 0) *x = -1;
else *x * recursiveFactorialByReference(ptr); //this is where the error occurs
}
int main(){
int x, *ptr=&x, **pptr=&ptr, y;
printf("Enter a positive integer: ");
scanf("%d",*&x);
y = x;
printf("%i! = %i\n",y,recursiveFactorialByValue(x));
recursiveFactorialByReference(ptr);
printf("%i! = %i\n", y, x);
return 0;
}
I get this error:
In function 'recursiveFactorialByReference':
14:7: error: void value not ignored as it ought to be
else recursiveFactorialByReference(ptr) * *x;
I've tried different function calls like:
else *x = *x * recursiveFactorialByReference(*x-1);
else *x = *x * recursiveFactorialByReference(ptr);
and none of these work, I can't find the problem please help.
*x * recursiveFactorialByReference(ptr)
This multiplies the value pointed to by x (which is an int) with the return value of recursiveFactorialByReference (which is void), which makes no sense. Think about what your recursive function does: you pass it a pointer to an int and it replaces that int with its factorial. So your recursive part should look like this:
else
{
recursiveFactorialByReference(ptr);
*x *= *ptr;
}
Note that you still have to assign to *x. Multiplying it on its own just throws away the value.
Also you have an extra * in your scanf call. It should be
scanf("%d", &x);
Also these technically aren't "references" (that's a concept from C++). Both of your functions are passing values, the latter just happens to be passing the values of pointers.
Related
I just started learning C language, and I can't fully understand why we should use pointers of pointers in order to append an element into the table (*tab).
here's the code :
#include "append.h"
int append(int ** tab, size_t *size, int value){
int *nouveauTab = realloc(*tab, (*size + 1) * sizeof(int));
if (nouveauTab == NULL){
return 0;
}
*tab = nouveauTab;
(*tab)[*size] = value;
(*size)++;
return 1;
}
If not to use pointer to pointer then the pointer tab will be passed by value. That is the function will deal with a copy of the value of the original pointer. Changing the copy does not influence on the original pointer. It will stay unchanged because it is its copy that was changed within the function.
So you need to pass the pointer by reference.
In C passing by reference means passing an object (a pointer is an object) indirectly through a pointer to it. Thus dereferencing the pointer the function will have a direct access to the original object. In the case of your function to the original pointer like
*tab = nouveauTab;
The short answer is: Because you want to change the value of a pointer in the caller of append. That happens here: *tab = nouveauTab;
The code calling your append function will look something like:
int* table = NULL;
size_t table_size = 0;
if (append(&table, &table_size, 42) == 0)
{
puts("append failed");
}
else
{
printf(size is now %zu and element %zu is %d", table_size, table_size-1, table[table_size-1]);
}
So your code expects that append (on success) will change the value of both table and table_size. That requires that you pass the function pointers to these two variables.
If you did it without usinb pointers, i.e. like:
if (append(table, table_size, 42) == 0)
the function would not be able to change their values as C would just pass a copy of their current values.
A simple example using int
void foo(int x)
{
x = x + 1;
printf("%d\n", x);
}
int x = 42;
printf("%d\n", x);
foo(x);
printf("%d\n", x);
will print
42
43
42 <--- x not changed by `foo` because we passed the value of x (i.e. 42)
but with this:
void foo(int* x)
{
*x = *x + 1;
printf("%d\n", *x);
}
int x = 42;
printf("%d\n", x);
foo(&x);
printf("%d\n", x);
it will print
42
43
43 <--- x was changed by `foo` because we passed a pointer
Using pointers, GCD and LCM are solved using a single function and pointer. I'm not used to pointers yet. Anyway, I wrote the code below. However, errors such as terminated with exit code: 3221225477 continue to appear. According to a search on the Internet, the exit code above is due to incorrect memory references. But I don't know which part is wrong.
#include <stdio.h>
void gcdlcm(int a, int b, int* p_gcd, int* p_lcm){
int tmp, n, result_gcd, result_lcm;
int gcd_a, gcd_b;
p_gcd = &result_gcd;
p_lcm = &result_lcm;
if(a < b){
tmp = a;
a = b;
b = tmp;
}
gcd_a = a;
gcd_b = b;
if(gcd_b == 0){
result_gcd = 0;
}
while (gcd_b != 0)
{
n = gcd_a % gcd_b;
gcd_a = gcd_b;
gcd_b = n;
}
result_gcd = gcd_a;
printf("result_gcd = %d\n", result_gcd);
result_lcm = a * b / result_gcd;
printf("result_lcm = %d\n", result_lcm);
}
int main(){
int x, y;
int *p_gcd, *p_lcm;
scanf("%d %d", &x, &y);
gcdlcm(x, y, p_gcd, p_lcm);
printf("%d %d", *p_gcd, *p_lcm);
return 0;
}
Here:
p_gcd = &result_gcd;
you change the local variable p_gcd. This wil not affect the p_gcd in main, which after returning from gcdlcm has the same undefined value as before. Dereferencing it leads to your exception.
I you want to pass arguments as pointers so that your function can fill in the correct data, you must create variables to hold the data, then pass pointers to them with the address-of operator &:
int gcd, lcm;
scanf("%d %d", &x, &y);
gcdlcm(x, y, &gcd, &lcm);
(By the way, that's exactly the same how the scanf function one line above your call works.)
In your function, assign the result to what the pointer points to:
*p_gcd = gcd_a;
This modifies the variable gcd in main via the pointer p_gcd. Now, after returning from gcdlcm, gcd has the desired value.
the error is in this line printf("%d %d", *p_gcd, *p_lcm);. and the reason is that both will point to some random data.
This happens because your function will copy these values. p_gcd and p_lcm from your function are copies of the values in main. so when you set them, just the copies are modified to point to the variable, not the actual values. you should add a & or another * there, but even doing that will give you an error. because you try to return addresses of result_gcd and result_lcm which are local to your function.. and their addresses are invalid after the function ends
the best way around this would be (in my opinion) to return both values in a struct:
struct Result {
int gdc;
int lcm
};
struct Result gcdlcm(int a, int b){
//...
struct Result r;
r.gdc = result_gcd;
r.lcm = result_lcm;
return r;
}
if you dont like the solution, you can use pass pointers to variables in main and set them up in the function:
void gcdlcm(int a, int b, int* p_gcd, int* p_lcm){
int tmp, n, result_gcd, result_lcm;
int gcd_a, gcd_b;
if(a < b){
tmp = a;
a = b;
b = tmp;
}
gcd_a = a;
gcd_b = b;
if(gcd_b == 0){
result_gcd = 0;
}
while (gcd_b != 0)
{
n = gcd_a % gcd_b;
gcd_a = gcd_b;
gcd_b = n;
}
result_gcd = gcd_a;
printf("result_gcd = %d\n", result_gcd);
result_lcm = a * b / result_gcd;
printf("result_lcm = %d\n", result_lcm);
*p_gcd = result_gcd;
*p_lcm = result_lcm;
}
int main(){
int x, y;
int p_gcd, p_lcm;
scanf("%d %d", &x, &y);
gcdlcm(x, y, &p_gcd, &p_lcm);
printf("%d %d", p_gcd, p_lcm);
return 0;
}
You declared uninitialized pointers:
int *p_gcd, *p_lcm;
that have indeterminate values.
These pointers are passed by you to a function by value:
gcdlcm(x, y, p_gcd, p_lcm);
That is the function deals with copies of the values of the pointers p_gcd and p_lcm. So changing the copies do not affect the original pointers.
As a result dereferencing these initializing pointers in the statement:
printf("%d %d", *p_gcd, *p_lcm);
results in undefined behavior.
If you want to change the original pointers in the function you need to pass them by reference.
In C passing by reference means passing objects indirectly through pointers to them. So dereferencing the pointers you will get a direct access to the objects.
For example:
void gcdlcm(int a, int b, int **p_gcd, int **p_lcm){
int tmp, n, result_gcd, result_lcm;
int gcd_a, gcd_b;
*p_gcd = &result_gcd;
*p_lcm = &result_lcm;
//...
and in main:
gcdlcm(x, y, &p_gcd, &p_lcm);
I have a function which returns an integer pointer type:
int* f(int a, int b){
int *result;
result = &a;
*result += b;
return result;
}
and when I call this on main:
int main(){
int a = 5;
int b = 2;
int *result = f(a,b);
printf("The result is: %d \n", *result);
return 0;
}
It gives me the correct output(in this case 7). I was under the impression that by assigning the address of the parameter a to result I would get a segmentation fault when I ran this function.
My assumption is that C treats function parameters as local in scope to the function definition. But, I see that this is not the case so why is this specific program working ?
I'm using Code::Blocks 16.01 with gcc compiler.
Just because it works on your machine doesn't mean it isn't undefined behaviour. This works by fluke, but it's invalid.
It may produce the correct result because that stack is not overwitten or otherwise mangled by the time you do something later on.
For example, if you make another function call:
#include <stdio.h>
#include <stdlib.h>
int noop(int x, int y) {
return x + y;
}
int* f(int a, int b){
int *result;
result = &a;
*result += b;
return result;
}
int main(){
int a = 5;
int b = 2;
// Do something with undefined behaviour
int *result = f(a,b);
// Do something else which uses the stack and/or the same memory
int x = 10;
int y = 11;
int z = noop(x, y);
printf("The result is: %d \n", *result);
return 0;
}
Now the output gets stomped with the definition of x which coincidentally takes the same piece of memory so the output is 10. As this is undefined behaviour, though, anything could happen, including a crash.
My issue is that I keep getting the same type of error and I can not understand why. I'm fairly sure I declared and defined it before the main function.
Here is my code.
#include <stdio.h>
void functn (int x);
int functn(int x, int result){
result = (x-1)+2;
if (x <= 0){
return 0;
}
else{
return result;
}
}
int main (){
int x, y;
printf ("Enter the value of x: ");
scanf ("%d", &x);
y = f(x);
printf ("%d", y);
return 0;
}
You have a number of problems in functn. Primarily passing result. When you pass result to functn, functn receives a copy of result and the only way to get the modified value is to return the modified value. You can also pass a pointer to result and update *result in functn (similar to what you do now), that would eliminate the need to return a value, as any changes to result would be visible back in the calling function (main() here). Further, there is no need for global variables. Simply declare the variables local to main and pass as parameters, as required.
The following example declares functn (simply f below) to do both, take a pointer to result (e.g. &result) as a parameter, while also returning result, which allows you to either assign the return or not, but always have the updated value for result back in main, e.g.
#include <stdio.h>
int f (int x, int *result);
int main (void){
int x, y, result = 0;
printf ("Enter the value of x: ");
if (scanf ("%d", &x) != 1) {
fprintf (stderr, "error scanf, invalid conversion.\n");
return 1;
}
y = f (x, &result);
printf ("y = f(%d) => %d\n", x, y);
return 0;
}
int f (int x, int *result)
{
*result = (x-1)+2;
if (x <= 0)
return 0;
return *result;
}
Example Use/Output
$ ./bin/yfx
Enter the value of x: 5
y = f(5) => 6
Look things over and let me know if you have questions.
Return type of functn() different in declaration and definition. So, use
int functn(int x);
instead of
int functn(int x, int result)
Remove int result from function argument and declare inside function. like,
int functn(int x)
{
int result = 0;
result = (x-1)+2;
if (x <= 0){
return 0;
}
else{
return result;
}
}
Also, correct function call, like
y = functn(x);
instead of
y = f(x);
My objective is to call a void function "sum" which is passed two integers where they will be added together. I then want the first integer variable to be modified so that it is pointing at the sum of the two integers.
When I compile I get "error: indirection requires pointer operand ('int' invalid)."
This should work:
void sum(int *x, int y){
*x += y; // *x means "contents of what is pointed to by pointer x"
}
void call_sum() {
int x = 1, y = 2;
sum(&x,y); // &x because you're passing the address
printf("%d\n", x); // this should print 3
}
In that case you want:
void sum ( int * x, int y ) {
if (x != NULL) *x += y;
}
...
sum(&x, y);
Saying int * y says you need to pass the address of an int variable. The & character is the address-of operator.
In the function *y says use the value at the address, not the address itself.
The if (x != NULL) check is because, without it doing:
sum(NULL, x);
is "undefined behavior" (think Allstate "Mayhem" commercial) :)