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

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.)

Related

Incrementation using functions

I want to increment the value of a integer using functions in C.
So first I wrote a function inc where I incremented the value of integer v. Then in main function I declared a new variable a and incremented using inc(a) function.
Here is my code:
#include<stdio.h>
void inc(int v)
{
v++;
}
int main()
{
int a;
scanf("%d",&a);
inc(a);
printf("%d",a);
return 0;
}
But the output is same as the input value. It is not incrementing.
i.e If I give the input as 45,I am expecting the value 46 as output. But the output is still 45. Where am I going wrong? Someone please explain.
So I've done some research and found that the expected answer is coming when pointers are used and here is the code for that
#include<stdio.h>
void inc(int *v) {
(*v)++;
}
int main() {
int a;
scanf("%d", &a);
inc(&a);
printf("%d", a);
return 0;
}
Why is the method without pointers is not correct?
Also in the second method why are we passing the argument as address i.e &a. Why can't we pass it as a?
I'm a newbie to C .So please help me with my doubts
The problem is that by default c uses pass by value for functions. That means that if your calling the function the following way in your main,
int a = 45;
inc(a);
the function only gets to know the value 45 but not the variable a. It will therefore make a new local variable (int v in your case) that stores the value 45 and gets incremented. Since the function does not know anything about a, in particular not where a is located in memory it can not modify it. There are generally two ways to solve this:
Using returns:
In this case the function keeps manipulating a local copy with the values of the arguments passed. In the end it can return the desired output of the function. This would be implemented the following way:
#include<stdio.h>
void inc(int v)
{
v++;
return v
}
int main()
{
int a;
scanf("%d",&a);
a = inc(a);
printf("%d",a);
return 0;
}
Passing the argument as a pointer:
In the second case, that you already found, your passing your argument by reference. This way the function gets to know the memory address of a and can therefore manipulate the value stored at a directly. The little star icon next to v in the function definition void inc(int *v) defines that the function takes an address as an input. Therefore, you have to pass the address of a by using &a as done in the code you posted.
Summary:
Your function, or any future functions you implement can be one of the two types above according to your needs. It should however, as a guideline, never manipulate values at passed addresses and return something at the same time. This can lead to confusion and results in a less readable code in general.
"Why is the method without pointers not correct?"
If you use a pointer parameter, your intention is to point to an object in the caller. You can then modify this object in the called function. This is what is called pass by reference. You pass a reference to an object in the caller.
If you don't use a pointer, you just pass the value of the variable by value to the function, which means the value of the argument is assigned to a function-local variable. Inside of the function you can modify only the value of this function-local variable, but not an object in the caller.
What's the difference between passing by reference vs. passing by value?
Also in the second method why are we passing the argument as address i.e &a. Why can't we pass it as a?"
The & operator gains in this case the address of a, which is needed to be assigned to the pointer parameter.
A pointer always stores an address of an object to point to, not a value of the pointed object.
Without address, the pointer doesn't denote an object.
Please learn more about pointers and read a good C starting book like Modern C (You can get a free copy of it there).
This and others you can also find here:
The Definitive C Book Guide and List
It is usually explained in the first few chapters about functions and argument passing.
You always pass a copy of your variable, value or reference, to the function. So, sending a copy of the value will not affect the main function. However sending a copy of its reference will affect the main function because you say where your variable is in the memory.
Also in the second method why are we passing the argument as address i.e &a. Why can't we pass it as a?
You're here manipulating with pointer, when you change the value of address to that pointer, then the original value is also get changed.
In the other hand, when you pass the variable a by-value, it'll just make a copy and increment it in the function call, no changes will occur in the original value. The first method doesn't works because the variable passed in the function was pass-by-value type.
Edit: This question is now only tagged in C. But for extra inforamtion, there's a method to do it without pointers in C++, it's called pass-by-reference (manipulates with original copy of variables) which could be represented by an ampersand sign on the function signature, something like:
void changeRealValue(int& value) {
// _____________________^________
value++; // original value is incremented now
}
Short answer:
C is default pass by value. If pointer is not specified, a v in inc is just a copy of a in main with the same value.
That is, v++ would increase v in scope of inc but effects no others.
For pointer, (*v)++ means "add one value to where v points to"
If you're using C++, passying by reference is another solution.
Pointer is a variable containing the address of an object. The pointer does not carry information about the contents of the object, but contains information about where the object is located.
Pointers are widely used in C programming.
Pointers are often used when working with arrays.
Computer memory can be thought of as a sequence of numbered single-byte cells that can be accessed individually or in blocks.
Each variable in memory has its own address - the number of the first cell where it is located, as well as its value. A pointer is also a variable that is allocated in memory. It also has an address, and its value is the address of some other variable. A variable declared as a pointer occupies 4 bytes in RAM (in the case of a 32-bit version of the compiler).
A pointer, like any variable, must be declared.
сhar c; // variable
char *p; // pointer
p = &c; // p = address of c
Look at this exammple:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a, *b;
system("chcp 1251");
system("cls");
a = 134;
b = &a;
// %x = display the number in hexadecimal form
printf("\n The value of the variable a is %d = %x hex.", a,a);
printf("\n The address of the variable a is %x hex.", &a);
printf("\n Data at pointer address b are equal %d = %x hex.", *b,*b);
printf("\n The value of b pointer is %x hex.", b);
printf("\n Location address of pointer b is %x hex.", &b);
getchar();
return 0;
}

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.

