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;
}
Related
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.
I have code like this:
typedef struct _Statistics {
Some code here
} Statistics;
void function1(char *string, Statistics *statistic){
Some code here
function1(string1, statistic);
}
int main(){
Statistics statistic;
function1(string, &statistic);
}
This is probably idiotic question, but I don't understand pointers completely:
I understand why I use & in main function, & send address of variable statistic, so that in function1 I can modify it. But why don't I use & in recursive function1?
Because &statistic (in function1()) is the memory address of the pointer, not the address contained by the pointer.
The type of &statistic is Statistics** in function1().
Few words about pointers
Let's say we define the following variables:
char c = 'a';
char *p_c = &c;
Now, we will print the values and memory addresses of p_c and c:
printf("%c\n", c); // will print 'a'
printf("%c\n", *p_c); // will print 'a'
printf("%p\n", &c); // will print the memory address of c
printf("%p\n", p_c); // will print the memory address of c
printf("%p\n", &p_c); // will print the memory address of p_c
Finally we define a char**, a pointer to a pointer to char:
char **p_pc = &p_c;
printf("%c\n", **p_pc); // will print 'a'
printf("%p\n", *p_c); // will print the memory address of c
printf("%p\n", p_c); // will print the memory address of p_c
Sometimes it helps to write it this way:
void function1(char* string, Statistics* statistic){
The variable statistic is a pointer to Statistics, not the Statistics itself. If you did this in function1:
function1(string1, &statistic);
You would be passing a pointer to (because of the &) a pointer to (because of the * in the declaration) Statistics, which would be incorrect.
Your declaration of statistic in main as Statistic adds to the confusion: you're using the same variable name with different types in the two scopes.
With different variable names it's clearer:
typedef struct _Statistics {
Some code here
} Statistics;
void function1(char* string, Statistics* ptrstat){
Some code here
function1(string1, ptrstat);
}
int main(){
Statistics statistic;
function1(string, &statistic);
}
In general (i.e. most languages), you can pass by value or pass by reference. It will depend on the definition of the function and its 'signature'; i.e. the way it and its arguments are declared.
Pass-by-value is like an assignment and, if copying a larger structure, it will take longer. Also, the function only receives a copy, so you can make changes to the argument in the function, but that will only effect the function's local copy (the argument) and will make NO change to the original value (in the caller) that was passed to you.
By contrast, pass-by-reference simply passes a pointer (the address in memory) of the original value. This is much faster, (4 or 8 bytes), but it does means that the function can not only read but also write the caller's value. Sometimes you want this! Sometimes you don't.
In your main, you have the value of statistics. The function you are calling expects the address (*), so instead of passing the value, (statistic), you need to pass its address, (&statistic).
In the function, calling itself, you have a pointer to statistic (Statistics *) and you must pass a pointer to statistic (Statistics *): hence, just pass it, the pointer 'statistic'.
if a have a structure say
struct first
{
int a;
int b;
};
now if i create its object
int main(){
struct first ob1,ob2;
ob1.a=5;
printf("%u %u",&ob1,&(ob1.a)); //prints same address
printf("%d %d",ob1,(ob1.a)); // 5,garbage value
return 0;}
my professor said that ob1 is a pointer to a structure. I want to know what address does ob1 and ob1.a also what value they store?
Also in c++ we have this pointer to assign value to ob1.a and ob2.a. In C how does compiler know in which object to store value ?
ob1 is in no way a pointer. It is a structure.
Since a is the first field of struct first, &ob1 and &ob1.a are the same address (but have different types).
In C, the compiler knows which object to store to because you have to tell it. In your case, you said ob1.a or ob2.a respectively.
Editorial note: use %p to print pointers, and don't try to pass a structure to printf at all.
This line provokes undefined behavior because printf expect the first argument to be an int but you are passing in a struct that holds two ints:
printf("%d %d",ob1,(ob1.a)); // 5,garbage value
The reason it prints 5 and a garbage value in your case is because of how your compiler passes parameters to functions: it puts a copy of ob1 on the stack, followed by a copy of ob1.a. Since a is the first field, pushing ob1 on the stack is equivalent to pushing first ob1.a and then ob1.b on the stack. The printf above is therefore equivalent to:
printf("%d %d", ob1.a, ob1.b, ob1.a); // 5,garbage value
So, the first value printed is 5, which is the value that was given for ob1.a, followed by whatever garbage happens to be in ob1.b.
Needless to say, on another system, or with another compiler, you could see something completely different.
I am having trouble understanding how the & operator works and its importance.
I found this example online:
#include <stdio.h>
void main()
{
int a = 10;
printf("\nValue of n is : %d" ,n);
printf("\nValue of &n is : %u", &n);
}
Output :
Value of n is : 10
Value of &n is : 1002
Firstly, why does the &n print out those two extra numbers?
Secondly, why is this important?
n is a variable. It represents a value.
&n is a reference to n. It represents the address in memory where n is store.
As to why it is important:
When you pass an array in C, the function is usually expecting a pointer.
(ie: int* as opposed to just int).
If you were to pass 'n' to the function, it would complain when compiling because the types don't match up (n=int, function expects int*).
If you pass in &n, however you are passing in an address to 'n' which is what the function expects.
To print out an address in C, you normally should use %p in stead of %u.
Note %p prints out address in hexadecimal number.
The & operator is the "address of" operator. so &a means the address of a, not just the value of a.
What this is telling you is that the address of a is 1002 (or as dreamlax pointed out, quite possibly not the real address due to oddities with how printf is being used), even though the value is 10. Note that there is no strict correlation between the two values, you could just as easily have a=121765 and &a=494260.
Knowing the address of a variable allows you to manipulate that specific value/object the variable is "referring" or "pointing" to. If you wish for a function to manipulate that specific value/object rather than manipulate a copy, you should pass the variable's address.
Take the following code (not necessarily complete code):
int main(void)
{
int a = 10;
doIt(a);
printf("after doIt: %d", a);
doItByReference(&a);
printf("after doItByReference: %d", a);
}
void doIt(int val)
{
val = 13;
}
void doItByReference(int *val)
{
*val = 15;
}
Calling doIt passes the value held by a, and a new integer variable at a different address gets that value copied into it. The function is free to make any changes to this duplicate copy and no modifications will be seen in the original a variable.
However, calling doItByReference passes the address of a. Any changes made to the value at the given address will reflect as changes made to a.
This by itself is useful if you want to make changes to a given object and have those changes be reflected in the original copy. However, even if you don't want to modify a value in the original copy this is useful performance wise because you avoid having to copy any values. For a simple int which may be say 4 bytes (exact value isn't important), this is insignificant.
However, say you had a struct which was thousands or millions of bytes:
struct LargeStruct
{
int buffer[134217728];
};
void doIt(LargeStruct buffer)
{
// ... do something
}
void doItByReference(LargeStruct *buffer)
{
// ... do something
}
This time, every call to doIt will have to copy the entire LargeStruct object which is millions of bytes, where-as a call to doItByReference simply uses the existing object and no copy is required.
The address of operator, &, returns the memory address of the following variable. This is important because:
it allows referring to large memory chunks (structures, arrays, dynamically allocated unstructured memory regions) with a light weight handle
it provides means to access internal representations of data structures
it allows us to process different types of data through the same interface
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.