2
int main(){
    int p = 10 , q = 11;
    int a[3];
    int * ptr = &q;
    cout << *ptr+1 <<endl;

    cout <<"P = " << (int)&p <<endl;
    cout <<"q = " << (int)&q <<endl;
    cout << "Size of p = "<< sizeof(p) <<endl;
    cout << "(int)&a[0]:" << (int)&a[0] <<endl;
    cout << "(int)&a[1]:" << (int)&a[1] <<endl;
    cout << "(int)&a[2]:" << (int)&a[2] <<endl;
}

And the output of this code is

12
P = 14679472
q = 14679460
Size of p = 4
(int)&a[0]:14679440
(int)&a[1]:14679444
(int)&a[2]:14679448

Now i have few questions .
- int take 4 bytes or 8 bytes but here the difference between p and q is 12. I don't get it ? what it is? am i missing something important here ?
- I was actually reading about about stack frame so any body can explain or provide a good study material what it is would be really appreciated.

Ôrel
  • 4,349
  • 2
  • 19
  • 34
Umar Farooq
  • 377
  • 1
  • 9
  • 1
    An implementation can lay out automatic objects however it wants, with as much padding as it wants. – molbdnilo May 25 '20 at 09:21
  • As already noted, the explanation will be compiler specific - all sorts of possible explanations. You might want to also examine the address and size of `ptr` - that may (or may not) provide insights relevant to your particular compiler. – Peter May 25 '20 at 09:35

2 Answers2

2

With regard to (paraphrased):

An int take four or eight bytes but here the difference between p and q is twelve.

An int does not take four or eight bytes, that's just a common thing in many implementations. The standard specifies a minimum range but no maximum. In any case, the standard does not mandate that distinct variables are allocated on the stack in any particular order. In fact, it doesn't mandate a stack at all, it just has to behave in a certain way.

Granted arrays have to be ordered in a certain way (as you can see from the addresses of the a elements) but p and q are not part of an array. And, even thought the a element addresses are four bytes apart, even that is not mandated. An implementation is free to add padding between elements and after the last element.

Since you can't (safely) use the address of p to do anything other than access p itself, it's address is actually irrelevant.


In regard to your second question about good reference material, that's actually disfavoured by Stack Overflow, one of the close reasons being:

Seeking recommendations for books, tools, software libraries, and more. This question is likely to lead to opinion-based answers.

Hence I won't bother answering that bit.


However, I will give a bit of extra advice: if you really want to know what specific implementations are doing with your code, you should head on over to GodBolt and type your code in. Making some minor modifications to get it to compile cleanly:

#include <iostream>
#define USE_P 1
#define USE_Q 1
#define USE_A 1
int main() {
    #if USE_P
        int p = 10;
    #endif
    #if USE_Q
        int q = 11;
    #endif
    #if USE_A
        int a[3] = {12, 13, 14};
    #endif
    std::cout << "hello\n";
}

You'll see something at the start of main that looks like this (though I added the comments):

push    rbp
mov     rbp, rsp
sub     rsp, 32                 // Stack frame size
mov     DWORD PTR [rbp-4], 10   // p
mov     DWORD PTR [rbp-8], 11   // q
mov     DWORD PTR [rbp-20], 12  // a[0]
mov     DWORD PTR [rbp-16], 13  // a[1]
mov     DWORD PTR [rbp-12], 14  // a[2]

And you watch how this changes when you tell it to stop using any of those variables, in any combination. From the example I gave (and using x86-64 gcc 10.1), it appears that the variables are placed as you expected. However, as stated earlier, this is not a requirement.

paxdiablo
  • 772,407
  • 210
  • 1,477
  • 1,841
  • i agree but sizeof tells us that it is taking 4 bytes where are the rest of 8 ? the real confussion lies here. – Umar Farooq May 25 '20 at 09:30
  • 1
    @UmarFarooq, the size of the object itself is four bytes but that has *zero* bearing on how it may be organised with other variables on the stack. They may be placed in any order and there may be any amount of padding between distinct variables. The real confusion is caused the expectation that they follow some rules that don't *actually* exist :-) – paxdiablo May 25 '20 at 09:35
  • Thank you very much ! can you tell any trick how can we avoid pedding or reduce it cause i feel it is just a waste of memory. – Umar Farooq May 25 '20 at 09:47
  • @UmarFarooq -- The authors for the compilers and linkers you're using are not new college students or amateur programmers. They are some of the best programmers in the business. They will not write these tools with the knowledge that when they lay out the variables, they're foolishly "wasting memory". Thus attempting to "beat the compiler at its own game" usually results in a waste of time, and worse, sometimes becomes detrimental. – PaulMcKenzie May 25 '20 at 09:54
  • @PaulMcKenzie is right, I long ago stopped trying to hand-optimise code at assembler level. Compiler writers are in the same class as cryptic crossword compilers: minds horribly warped due to the field they work in, but damn good at what they do :-) – paxdiablo May 25 '20 at 10:05
  • @UmarFarooq: One of the best ways to avoid padding is by _not_ taking the address of variables. Modern CPU's have many registers, and it's likely that your variable `p` would have been stored in a register. But registers don't have an address, so when you printed that address the compiler needed to pick an address. – MSalters May 25 '20 at 10:29
  • @MSalters can you give some refrence ? because it is very new to me where can i study this behaviour because as per my knowledge the the variables are stored in stack and heap . – Umar Farooq May 25 '20 at 10:53
  • @UmarFarooq: there is no spoon^H^H^H^H^H stack :-) – paxdiablo May 25 '20 at 11:06
1

Why it is priniting 12 for *ptr+1

As per operator precedence, deference operator * will be executed first and it will give the value of 11. 11 plus 1 is 12.

int take 4 bytes or 8 bytes but here the difference between p and q is 12. I don't get it ? what it is? am i missing something important here ?

The compiler/implementation can save the variable with auto storage class in any order. Even, in some implementation, there couldn't a stack at all. The standard just defines the behavior and each implementation has to abide to it but they are free to use any data structure for function calls (but I think stack are mostly used). There could be some variables in between p and q with as much padding as it wants.

I was actually reading about about stack frame so any body can explain or provide a good study material what it is would be really appreciated.

See this and read about ABI.

abhiarora
  • 7,515
  • 3
  • 27
  • 46