C -- Modify const through aliased non-const pointer

Is it allowed in standard C for a function to modify an int given as const int * using an aliased int *? To put it another way, is the following code guaranteed to always return 42 and 1 in standard C?
#include <stdio.h>
void foo(const int *a, int *b)
{
printf("%d\n", *a);
*b = 1;
printf("%d\n", *a);
}
int main(void)
{
int a = 42;
foo(&a, &a);
return 0;
}
In your example code, you have an integer. You take a const pointer to it, and a non-const pointer to it. Modifying the integer via the non-const pointer is legal and well-defined, of course.
Since both pointers are pointers to integers, and the const pointer need not point to a const object, then the compiler should expect that the value read from the const pointer could have changed, and is required to reload the value.
Note that this would not be the case if you had used the restrict keyword, because it specifies that a pointer argument does not alias any other pointer argument, so then the compiler could optimise the reload away.
Yes and yes. Your program is defined.
The fact that you point to an non-const int variable with a pointer to a const int, doesn't make that variable const and may be still modified trough a pointer to an int or by using the original variable label.
Yes you can do this (if you know you can get away with it).
One reason you may not be able to get away with it, is if the destination memory you are writing to is in a read-only protected areas (such as constant data) then you will get an access violation. For example any const's at compile time that end up in read-only data sections of the executable. Most platform support protecting it from being written to at runtime.
Basically don't do it.
There are other issues with your example that probably don't make it the best demonstration. Such as needing a reload of *a in the 2nd printf the compiler may optimize it out! (it knows 'a' did not change, it know's 'a' points to a const, therefore, it does not need to reload memory by preforming a memory load for the 2nd '*a' expression, it can reuse the value it probably has in a register from the 1st time it loaded '*a'). Now if you add in a memory barrier between, then your example has a chance of working better.
https://en.wikipedia.org/wiki/Memory_barrier
GCC ? asm volatile ("" : : : "memory"); // might work before 2nd printf
But the principal for the actual question you asked, yes you can do it if you know what you are doing about other stuff like that.
Yes, it is guaranteed to always print 42 and 1.
const int *a means the value pointed to is a constant for pointer a.
Try dereferencing from a (*a = 10;) in the function and you will get an error.
The pointer a however is not constant. You can do a = b for example.
b can point to the same address as a and/or modify the value, as you did in your example.
Would you declare b pointer's value to be constant (const int *b), you would receive an error.
I try to memorize like this:
const int *a - a points to an object of type int, which it is not allowed to modify (any other pointer to that object can do what it wants, depends on its declaration/definition).

When to return a pointer, pass a pointer as a parameter or not use them at all?

