Using the &-operand when passing a pointer to a function? - c

int enter_path(char** path) {
char* standard = "./questions.txt";
printf("\n\t%s\n\t%s",
"Please enter the file location.", "path: ");
fgets(*path, MAX_PATH_LENGTH ,stdin);
*(*path + (strlen(*path)-1) ) = '\0';
if(**path == '\n' )
*path = strdup(standard);
return 0;
}
int main(void){
char* path = malloc(MAX_PATH_LENGTH);
enter_path(&path);
some_other_function_using_the_path_string(path);
}
the code above works fine, the reason why i'm posting this is the following.
Why do i have to pass the adress of the pointer "path" to the function enter_path, so some other function can use/read the modified value.
So in short, Why do i have to use the &-operand when calling the "enter_path" function, and can't define enter_path as "int enter_path(char* path);"
I know this is normal variables refering to datatypes like int, long, etc.
but i assumed that when working with pointers the change should be visible for every other function. cause the pointer still referes to the same point in the memory, just the value has been changed.
Could it be i'm seeing this all wrong?
PS: I'm trying my best to keep my code ansi-C compliant, which is the reason i'm using fgets instead of readline. Just sayin that cause i've allready got some comments regarding the fact that the readline function is easier/safer to use.
With kind regards,
JD

If you have a variable of type T that you want a function to be able to modify, you need to pass it via a pointer, i.e.:
void foo(T *p) { *p = 42; }
int main(void) {
T t;
foo(&t);
// The value of t is now 42
}
In your code, T is char *; in other words, your function needs to be able modify a pointer, so you need to pass it a pointer to that pointer.
However, this is not good code. If (**path == '\n') is true, then you will leak memory.

The reason is that if you specify the parameter type as char *, you will operate on a copy of the pointer in the function, so your code (modified for this scenario)
path = strdup(standard);
Would not reflect back in the caller after the function ends
By passig the address of the variable, you can change the pointed-to pointer and this change will persist even after the function returns
Think of the pointer as your data (just like with int, etc.) by passing a char * pointer you can modify the pointed-to characters; by passing a char ** pointer, you can modify the pointed-to pointer (with the modification reflecting in the caller function as well).

You are passing a variable path that is itself a pointer.
But you are modifying the pointer itself in the function enter_path, hence you will have to pass the pointer to path and hence the address of path is to be passed and hence &path is passed.
In the current scenario, the line
*path = strdup(standard);
it does modify the variable path in the function but it's value will not change outside the function, i.e. in function main.

Related

Why are pointers such a big deal in C?

I understand the premise of pointers, but I find it very annoying, and I don't get why it's considered useful;
I've learned about pointers, and the next thing I know, I start seeing bubbles, asterisks, and ampersands everywhere.
#include <stdio.h>
int main () {
int *ptr, q;
q = 50;
ptr = &q;
printf("%d", *ptr);
return 0;
}
why is this important or useful?
First, parameters passed to a function can only be primitives(int, char, long....), structs or pointers. Then if you need to pass a more complex element like an array (strings) or a function, you have to pass a reference to this element.
The second things that I can quickly think of is: parameters are always passed by "value". This means the called function only get a copy of your variable. So, modifications will only affect the copy, the original variable will remain unchanged.
If you pass a variable by "reference" with a pointer, the pointer itself is immutable but as it is a reference to the original var, any modification to the pointed element will also affect the var in the caller function.
In other words, if you want to create a function that can alter a variable, you have to pass it a pointer to that variable to achieve this.

How do you use scanf to get an int in C?

