Does sprintf() modify variable across function? - c

I use sprintf() to fill my string, but when I'm not done, I found something strange, the var which names test can be modified even it is a argument, I thought it was just like a Rvalue when calling function, or here is somewhere I didn't notice, and the following is my code and output.
Thanks.
#include <stdio.h>
#include <stdlib.h>
void Encap(char str[9])
{
printf("%s\n", str);
sprintf(str, "hi e");
printf("%s\n%p\n", str, &str);
}
int main()
{
char test[9] = "ABC";
printf("%s\n", test);
Encap(test);
printf("%s\n%p\n", test, &test);
system("pause");
return 0;
}
Output
ABC
ABC
hi e
0061FF10
hi e
0061FF27

You declare an array test, and you pass it to the function Encap. Your question is a little unclear, but there are two things which may be surprising you:
Within the function Encap, you are modifying the contents of the array.
After the function Encap returns, back in the caller, the modifications to the test array persist.
(You also asked about "rvalue", which can be an important concept, but it doesn't apply here in the way that you expect.)
The reason this works the way it does is because of two different things:
When you pass the array test to the function Encap, you do not pass the entire value of the array. what actually gets passed is just a pointer to the array;s first element.
Within the function Encap, you are not modifying the pointer that was passed, instead, you are modifying the memory that the pointer points to. You are using the pointer as a value (a pointer value) to know where the memory is that you should modify -- and this ends up being the test array up in main().

You are passing pointer to function, It will surely change value at the memory location.
As you are passing pointer, another copy of pointer will be created and which will be used in function.(Whenever we call to a function, copy of variable is made and operations are done on that copy variable). Here the variable is of type pointer, hence another pointer variable will be created which will be pointing to same memory locations as pointed by test but will be having different address.
That's why two different memory address gets printed as you are printing address of two different pointers.

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.

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.

Pointers, structure, passing arguments, recursion

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

Whats wrong with this C code lines

Whats wrong with this C code lines
char *string()
{
char *text[20];
strcpy(text,"Hello world");
return text;
}
I was poor at pointers and I have seen this in some previous paper.
Can't able to solve.
It doesn't compile, since it treats an array of character pointers as a single array of characters.
The variable declaration line should be:
char text[200];
With that fix done, it's still broken for the reason you're probably interested in: it returns the address of a local variable (the text character array) which goes out of scope as the function returns, thus making the address invalid. There are two ways around that:
The easiest is to make the array static, since that makes it live for as long as the program runs.
You can also switch to dynamic (heap) memory by using malloc(), but that transfers ownership to the caller and requires a call to free() or memory will leak if this function gets called a lot.
Also, as a minor point, its name is in a reserved name space (user programs cannot define functions whose names begin with str). Also, a function taking no arguments should be declared as (void) in C, an empty pair of parentheses does not mean the same thing.
This code will not compile because you are trying to make an array of pointers.
In simple words if you want to handle string using pointer you can do using following:
char *str="HELLO WORLD";
And if you want to handle string using char array you have to remove value at address operator(*).
here it is:
char text[20];
then you can perform your function.
Still there is error as the Scope of the text is only valid inside the function so if you want to pass address and retain the value make it static
static char text[20];
return text;

Resources