Why does the C/++ scanf function need referenced variables as arguments? - c++

Why does the C/++ scanf function need referenced variables as arguments? I was wondering why scanf can't just take in the variable itself, since it gave me a weird warning whenever I didn't put in a referenced variable. It thought I had put in a pointer. Why is that? Thanks.

I don't see how they could modify the value
Here is an example
#include <stdio.h>
void changeNumber(int *n) {
*n = 12;
}
int main() {
int x = 5;
printf("X: %i\n", x);
changeNumber(&x);
printf("X: %i", x);
return 0;
}
Output
X: 5
X: 12

IIRC, scanf() functions are from C and required their arguments to be pointers because the original C did not have a pass-by-reference for parameters at all.
The programmer writing the function had to use pointers (which passed a memory address value) to achieve the result that pass-by-reference would have provided.
I learned to program with Pascal and this (along with the lack of array bounds-checking) was one of the most annoying things about C when I first learned it.
I believe C++ has pass-by-reference but the scanf functions are from the C language stdio so they pass parameters by value.

Think about the difference between two scanf function below:
#include <stdio.h>
void scanf_1(int a) {
a = 5;
}
void scanf_2(int *a) {
*a = 6;
}
int main()
{
int b = 1;
scanf_1(b);
printf("(1) b = %d\n", b);
scanf_2(&b);
printf("(2) b = %d\n", b);
return 0;
}
The output:
(1) b = 1
(2) b = 6
You can see, if you pass by value, the value of b is not changed. But when you use the pointer then pass by reference, the value of b is updated.

Related

Pointer vs Reference

I know this is already a commonly asked question, but I'm more curious about how pointers and references behave at a lower level (like how compiler deals with them, and how they look like in memory), and I didn't find a solution, so here I am.
At first I was wondering if an array can be passed as a parameter without being cast (or decay) into a pointer. More specifically. I would like the following code:
void func(?? arr) {
cout << sizeof(arr) << "\n";
}
int main() {
int arr[4];
func(arr);
return 0;
}
to output 16 instead of 8, which is the size of a pointer.
First I tried
void func(int arr[4]);
Hoping that specifying the size can keep the property of an array, but arr is still treated as a pointer.
Then I found something that worked:
void func(int (&arr)[4]);
But it confused me.
In the past I was under the impression that although pointers and references had different meanings, they had the same behavior when the code was actually executed.
I got that idea from my own experiments:
void swap(int* a, int* b) {
int c = *a;
*a = *b;
*b = c;
}
int main() {
int a = 3, b = 5;
swap(&a, &b);
}
and
void swap(int& a, int& b) {
int c = a;
a = b;
b = c;
}
int main() {
int a = 3, b = 5;
swap(a, b);
}
were compiled into the same assembly code, and so did
int main() {
int a = 3;
int& b = a;
b = 127;
return 0;
}
and
int main() {
int a = 3;
int* b = &a;
*b = 127;
return 0;
}
I turned off optimization and both g++ and clang++ showed this result.
Also my thought on the first experiment:
when thinking in terms of memory, swap should have its own stack frame and local variables. Having a in swap directly mapped to the a in main didn't make much sense to me. It was as if the a in main magically appeared in the stack frame of swap, where it shouldn't belong. So it didn't surprise me that it got compiled into the same assembly as the pointer version. Maybe the magic of reference was achieved by a pointer underneath the hood. But now I'm not sure.
So how does a compiler handle references and how do references look like in memory? Are they variable that occupies space? And how can I explain the result of my experiments and the array problem?
The old C idiom is, that arrays get turned into pointers to the array type, when a function is called. And that is mostly still true für C++.
So for the details of it, let's look at two functions taking an integer argument, first:
void f(int x) { x = 42; } // function called with x by value
void g(int& x) { x = 42; } // function called with x by reference
As f() is called by value, a copy of the argument is made, and the assignment x = 42; inside the function has effectively no effect for the caller of the function. But for g(), the assignment of x becomes visible to the caller:
int a = 0, b = 0; // initialize both a and b to zero
f(a); // a is not changed, because f is called by value
g(b); // b is changed, because g is called by reference
std::cout << a << " " << b << std::endl; // prints 0 42
For arrays, the same rules should hold, but don't. So let's try it:
void farr(int x[4]) { x[0] = 42; } // hypothetical call by value
void garr(int (&x)[4]) { x[0] = 42; } // call by reference
And let's call these functions:
int c[4] = { 1, 2, 3, 4 }, d[4] = { 5, 6, 7, 8 };
farr(c); // call by value?
garr(d); // call by reference
for(unsigned i = 0; i < 4; i++)
std::cout << c[i] << (i < 3 ? ", " : "\n");
for(unsigned i = 0; i < 4; i++)
std::cout << d[i] << (i < 3 ? ", " : "\n");
The unexpected result is, that the farr() function (unlike the f function before) does modify its array, too. The reason is an old C idiom: Because arrays must not be copied directly by assignment, functions cannot be called with arrays by value. Therefore array declarations in parameter lists are automatically converted into a pointer to the first element of the array. So the following four function declarations are syntactically identical in C:
void farr1(int a[]) {}
void farr2(int a[4]) {}
void farr3(int a[40]) {}
void farr4(int *a) {}
Being compatible with C, C++ took over that property. So it is not a syntactical error (but likely causes undefined behaviour!) to call farr2() or farr3() with an array of different size. Furthermore, though, references come in in C++. And yes, as you already suspected, a reference to an array is internally represented as a pointer to the first array element. But, and that is the advantage of C++: If you call a function, that expects a reference to an array (and not just an array or a pointer), the size of array is actually validated!
So, calling farr() with an int-Array of size 5 is possible, calling garr() with the same leads to an compiler error. That gives you better type checking, so you should use it, whereever possible. And it even allows you to pass the array size to a function by using a template:
template<std::size_t N>
void harr(int (&x)[N]) { for(std::size_t i = 0; i < N; i++) x[i] = i*i; }

