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
Related
I'm trying to understand some sample C code that I got with my microcontroller board. I have a really hard time to understand that whole pointer thing. I read a lot of posts in this forum and I also read several tutorials and slowly I get the hang of it :) But...
In my sample code there is the following line of code, which I could not decrypt with any information that I have found yet.
#define SOMENAME ((uint32_t *)0x130010f0)
I understood, that #define simply replaces all occurrences of SOMENAME in the compiled code with the respective statement (don't know if this is correctly explained, but I really think I got what this is doing).
Now, what I could imagine, what the rest of the statement means is the following:
SOMENAME is now a pointer to the address 0x130010f0 but without being an actual variable.
Is this correct? And I could kind of use it for example as: printf("value at address 0x130010f0: %p",SOMENAME) because the compiler would replace it with printf("value at address 0x130010f0: %p",((uint32_t *)0x130010f0)) and this gives the value stored at that address? What would be the print statement if I want the address of that pointer? I can't, right? Because the pointer does not have an address as it is not a variable? Very confusing...
The example is quite complex and this definition is also part of other definitions which are pointers to structs of structs of structs, therefore this "simple" example. Below you can find the "whole" structure:
#define ROM_API_TREE ((uint32_t *)0x130010f0)
#define BOOTLOADER_POINTER ((bootloader_tree_t *)ROM_API_TREE)
flash_driver_interface_t *FLASH_API_TREE
#define FLASH_API_TREE BOOTLOADER_POINTER->flashDriver
typedef struct BootloaderTree{
...
const flash_driver_interface_t *flashDriver;
} bootloader_tree_t
typedef struct FlashDriverInterface{
...
status_t (*ffr_get_uuid)(flash_config_t *config, uint8_t *uuid);
} flash_driver_interface_t
/*
* I actually want to understand that statement, but as I fail
* already at the beginning, I posted this question
*/
status_t = FLASH_API_TREE->ffr_get_uuid(config,uuid);
You are correct that SOMENAME get replaced by the preprocessor with ((uint32_t *)0x130010f0). What this gives you is a pointer to a uint32_t, and the value of that pointer is 0x130010f0.
When you then do this:
printf("value at address 0x130010f0: %p",SOMENAME);
You'll actually print the value of the pointer, i.e. 0x130010f0, not what it points to. For that you would need to dereference it, i.e.:
printf("value at address 0x130010f0: %u", *SOMENAME);
This however assumes that 0x130010f0 is a valid address that can be dereferenced and read. This will typically only be the case in some particular embedded environment where the implementation allows it.
As i saw, you basically could understand many things behind the Pointers. The SOMENAME is a macro not a variable right. Before i get to the code, a pointer in general is nothing else but a variable that contains an adress instead of having a value.
printf("value at address 0x130010f0: %p",SOMENAME); is wrong because the %p expects a value not an Adress and you are passing the adress to it, so you all you have to do is to dereference it using the *.
When you write (uint32_t *)0x130010f0 you are casting the adress to the type writteb between parentheses.
Whenever it gets complicated while using pointers try to remember this small example:
int a = 10;
int *p = &a;// declare pointer of type integer. This is valid, adress of an integer variable contains adress of integer variable
int *j; //declare pointer of type integer
j = &a; //correct, because j expects an adress.
*j = &a; //wrong *j expects a value
printf("value of p: %p", *p);
printf("adress of p: %p", p); //or &p
This shows that your microcontroller board has a program accessible 32-bit device.
I say 'accessible' because this device could be readable, writable or both.
I use the kinda general term 'device' because it could be all kinds of things. Quite often it's a register that simply stores a value, but it could also be a FIFO chip returning the next stored value at every read.
Assuming it's a register: These registers often consist of separate bits or small groups of bits to represent some function. In that case you'd see bitfield struct declarations that look like this (two 16-bit fields as example):
struct {
uint32_t someField : 16;
uint32_t otherField : 16;
} fields;
why below program taking memory difference to next location fix 12 in next memory location or its have some logic for char/float /int have diffrencet different -2 difference to next location
include
#include
int main () {
char var;
char *ptr;
char **pptr;
char ***ppptr;
char ****pppptr;
var = 'M';
/* take the address of var */
ptr = &var;
/* take the address of ptr using address of operator & */
pptr = &ptr;
ppptr=&pptr;
ppptr=&pptr;
ppptr=&pptr;
pppptr=&ppptr;
/* take the value using pptr */
printf("Value of var = %d\n", var );
printf("Value available at *ptr = %c....and address is %u\n", *ptr ,ptr);
printf("Value available at **pptr = %c....and address is %u\n", **pptr,pptr);
printf("Value available at ***ppptr = %c....and address is %u\n", ***ppptr ,ppptr);
printf("Value available at ****pppptr = %c....and address is %u\n", ****pppptr,pppptr);
getch();
return 0;
}
//out put
///-----------------------------------------------
Value of var = 77;
Value available at *ptr = M....and address is 11401207
Value available at **pptr = M....and address is 11401192 why differnceis 12 in memory locaton
Value available at ***ppptr = M....and address is 11401180
Value available at ****pppptr = M....and address is 11401168
You appear to be asking about why the address of ptr, as judged by printing the value of pptr using scanf field descriptor %u, appears to differ from the address of the next-declared local variable, pptr, by 12 bytes. And so on down the line for the other local variables, I presume.
In fact, as #SouravGhosh already described in his answer, the %u field descriptor does not correspond properly to pointer arguments, and therefore the effects of your scanf calls, including all aspects of the output, are undefined.
However, the actual results don't really matter for the purposes of the question. The C language provides no justification for assuming any particular ordering or difference between the addresses of any function's local variables. It is at the discretion of the compiler. There is therefore no general answer to the question.
If we hypothesize that the output you observed happens to accurately reflect the differences between the addresses of the local variables -- which is by no means certain -- then that would suggest that the compiler is intentionally leaving padding between the variables. It is entirely free to do so, for any purpose whatever. For example, the compiler might be trying to minimize the potential impact of off-by-one errors in code that accesses the local variables via the pointers to them.
First, a proper way to print pointers is with %p and with the pointer converted to void * when passed to printf, as in printf("%p\n", (void *) ptr);. Since you mention in a comment having used %P, differing from the %u shown in the question, I will presume that incorrect case is a typo, and you have reproduced the problem using %p with results similar to those shown in the question.
In that case, what is likely happening is that the compiler is storing the pointers ptr, pptr, ppptr, and pppptr at addresses that happen to be 12 bytes apart. Of course, it could store them merely four or eight bytes apart if pointers in your C implementation happened to be four or eight bytes in size. However, the compiler may be storing other things between the pointers, perhaps addresses of the strings you use in the printf statements or other incidental values. This makes me suspect that you compiled without optimization enabled. If you recompile with optimization, you will likely see different results.
In any case, a better explanation of the results would likely be had by asking the compiler to show the assembly code it generates (as by using the -S switch with GCC).
Using %u for printing pointer address results in undefined behavior.
Use %p format specifier and cast the argument to void *.
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