in structure how values get stored? - c

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.

Related

why pointer of an array of structure printing different addresses

struct Student{
int roll;
char name[8];
float marks;
};
void main(){
struct Student stu[5] = {{10,"xyz",30},{15,"abc",50},{20,"lmn",70}};
printf("%d \n", (*stu).roll);
printf("%d \n", (*(stu+1)).roll);
printf("%x %x\n", (*stu), (*(stu+1))); // <- here (a)
printf("%x \n", (*(stu+1))); // <-here (b)
printf("%x \n", (stu));
printf("%x \n", (stu+1));
}
why (*(stu+1)) printing different addresses in (a) and (b)?
why address of (*(stu+1)) in (b) and address of (*stu) same ?
// --------------------
here is output i am getting
10
15
351ff8c0 351ff8b0
351ff8c0
351ff8d0
351ff8e0
Because those printf calls aren't printing the addresses of stu elements, they're printing the addresses of struct Student copies which have been made on the call stack for argument-passing.
Here's why:
printf and the "%x" format do not tell the language to take the address of their argument. They just take whatever they got, and interpret it as an integer, and print that integer as hex.
*stu is not an address, it is the first struct Student in stu. stu is an array, which for most purposes is an address, and * goes the other way: it gets the value at an address, not the address of a thing.
So per the second point, when you do *stu, you get the first struct Student. When you do *(stu+1), you get the second struct Student.
But per the first point, you aren't getting their addresses, you're just getting the structs themselves, and passing those structs - all their contents to printf.
So why do they still look like addresses?
Well, how is a struct type passed to printf?
Turns out there are multiple possible ways, and the exact way depends on your computer, operating system, and compiler.
One way, the way your system seems to be doing, is to make a new copy of each struct argument onto the stack, and then pass the address of that copy to the function as the "actual" machine-level argument. Then the function, which is presumed to know what to do with that argument of that type, is expected to be compiled to look through that address to get the "actual" C-level struct argument.
But of course printf doesn't know what to do with your struct type argument - your compiler knows, because it sees the call to printf, that it needs to do this copy-to-stack-and-pass-the-address-of-copy trick - but the printf function doesn't know that its machine-level argument is actually an internal address argument, it just knows that you told it (by writing "%x") that this argument is an integer. So printf prints that internal implicit incidental copy's address.
So why are the addresses between calls different?
Because each call gets new copies, but the stack space is reused, and nothing changes the stack layout between the two calls, so the first argument to both printf calls gets the same address, then if there's a second argument it gets an adjacent address, and so on.
So printf("%x %x\n", *stu, *(stu+1)) gives the first address to the copy of *stu, and the second address to the copy of *(stu+1).
But printf("%x\n", *(stu+1)) gives the first address to its copy of *(stu+1).
(Notice also that the addresses from those two printf lines in your example are different by the same small amount from the addresses in the next two printf lines. This is because the next two lines are correctly getting the addresses of elements in stu like you wanted, and stu is also allocated on the stack, as is typical for function-scoped variables. This was a big clue for me in figuring out what's happening.)
The printf() functions aren't printing the actual addresses of the structure rather the copies of struct student which have been made on the call stack to service the printf() function
So, the line
printf("%x %x\n", (*stu), (*(stu+1)));
Simply prints the first 2 created addresses on the stack.
To better illustrate if we consider the statement
printf("%x %x\n", (*(stu+5)), (*(stu+4)));
printf("%x %x\n", (*(stu+3)), (*(stu+2)));
These two should print the same addresses as they are simply the first 2 copies created on the stack to service the printf() function
The output I got was
225ffae0 225ffad0
225ffae0 225ffad0

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;
}

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

Why is the address operator (&) important for an array being passed through a function?

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

Resources