C++ passing by reference function [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
The code snippet is as follows
#include <iostream>
using namespace std;
int a(int m)
{
return ++m;
}
int b(int &m)
{
return ++m;
}
int c(int &m)
{
return ++m;
}
int main(void)
{
int p=0,q=0,r=0;
p+=a(b(p));
q+=b(a(q));
r+=a(c(r));
cout<<p<<q<<r;
return 0;
}
The error occurring is invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int' at q+=b(a(q)). How to go about the error so that this program prints a desired output
Timothy J Williams is one or both of the following things:
wrong;
teaching C++ as it pertains to Visual Studio only, without disclaiming it, which is ill-advised.
References cannot bind to temporaries. It is not allowed in C++. Visual Studio allows it as a non-standard extension, but that's it. Some people get confused and think that means it's valid C++. It's not.
You will have to store the results of function calls like b(1) into named variables before you pass them anywhere by reference.
int main()
{
int p = 0, q = 0, r = 0;
int result_of_b_p = b(p);
p += a(result_of_b_p);
int result_of_a_q = a(q);
q += b(result_of_a_q);
int result_of_c_r = c(r);
r += a(result_of_c_r);
std::cout << p << q << r << '\n';
}
I should also note that the cited code is confusing and appears to serve no purpose other than for contrived "test your knowledge" challenges. I'd pay not too much attention to this and instead learn C++ from a proper book. After all, Timothy Williams claims that the above program outputs 322; it doesn't.
You cannot pass by reference a constant.
To break down your code.
int a(int m){
return ++m;
}
This will return an int (constant, eg. 5)
Then in
int b(int &m){
return ++m;
}
You are now technically passing in an integer (constant) not a variable into B. You must pass B in as a variable.
Try exactly what you have but passing in
int x = a(your_number_here);
int z = b(x);
EDIT:
int main(void){
int p=0,q=0;
int x = 5;
p = a(x);
q = b(p);
cout << q << endl;
return 0;
}
Returns 7.
The error is a result of trying to call a function that takes a reference with a value. It would be like calling b with a value literal b(1). That can't work...
The function call is where you pass by reference. See below:
void foo (int* m)
{
(*m)++;
}
int main (void)
{
int a = 0;
foo (&a);
cout << a << endl; // prints 1
}
So here b(int& m) takes a reference to an integer. Think about it this way. A reference is a "safe pointer" for which the compiler automatically handles the dereferencing operations.
The return value of a(int m) is a temporary, i.e. it is a temporary value that goes out of scope as soon as the function returns and its value has been utilized in some way. So you can do x = a(15); and x will become a copy of the returned 16. This is what an r-value is. A sort of "temporary" (r because it is on the right side of the expression). So when you have a pointer to a temporary value it does not make sense in most cases. For example in the following code
int* return_local() {
int a = 10;
return &a;
}
This will give you a compiler warning. Because you don't want to bind a pointer to a value which will go out of scope. Similarly you don't want a reference to an object that will go out of scope as soon as the function has returned and its value has been utilized. That is why there is an error in your code. a(int m) returns an r-value and when you do b(a(q) you are trying to bind a reference to an r-value
Now there is something called an r-value reference which takes the form void some_func(int&& rvalue_reference) in syntax. The && means r-value reference not reference to reference. Look it up if you are interested.
It's not allowed to pass a r-value as a non-const reference argument. This happens in the line whereyou call the function b with a(q) as its argument, which is an r-value (an expression which is not a simple variable).
So you need to first call a and store itsvalue in a variable, and then pass this variable to b:
int main(void)
{
int p=0,q=0,r=0;
p+=a(b(p));
int t=a(q);
q+=b(t);
r+=a(c(r));
cout<<p<<q<<r;
return 0;
}

Inconsistency in passing by reference - how does this simple example of passing by reference work?

I had a simple question and was hoping for the underlying logic behind passing by reference.
Here's one code (let's call it Code1):
void fn(int& a)
{
a = 6;
}
int main()
{
int b = 5;
fn(b);
cout << b;
}
Here's another code (Code2):
void fn(int* ptr)
{
*ptr = 6;
}
int main()
{
int b = 5;
fn(&b);
cout << b;
}
And a pass by value code (Code 3):
void fn(int a)
{
a = 6;
}
int main()
{
int b = 5;
fn(b);
cout << b;
}
Here goes my question. Intuitively, I see that while passing by value (Code3), the values are copied ie a would just have taken/copied into itself the value of b. Thus, as a general rule, I see that value passed is just copied always to the called function (here fn). Even with the pointer code (ie Code2), the first line of Code 2 ensures that int *ptr = &a;
I don't understand how this would work in Code1. Saying that &a = b makes no sense. Is this an exception, or does this fit into a rule that is consistent with the cases discussed in the paragraph above?
Thanks!
In this function:
void fn(int &a) {
a=6;
}
the term "&a" does not mean "the address of the variable a". It means "a reference called a". Code 1 and Code 2 are effectively the same (but note that the function in Code 2 can be passed an invalid pointer, which is (almost) impossible for Code 1).
For most intents and purposes, a reference is just a pointer in disguise. Different syntax, same effect (mostly).
Conceptually, in your first case what happens is that the same variable has two labels: b, visible within the scope of main(); and a, visible within the scope of fn.
You don't have to worry about what the compiler does "behind the scenes" to implement this concept.
If you mentally promote the compiler's "behind the scenes" actions to actually being imagined principles of C++, e.g. "the reference is a pointer in disguise", then it leads you to get confused about what is actually a pretty simple concept: the ability to give multiple names to a variable.
It is nothing special being a function parameter; e.g. you could write in main():
int a;
int &c = a;
which is exactly equivalent to:
int c;
int &a = c;
In both cases there is an int variable with two labels, a and c.

function call with function pointer in c++

Here's the code:
#include<iostream>
using namespace std;
typedef struct ptrs
{
int (*addptr)(int a, int b);
}mems;
int add(int a, int b)
{
int result = a+b;
return result;
}
int main()
{
mems ptrtest;
ptrtest.addptr = &add;
int c = (*ptrtest.addptr)(3,4);
//int c = ptrtest.addptr(3,4);
cout << c << endl;
return 0;
}
if I replace the code int c = (*ptrtest.addptr)(3,4); with it's next line(annotated now), the result will be the same, why is that?
Of course, int c = (*ptrtest.addptr)(3,4); is the base case. However, in C++ (and in C as well), if you use the call (()) operator on a function pointer, it will do the "dereferencing" automatically. Just like when assigned to a variable of function pointer type, the name of a function decays into a function pointer, i. e.
int (*fptr)() = some_func;
is just as valid as
int (*fptr)() = &some_func;
albeit the type of func is int ()(void).
Functions and function pointers can be used interchangeably, presumably for convenience. In particular, section 5.2.2 of the C++11 standard specifies that a function call can occur using a function or a pointer to a function.
C++ will automatically cast a function name to a function pointer (and vise versa) if doing so will create correct syntax.

Understand Reference and Dereferencing Operators?

Can someone please help me understand Reference and Dereference Operators?
Here is what I read/understand so far:
int myNum = 30;
int a = &myNum; // a equals the address where myNum is storing 30,
int *a = &myNum; // *a equals the value of myNum.
When I saw the code below I was confused:
void myFunc(int &c) // Don't understand this. shouldn't this be int *c?
{
c += 10;
cout<< c;
}
int main()
{
int myNum = 30;
myFunc(myNum);
cout<< myNum ;
}
int &c has the address to what's being passed in right? It's not the value of what's being passed in.
So when I do c+=10 it's going to add 10 to the memory address and not the value 30. Is that correct?
BUT... when I run this...of course with all the correct includes and stuff...it works. it prints 40.
Actually the ampersand in the function parameter list for myFunc is not an address operator, nor a bitwise and operator. It is a reference indicator. It means that within myFunc, the parameter c will be an alias of whatever argument is passed to it.
You have a few issues here.
your second line of code int a = &myNum; // a equals the address where myNum is storing 30 is wrong;
you can combine it with line 3 like so:
int *a = &myNum; // a equals the address where myNum is stored;
*a == myNum.
The type int & is read as "reference-to-int". Perhaps the Wikipedia article can help you understand what this means.
Both pieces of code are valid and your understanding of pointers in the first piece of code is correct. However, the ampersand (&) in the two pieces of code are actually different things. (Like how * is both the dereference and multiplication operator)
The second piece of code shows how the & can be used to pass variables to a function by reference. Normally if you had code like this:
int a;
void foo(int bar) {
bar = 3;
}
int main() {
a = 5;
foo(a);
// a still equals 5
}
The call to 'foo()' does not affect the variable you passed to it (bar or in this case, a). However if you changed this line:
void foo(int bar) {
to
void foo(int &bar) {
then it would affect the variable and at the end of the program above, the value of a would be 3.
In C++ when you pass things by reference using int &c you don't need to dereference. You only need to dereference pointers. If it was int *c then it would be necessary. Just remember in both cases you change the value of what was passed in the original caller so myNum is now 40.
Let's have a look at the assumptions first:
int myNum = 30;
// this won't compile. &myNum is the address of an int (an int *), not an int:
int a = &myNum;
// *a is a pointer to an int. It received the address of myNum (which is &myNum),
// and not its value
int *a = &myNum;
About the code:
void myFunc(int &c)
// c is passed by reference. This is a kind of "hidden pointer" that
// allows using the variable as if it was not a pointer but the pointed variable.
// But as this reference and the variable that was passed by the caller (myNum
// in your example) share the same address (this is the property of a reference),
// any modification of the value of c inside myFunc modifies it in the
// caller's scope too (so here, it modifies myNum).
{
c += 10;
cout<< c;
}
int main()
{
int myNum = 30;
myFunc(myNum); // displays 40
// What follows displays 40 as well, due to the fact
// c was passed by reference to myFunc that added 10 to it
cout<< myNum ;
}
So when I do c+=10 it's going to add 10 to the memory address and not
the value 30. Is that correct?
No, 10 was added to the value of c by myFunc.
As c is a reference (a "hidden pointer to") that received myNum, myNum was modified as well.