I am currently experimenting with C, and I am having a really hard time understanding how to use pointers in functions. I understand what is happening when I initialize a pointer then dereferencing it, however, I get a little confused when I have to use them in functions as follows:
I have three functions here, but I do not know exactly when to use which. I am still relatively new to C.
int returnSomething(int a, int b)
int returnSomething(int *ptrA, int *ptrB)
int* returnSomething(int *ptrA, int *ptrB);
edit:
Is there a major difference between the three?
You need to adapt your usage to every situation.
The first case, you take two ints by value as parameters and return an int. Because your parameters are by value, any changes applied to them will only have function scope.
For example:
int returnSomething(int a, int b)
{
a = 0;
b = 0;
return 0;
}
//....
int x = 3;
int y = 4;
returnSomething(a,b);
// x will still be 3, y will still be 4
In the second case, because you pass parameters as pointers, you will be able to change the values.
int returnSomething(int* a, int* b)
{
*a = 0;
*b = 0;
return 0;
}
//....
int x = 3;
int y = 4;
returnSomething(&a,&b);
// x and y will be 0 here
The third case, besides passing parameters by their pointer, you return a pointer to an int. This means inside the function you have to allocate memory and free it when you are done. I don't recommend using this, there usually are workarounds to doing it.
int* returnSomething(int* a, int* b)
{
int* x = malloc(sizeof(int));
*x = 1;
return x;
}
//....
int x = 3;
int y = 4;
int* z = returnSomething(&a,&b);
free(z);
The answer is, it depends on what you want to do. If you need to change the parameters value in the method, pass by reference or by pointer. I wouldn't recommend using the last method.
Also, this applies because you're dealing with POD types. If you have your own struct, it will be more efficient passing it by pointer or returning a pointer, since a new copy won't have to be made.
Let's explain passing by reference to you first; it's a lot less complicated to deal with.
Say you have:
int increment(int &a)
{
a = a + 1;
return a;
}
increment(foo); // foo = foo + 1;
(NOTE: To make it easier to understand, I've sacrificed some 'correctness'.)
This does two things:
The third line increments a by 1. But notice - we put &a in the function declaration. This means that the value passed to increment() "by reference" is also incremented by 1. In other words, foo increases by 1, just like a.
The fourth line returns the value of a - a number, such as 1, 2, 42, -21, etc.
One more thing: Passing by reference is C++; you can't use it in C, but it's a good concept to learn before you start messing with pointers.
Passing a pointer is basically just passing by value... except you're passing the location in memory (0x12345678), as opposed to the actual foo.
int pincrement(int *p)
{
*p = *p + 1;
return *p;
}
pincrement(&foo); // foo = foo + 1;
This does the same thing as our first program - it increments the value of foo.
The &foo tells you the address of foo in memory. This information is passed to p. So:
p = &foo;
On the third line, the value pointed to by *p is incremented. In other words, foo is incremented by 1.
The fourth line returns the value of foo - a number, such as 1, 2, 42, -21, etc.
For returning pointers, you could use them to return strings:
char *HelloWorld()
{
return "Hello, World!";
}
The answer to your question has more to do with memory considerations and good code design i.e. whether you'd like to conserve resources and if you are aware of what's going on in your code at any one instance in time.
1) when you pass by value ( int returnSomething(int a, int b) ) every parameter is a copy and any changes made to them doesn't affect the original variable outside of the function (The parameters have function scope), and the function returns a value which you can then use to initialise a variable.
2) When you pass by pointer, you're passing an address to a location in memory so remember that as a matter of good code design you have to insulate that location against modification by another external (lock semantics) process. This especially applies to your provided examples:
int returnSomething(int *ptrA, int *ptrB)
int* returnSomething(int *ptrA, int *ptrB);
wherein changes made to *ptrA and *ptrB within the function persists after the function exits. The only difference between the two is that one of the functions return a value which you can then use to initialise a variable ( int returnSomething(int *ptrA, int *ptrB) ), the other returns another address to a location in memory that maybe subject to change and/or garbage headaches depending on your program design (you create memory inside the function for the return type and assign that address to a pointer variable, the pointer variable itself can be arbitrarily changed to point to another location in memory, e.t.c.). I'll expand on Luchian's last example by adding: imagine some somewhere else in your code you pass the *z variable to another function which then tries to use the memory pointed to by that address, you now have a pointer variable pointing to nothing which you then try to use.
It all boils down to good code design. If you understand the pros and cons of pointers and use them appropriately then you'll have no issues.
Luchian Grigore has written some good description above. I would like to give you a small thought to further simplify your thinking.
When ever you pass a argument to a function in C, try to think what exactly goes on to the stack ( in case 1, actual integer variables gets pushed onto stack and in case 2 & 3 adresses of those integer variables gets pushed ), now to this combine that fact that changes made to variables on stack vanish as soon as the control returns from funciton and stack unwindes.
So in simple terms if you plan to change the varibales being passed inside the function and expect to use those changes later then consider passing the address of those varibles, else simply pass variables.
For int, always pass by value unless it is not possible to do so.
i.e int returnSomething(int a, int b).
When you are passing some custom big struct, pass it and return it as a pointer unless it is not possible to do so.