I'm trying to learn the benefits and shortcomings of different ways to get input from the console. I'm confused with scanf. Why do I need to use use &favNumber instead of favNumber?
I understand that &favNumber is the address location of favNumber, but why is it done this way?
I feel like there's a type mismatch here where favNumber is an int and I'm telling scanf that it's a pointer to an int. I thought I wrapped my head around pointers but this is confusing me a bit. Any help would be appreciated. Thanks!
#include <stdio.h>
int main()
{
char userPrompt[100] = "What is your favorite number?";
int favNumber;
printf("%s", userPrompt);
scanf("%d", &favNumber);
printf("%d", favNumber);
return 0;
}
When you call a function by value, the function gets a copy of the argument. Any changes to the argument in the function does not affect the value of the original variable.
void foo(int i )
{
i = 20; // The change is local to the function.
}
void bar()
{
int i = 10;
foo(i);
printf("i=%d\n", i); // i is still 10.
}
If you want a function to change the value of a variable, the function must use a pointer type and the calling function must use the address of the variable when calling the function.
void foo(int* i )
{
*i = 20; // The change is visible in the calling function
}
void bar()
{
int i = 10;
foo(&i);
printf("i=%d\n", i); // i is now 20.
}
This is why scanf expects pointers and the calling functions must use the address of variables when calling scanf. scanf must be able to set the values of the variables.
An & sign is used to reference a value by its memory address. So when a reference is passed around the use of that reference modifies the value at the address the reference holds.
scanf is basically just a function, if you are familiar with functions you will see that a parameter passed in to a function by value will be local to the function and any assignment to it will only change its value within the function(which does not answer the need of storing the "scanned" value in the passed variable). In case of scanf it accepts a reference(in other words the location in memory of that value) so it can modify the value at that location and the "scaned" value can be stored in the variable of interest.
So to wrap it up what &favNumber does is passing to scanf the memory address of favNumber variable which in it self is an int, so an int value is then written to that address and can be accessed by favNumber.
"How do you use scanf to get an int in C?"
– you don't. You use a saner approach (e.g. fgets() + strtol()), because scanf() is quirky and clumsy and hard to use correctly.
However, your question is apparently not about this; you are asking why you have to write scanf("%d", &favNumber); when &favNumber is an int * but %d specifies an int.
Well, you seem to be confusing type safety/type mismatches with arbitrary denotation of types expected by library functions.
&favNumber is indeed a pointer to int. However, the %d specifier does NOT mean that "you must pass an int for this argument". %d is a library-defined notation that tells scanf() to scan an integer, and put it into the next argument. In order scanf() to be able to modify your argument, you need to pass a pointer to it, and indeed this function expects that you pass a pointer to it.
I could put it this way: "%d" simply means something different when used with printf() and scanf(): in the former case, it means you pass an int argument, in the latter case, it means you should pass an int *.
Again, that is the case because these format strings have no inherent semantics. It's the formatted input/output functions that interpret them – in this case, they interpret format strings differently for technical necessity reasons.
Alright so what I believe you're confusion is coming to is the fact that '&' denotes an address, not a pointer to an address as '*' denotes but an address itself. You re telling the scan function where it will store the value that is received from the user.
If you were to reference the variable itself ie 'favNumber' how would you know where to store the value that you've placed into stdin? favNumber is just a container, it's nothing special but just a place in memory that is allocated to hold said amount of bytes. I feel as if I understand where your question is coming from, but if you've already encountered pointers, I think you may be confusing the two. A pointer points to an address in memory, the '&' denotes the actual address, and does roughly what a pointer would do, but to a non pointer variable.
If favNumber were a 'int *' type then you would not need the ampersand, as that is already an address, but you would need to dereference that address to be able to tell what is within it. That is roughly what you have within favNumber, a dereferenced address pointer that shows what is stored in the address of favNumber, that is allocated at the beginning of your program being run, in the stack.

What is C-equivalent of reference to a pointer "*&"

Could someone please let me know the C-equivalent of reference to a pointer "*&"?
In other word, if my function is like this in C++:
void func(int* p, int*& pr)
{
p++;
pr++;
}
How would I changed the second argument while converting it in C?
UPDATE:
#MikeDeSimone : Please let me know if I understood the translated code properly?
Let me start by initializing variable:
int i = 10;
int *p1 = &i;
int **pr= &p1;
So, when you performed (*pr)++ , that is basically equivalent to:
(p1)++
However, I fail to understand how would that look from inside main()?
Question 2: what would I do if I have code snippet like this?
void pass_by_reference(int*& p)
{
//Allocate new memory in p: this change would reflect in main
p = new int;
}
You use a pointer to a pointer.
void func(int* p, int** pr)
{
p++;
(*pr)++;
}
See, for example, the second parameter to strtoul, which the function uses to return the point at which parsing stopped.
Sorry for the late update...
Please let me know if I understood the translated code properly? Let me start by initializing variable:
int i = 10;
int *p1 = &i;
int **pr= &p1;
So, when you performed (*pr)++ , that is basically equivalent to:
(p1)++
Yes.
However, I fail to understand how would that look from inside main()?
I don't understand how main comes into this; we were talking about func. For this discussion, main would be a function like any other. Variables declared within a function only exist during execution of that function.
Question 2: what would I do if I have code snippet like this?
void pass_by_reference(int*& p)
{
//Allocate new memory in p: this change would reflect in main
p = new int;
}
The thing to remember about references passed into functions is that they are just saying "this parameter is a reference to the parameter passed to the function, and changing it changes the original. It is not a local copy like non-reference parameters."
Reviewing references in practice:
If your function is declared void func(int foo); and called with int k = 0; foo(k); then a copy of k is made that func sees as foo.
If func changes foo, k does not change. You will often see functions "trash" their passed-in-by-copy parameters like this.
If your function is declared void func(int& foo); and called with int k = 0; foo(k); then a reference to k is made that func sees as foo.
If func changes foo, it is actually changing k.
This is often done to "pass back" more values than just the return value, or when the function needs to persistently modify the object somehow.
Now the thing is that C doesn't have references. But, to be honest, C++ references are C pointers under the hood. The difference is that references cannot be NULL, should not be taken as pointing to the start of a C array, and references hide the pointer operations to make it look like you're working on the variable directly.
So every time you see a reference in C++, you need to convert it to a pointer in C. The referred-to type does not matter; even if it's a pointer, the reference turns into a pointer itself, so you have a pointer-to-pointer.
So what's a pointer, anyway? Remember that memory is just a big array of bytes, with every byte having an address. A pointer is a variable that contains an address. C and C++ give pointers types so the language can determine what kind of data the pointer is pointing to. Thus an int is an integer value, and an int* is a pointer to an integer value (as opposed to a pointer to a character, or structure, or whatever).
This means you can do two general things with a pointer: you can operate on the pointer itself, or you can operate on the object the pointer is pointing to. The latter is what happens when you use unary prefix * (e.g. *pr) or -> if the pointer points to a structure. (a->b is really just shorthand for (*a).b.)