Passing arrays, pointers to int in C

I'm new to C for numerical analysis after many years of working with Matlab. I have a function that constructs an array and I need to get it back to main(). I had the usual trouble with arrays vs. pointers, and by fiddling figured out how to do this. But the fiddling left me with a conceptual question based on the following code.
#include <stdio.h>
void array_set(int y_out[2][2]);
void int_set_wrong(int y);
void int_set_right(int *y);
int main (int argc, const char * argv[]) {
int y_array[2][2]={{0,0},{0,0}};
int y_int_1 = 0;
int y_int_2 = 0;
array_set(y_array);
int_set_wrong( y_int_1 );
int_set_right( &y_int_2 );
printf("\nValue array: %d \n",y_array[0][0]);
printf("Value int wrong: %d \n",y_int_1);
printf("Value int right: %d \n",y_int_2);
return 0;
}
void array_set(int y_out[2][2]){
y_out[0][0] = 10;
y_out[1][0] = 20;
y_out[0][1] = 1;
y_out[1][1] = 2;
}
void int_set_wrong(int y){
y = 10;
}
void int_set_right(int * y){
*y = 10;
}
The snippet above returns:
Value array: 10
Value int wrong: 0
Value int right: 10
My question is in a few parts,
first, why does the function 'array_set' work? I would expect it to fail in the same way that 'int_set_wrong' did.
How are ints and int arrays treated differently in passing?
Furthermore, in the case of 'int_set_wrong', is there a local version of y?
If so, why is there not a local version of y_out in case of setting the array?
Thanks for the help. As an aside, if there is anything that will cause problems with my implementation of array_set, please chime in.
--Andrew
In int_set_right() you passed the address of the variable y_int_2 (which you declared and defined in main()) through the operator &.
int_set_right( &y_int_2 );
Since the function had access to the actual variable y_int_2 through the pointer y (set to the value of the address of y_int_2 from &y_int_2), you assigned y_int_2 the value 10 when you assigned *y = 10.
You can read *y = 10 as:
the value of the variable whose
address is stored in y is now set to
10
But for y_int_1, you merely passed the value. So a temporary variable was created when you called int_set_wrong() which was initialized with the value of y_int_1. So all you did was change the value of the temporary of the local variable (local to int_set_wrong()).
This is why the y_int_1 declared in main() is not affected by int_set_wrong().
array_set works because you passed the address of y_array to the function through the y_out variable (which is a pointer like y in int_set_right).
Arrays are passed using pointers rather than the entire array being copied by value on the stack. Your two dimensional array makes explaining this tricky, but consider a one dimensional version:
void f(int x[]){
x[0] = 1;
x[1] = 2;
}
You could equivalently write this as:
void f(int *x){
x[0] = 1;
x[1] = 2;
}
These two declarations are identical, but I'm sure you can see that modifications made in the the second version are propagated back to the caller.
The function array_set works because when you pass an array into a function, you are really passing a pointer. Then, inside the function, you are de-referencing the array using "y_out[0][0] = 10" etc. When you use array notation, it automatically de-references the array pointer so you are able to set the values within the array.
Ints are completely different from int arrays. An array can be treated in almost every case as a pointer, in this case a pointer to int. An int is an actual numerical value. Therefore, when you pass an int into you're int_set_wrong function, it is copied (that's just what C/C++ does), and you are setting a local variable y, not the int you passed in.
You're third question is answered in the first paragraph as well. Hope this clears things up.
Your function works because in C the inner most [] in function arguments (and only there!) is equivalent to a pointer argument. Your declaration is equivalent to
void array_set(int (*y_out)[2]){
..
}
That is y_out is a pointer to int[2].
You've created 3 functions.
array_set(y_array);
Prior to this you have created an array of numbers with the line.
int y_array[2][2]={{0,0},{0,0}};
In C when you declare an array you created a pointer in your code with the name y_array the array is stored somewhere in the memory and the pointer is pointing is holding the position of the location.
So essentially its a normal pointer with a big amount of memory allocated after it.
When you pass the array to save memory and time C by default passes the pointer.
void int_set_wrong(int y);
When you pass an int it copies the value to a local variable as a result, you don't hold any address to that variable outside that function.
When you pass the reference of an int you supply the function with the address of your int variable. As a result, the function can make changes there.
As the first and third call is sharing the location of the main variable you can see the change from the main. For the second one there is no sharing of address. So the function creates its own variable which cannot be accessed from outside.

Resources