pointer function in C not working

I intend to make my pointer print the value, but it just stops working (no error report from the MinGW) . . .
#include<stdio.h>
void point_here(int *yolo) {
int you = 2014;
yolo = &you;
}
main () {
int *punk = NULL;
point_here(punk);
printf("Punk # %d is not dead\w/.\n", *punk);
}
How do I make this work? And why this does not work? Please explain. I'm new to pointers and C, and still confuse after reading stuff.
C is "call by value"; functions get copies of the caller's values, not references to them. If you change an argument inside the function, nothing happens in the caller's context.
To work around this you need explicit pointers, but even you still can't have a pointer to a local variable inside a function persist beyond the running of that function.
You're passing NULL as an argument to a function which effectively doesn't nothing. Then you try to dereference that NULL pointer which is illegal.
This modified version of your code works well:
#include <stdio.h>
void point_here(int *yolo) {
*yolo = 2014;
}
int main () {
int value = 0;
int *punk = &value;
point_here(punk);
printf("Punk # %d is not dead\w/.\n", *punk);
return 0;
}
As others have said, you have the following issues:
Pointer to a function value doesn't work after the function finishes executing
You aren't passing the pointer to the pointer you are passing the pointer value. (In other words, you aren't editing what you think you are).
I fixed these two issues by passing in a pointer that has already been allocated, then you just modify it in the function. This is one standard way to use pointers. Best of luck!
There are 2 problems. First the pointer variable is pass by value, second the variable "you" is on stack which gets lost once the function returns.
Change the variable you to static like
static int you = 2014;
and change the argument to **yolo;

parameter passing in C function

I have a function written in C
FindBeginKey(KeyListTraverser, BeginPage, BeginKey, key1);
BeginKey is a pointer before function invoking, and I didn't initiate it, like
BeginKey = NULL;
In the FindBeginKey() function, I assign BeginKey to another pointer, and try to print out the current address of BeginKey in the function, it works correct.
But when code returns from function, I try to print out the address of BeginKey again, it shows 0x0.
Why does this happen, and if I want to preserve the address assigned in the function, what should I do?
To pass a value out of a function you have to pass by reference rather than by value as is normally the case with C functions. TO do this make the parameter a pointer to the type you want to pass out. Then pass the value into the call with the & (address operand).
e.g.
FindFoo(FOO** BeginKey);
and call it:
FindFoo(&BeginKey);
and in the function:
*BeginKey = 0xDEADC0DE;
From what I understand, you are calling the function like:
FindBeginKey(KeyListTraverser, BeginPage, BeginKey, key1);
However, when you try to write at the BeginKey address, you're basically passing in a pointer to 0x00. Rather, you need to pass a pointer to BeginKey.
FindBeginKey(KeyListTraverser, BeginPage, &BeginKey, key1);
If this is isn't what you meant, it would certainly help if you posted a code sample.
If you want to modify a parameter in a subroutine, you should pass a pointer of the thing you wanna modify.
void subroutine(int* x) {
*x = 5; // will modify the variable which x points to
x = 5; // INVALID! x is a pointer, not an integer
}
I don't know what all the C parameter passing rules are now, so this answer might be a little dated. From common practice in building applications and libraries that those applications called, the return from a C function would contain status, so the caller of the function could make a decision depending on the status code.
If you wanted the function to modify its input parameters, you would pass those parameters by reference &my_val, where int my_val;. And your function must dereference my_val like this *my_val to get its value.
Also, for performance reasons, and address (by reference) might be preferable, so that the your application did not bother copying the parameter's value into a local variable. That prolog code is generated by the compiler. Single parameters, char, int, and so on are fairly straight forward.
I am so used to C++ that passing by reference in C++ does not require dereferencing. The compiler's code takes care of that for you.
However, think about passing a pointer to a structure.
struct my_struct
{
int iType;
char szName[100];
} struct1;
struct my_struct *pStruct1 = &struct1;
If the structure contains lookup data that is filled in once on initialization and then referenced throughout your program, then pass a pointer to the structure by value pStruct1. If you are writing a function to fill that structure or alter already present data, then pass a pointer to the structure by value. You still get to alter what the structure pointer points to.
If on the other hand you are writing a function to assign memory to the pointer, then pass the address of the pointer (a pointer to the pointer) &pStruct1, so you will get your pointer pointing to the right memory.

Resources