Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #167065 > unrolled thread

variable addresses on the stack

Started byThiago Adams <thiago.adams@gmail.com>
First post2022-08-19 10:22 -0700
Last post2022-08-19 18:47 -0700
Articles 11 — 6 participants

Back to article view | Back to comp.lang.c


Contents

  variable addresses on the stack Thiago Adams <thiago.adams@gmail.com> - 2022-08-19 10:22 -0700
    Re: variable addresses on the stack Thiago Adams <thiago.adams@gmail.com> - 2022-08-19 10:27 -0700
    Re: variable addresses on the stack Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-08-19 10:59 -0700
      Re: variable addresses on the stack Thiago Adams <thiago.adams@gmail.com> - 2022-09-21 05:09 -0700
        Re: variable addresses on the stack Thiago Adams <thiago.adams@gmail.com> - 2022-09-21 05:18 -0700
          Re: variable addresses on the stack Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-09-21 15:30 -0700
        Re: variable addresses on the stack David Brown <david.brown@hesbynett.no> - 2022-09-21 15:34 +0200
        Re: variable addresses on the stack Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-09-21 15:23 -0700
    Re: variable addresses on the stack Kaz Kylheku <480-992-1380@kylheku.com> - 2022-08-19 20:58 +0000
    Re: variable addresses on the stack Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2022-08-19 15:47 -0600
    Re: variable addresses on the stack Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-08-19 18:47 -0700

#167065 — variable addresses on the stack

FromThiago Adams <thiago.adams@gmail.com>
Date2022-08-19 10:22 -0700
Subjectvariable addresses on the stack
Message-ID<54f99ed2-fe4d-4cab-944c-cb61799d64ecn@googlegroups.com>
I am curious with the following..

void f(int i) {
   if (i > 1)  {
       int j ='a';       
   }
   if (i < 1)  {
       int k ='b';       
   }
}
When I see the assembly ouput I can see the compiler
use the address  rbp-4 for j and rbp-8 for k

Why not the same address considering that j and k don't exist 
at the same time?
Any reason?

[toc] | [next] | [standalone]


#167066

FromThiago Adams <thiago.adams@gmail.com>
Date2022-08-19 10:27 -0700
Message-ID<88b71bc9-2e48-4f58-a0f5-6b17e4c5f0f6n@googlegroups.com>
In reply to#167065
Also.. 
Was this block scopes variables valid in previous versions of C?
I tried gcc -std=c89 and it works.

[toc] | [prev] | [next] | [standalone]


#167067

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2022-08-19 10:59 -0700
Message-ID<871qtc868m.fsf@nosuchdomain.example.com>
In reply to#167065
Thiago Adams <thiago.adams@gmail.com> writes:
> I am curious with the following..
>
> void f(int i) {
>    if (i > 1)  {
>        int j ='a';       
>    }
>    if (i < 1)  {
>        int k ='b';       
>    }
> }
> When I see the assembly ouput I can see the compiler
> use the address  rbp-4 for j and rbp-8 for k
>
> Why not the same address considering that j and k don't exist 
> at the same time?
> Any reason?

No particular reason.  They don't exist at the same time, and
a compiler certainly *could* allocate them at the same address.
It's valid either way as long as the code behaves correctly.

I played with it myself.  With gcc -O0, I got the same result
you did.  With -O1 and higher, it eliminated j and k.  When I
added putchar calls to prevent that, they were both stored in the
same register.

When I changed j and k to arrays, gcc -O0 allocated them at the
same address.

And yes, block local variables have been supported for a long time.
A 1975 C reference manual allowed declarations only at the top of
a function body, but K&R1 (1978) allows declarations within any
compound statement.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#167772

FromThiago Adams <thiago.adams@gmail.com>
Date2022-09-21 05:09 -0700
Message-ID<f2dfb3b5-379f-42d8-9bdc-99051a56d7e0n@googlegroups.com>
In reply to#167067
On Friday, August 19, 2022 at 2:59:21 PM UTC-3, Keith Thompson wrote:
> Thiago Adams <thiago...@gmail.com> writes: 
> > I am curious with the following.. 
> > 
> > void f(int i) { 
> > if (i > 1) { 
> > int j ='a'; 
> > } 
> > if (i < 1) { 
> > int k ='b'; 
> > } 
> > } 
> 
[...]
> And yes, block local variables have been supported for a long time. 
> A 1975 C reference manual allowed declarations only at the top of 
> a function body, but K&R1 (1978) allows declarations within any 
> compound statement. 

C99 added "mixed declarations and code"

I changed the code adding variable 'm'

void f(int i) { 
 
 if (i > 1) { 
   int j ='a'; 
 } 
 
 if (i < 1) { 
   int k ='b'; 
 } 
 
 int  m = 1;
} 

gcc with -std=c90 -pedantic 
gives:

"warning: mixing declarations and code is a C99 extension [-Wdeclaration-after-statement]"
 int  l = 1;
      ^
So, block declarations is something very old, but "mixed" declarations are new 
in C99.

Very weird because adding { }  around the "mixed" declaration it just works.
I cannot see a reason for this limitation, but I guess compilers use to accept
mixed declarations for a long time.

void f(int i) { 
 
 if (i > 1) { 
   int j ='a'; 
 } 
 
 if (i < 1) { 
   int k ='b'; 
 } 
 {
  int  m = 1;
 }
} 

[toc] | [prev] | [next] | [standalone]


#167773

FromThiago Adams <thiago.adams@gmail.com>
Date2022-09-21 05:18 -0700
Message-ID<50c4530a-b411-4ceb-8b8c-2181a15afd8fn@googlegroups.com>
In reply to#167772
On Wednesday, September 21, 2022 at 9:09:15 AM UTC-3, Thiago Adams wrote:
> On Friday, August 19, 2022 at 2:59:21 PM UTC-3, Keith Thompson wrote: 
> > Thiago Adams <thiago...@gmail.com> writes: 
> > > I am curious with the following.. 
> > > 
> > > void f(int i) { 
> > > if (i > 1) { 
> > > int j ='a'; 
> > > } 
> > > if (i < 1) { 
> > > int k ='b'; 
> > > } 
> > > } 
> >
> [...]
> > And yes, block local variables have been supported for a long time. 
> > A 1975 C reference manual allowed declarations only at the top of 
> > a function body, but K&R1 (1978) allows declarations within any 
> > compound statement.
> C99 added "mixed declarations and code" 
> 
> I changed the code adding variable 'm'
> void f(int i) { 
> 
> if (i > 1) { 
> int j ='a'; 
> } 
> 
> if (i < 1) { 
> int k ='b'; 
> }
> int m = 1; 
> } 
> 
> gcc with -std=c90 -pedantic 
> gives: 
> 
> "warning: mixing declarations and code is a C99 extension [-Wdeclaration-after-statement]" 
> int l = 1; 
> ^ 
> So, block declarations is something very old, but "mixed" declarations are new 
> in C99. 
> 
> Very weird because adding { } around the "mixed" declaration it just works. 
> I cannot see a reason for this limitation, but I guess compilers use to accept 
> mixed declarations for a long time.
> void f(int i) { 
> 
> if (i > 1) { 
> int j ='a'; 
> } 
> 
> if (i < 1) { 
> int k ='b'; 
> }
> { 
> int m = 1; 
> } 
> }

I added C89 target in my transpiler, so I am writing 
here

https://github.com/thradams/cake/blob/main/manual.md

changes since C89 and how we can write (if possible) the 
equivalent code in previous versions.

C99 added Flexible array members

struct s {
    int n;
    double d[]; 
};

Does anyone have suggestion how to write this in C89?

struct s {
    int n;
    double d[1]; //maybe?
};

The sizeof a struct with flexible array members is not not clear.. 

[toc] | [prev] | [next] | [standalone]


#167779

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2022-09-21 15:30 -0700
Message-ID<878rmcfjik.fsf@nosuchdomain.example.com>
In reply to#167773
Thiago Adams <thiago.adams@gmail.com> writes:
[...]
> C99 added Flexible array members
>
> struct s {
>     int n;
>     double d[]; 
> };
>
> Does anyone have suggestion how to write this in C89?
>
> struct s {
>     int n;
>     double d[1]; //maybe?
> };
>
> The sizeof a struct with flexible array members is not not clear.. 

The (questionably legal) predecessor to flexible array members was
known as the "struct hack".  See question 2.6 of the comp.lang.c FAQ.

https://www.c-faq.com/

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#167775

FromDavid Brown <david.brown@hesbynett.no>
Date2022-09-21 15:34 +0200
Message-ID<tgf3t6$1r02t$1@dont-email.me>
In reply to#167772
On 21/09/2022 14:09, Thiago Adams wrote:
> On Friday, August 19, 2022 at 2:59:21 PM UTC-3, Keith Thompson wrote:
>> Thiago Adams <thiago...@gmail.com> writes:
>>> I am curious with the following..
>>>
>>> void f(int i) {
>>> if (i > 1) {
>>> int j ='a';
>>> }
>>> if (i < 1) {
>>> int k ='b';
>>> }
>>> }
>>
> [...]
>> And yes, block local variables have been supported for a long time.
>> A 1975 C reference manual allowed declarations only at the top of
>> a function body, but K&R1 (1978) allows declarations within any
>> compound statement.
> 
> C99 added "mixed declarations and code"
> 
> I changed the code adding variable 'm'
> 
> void f(int i) {
>   
>   if (i > 1) {
>     int j ='a';
>   }
>   
>   if (i < 1) {
>     int k ='b';
>   }
>   
>   int  m = 1;
> }
> 
> gcc with -std=c90 -pedantic
> gives:
> 
> "warning: mixing declarations and code is a C99 extension [-Wdeclaration-after-statement]"
>   int  l = 1;
>        ^
> So, block declarations is something very old, but "mixed" declarations are new
> in C99.
> 
> Very weird because adding { }  around the "mixed" declaration it just works.
> I cannot see a reason for this limitation, but I guess compilers use to accept
> mixed declarations for a long time.
> 
> void f(int i) {
>   
>   if (i > 1) {
>     int j ='a';
>   }
>   
>   if (i < 1) {
>     int k ='b';
>   }
>   {
>    int  m = 1;
>   }
> }

C90 (and I believe before that too - but I am not well versed in 
pre-ANSI C rules) allowed the definition of variables at the start of a 
block, but not after statements.  There was no requirement for the 
common practice of bunching all the definitions at the start of a 
function.  And the initialisation for the variables could have function 
calls and anything else.

C99 allowed declarations and statements to be freely mixed, which let 
people write nicer code.  But your second version there, with "int m = 
1;" inside braces, is perfectly fine C90.

I don't know what the historic justification for C90's limitations here 
was - perhaps it made the language syntax easier to describe, or made 
"dumb translator" compilers easier to write, or perhaps it simply 
reflected the style of code structure that was popular at the time (it 
matches Pascal, for instance).

[toc] | [prev] | [next] | [standalone]


#167778

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2022-09-21 15:23 -0700
Message-ID<87czbofjtw.fsf@nosuchdomain.example.com>
In reply to#167772
Thiago Adams <thiago.adams@gmail.com> writes:
> On Friday, August 19, 2022 at 2:59:21 PM UTC-3, Keith Thompson wrote:
>> Thiago Adams <thiago...@gmail.com> writes: 
>> > I am curious with the following.. 
>> > 
>> > void f(int i) { 
>> > if (i > 1) { 
>> > int j ='a'; 
>> > } 
>> > if (i < 1) { 
>> > int k ='b'; 
>> > } 
>> > } 
>> 
> [...]
>> And yes, block local variables have been supported for a long time. 
>> A 1975 C reference manual allowed declarations only at the top of 
>> a function body, but K&R1 (1978) allows declarations within any 
>> compound statement. 
>
> C99 added "mixed declarations and code"
>
> I changed the code adding variable 'm'
>
> void f(int i) { 
>  
>  if (i > 1) { 
>    int j ='a'; 
>  } 
>  
>  if (i < 1) { 
>    int k ='b'; 
>  } 
>  
>  int  m = 1;
> } 
>
> gcc with -std=c90 -pedantic 
> gives:
>
> "warning: mixing declarations and code is a C99 extension [-Wdeclaration-after-statement]"
>  int  l = 1;
>       ^
> So, block declarations is something very old, but "mixed" declarations are new 
> in C99.
>
> Very weird because adding { }  around the "mixed" declaration it just works.
> I cannot see a reason for this limitation, but I guess compilers use to accept
> mixed declarations for a long time.
>
> void f(int i) { 
>  
>  if (i > 1) { 
>    int j ='a'; 
>  } 
>  
>  if (i < 1) { 
>    int k ='b'; 
>  } 
>  {
>   int  m = 1;
>  }
> } 

There's nothing weird about it.  C89, and older versions going back at
least to K&R1 C (1978), allowed zero or more declarations followed by
zero or more statements within a block.  By adding { } you created a
block, which can begin with a declaration.  (Of course your `int j` is
not visible outside the block, and nothing refers to it, so you might
get a warning about an unused variable.)  The C99 change was to allow
declarations and statements to be mixed within a block.

It was only some very old versions of C (1975 and earlier) that allowed
declarations only within the top-level block of a function definition.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#167068

FromKaz Kylheku <480-992-1380@kylheku.com>
Date2022-08-19 20:58 +0000
Message-ID<20220819135226.125@kylheku.com>
In reply to#167065
On 2022-08-19, Thiago Adams <thiago.adams@gmail.com> wrote:
> I am curious with the following..
>
> void f(int i) {
>    if (i > 1)  {
>        int j ='a';       
>    }
>    if (i < 1)  {
>        int k ='b';       
>    }
> }
> When I see the assembly ouput I can see the compiler
> use the address  rbp-4 for j and rbp-8 for k
>
> Why not the same address considering that j and k don't exist 
> at the same time?
> Any reason?

Nothing exists in the above; it is indistinguishable from

  void f(int i) { }

and in the ideal circumstances, the optimized treatment
of it would be indistinguisahble from the like treatment
of the above.

If there is a difference, the compiler is not being operated in a way
which best reveals its abilities to remove dead code, or else is
somewhat lacking in those abilities.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

[toc] | [prev] | [next] | [standalone]


#167069

FromJoe Pfeiffer <pfeiffer@cs.nmsu.edu>
Date2022-08-19 15:47 -0600
Message-ID<1b35drsy66.fsf@pfeifferfamily.net>
In reply to#167065
Thiago Adams <thiago.adams@gmail.com> writes:

> I am curious with the following..
>
> void f(int i) {
>    if (i > 1)  {
>        int j ='a';       
>    }
>    if (i < 1)  {
>        int k ='b';       
>    }
> }
> When I see the assembly ouput I can see the compiler
> use the address  rbp-4 for j and rbp-8 for k
>
> Why not the same address considering that j and k don't exist 
> at the same time?
> Any reason?

Easier to just allocate more space and not keep track of variable
lifetimes.  A compiler that was optimizing for space might decide to use
the same location for both.

Likelier would be for an optimizing compiler to notice the function has
no observable behavior and optimize the whole thing away.

[toc] | [prev] | [next] | [standalone]


#167070

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2022-08-19 18:47 -0700
Message-ID<tdpef2$1p1m4$1@dont-email.me>
In reply to#167065
On 8/19/2022 10:22 AM, Thiago Adams wrote:
> void f(int i) {
>     if (i > 1)  {
>         int j ='a';
>     }
>     if (i < 1)  {
>         int k ='b';
>     }
> }

You are most certainly building your code in "debug" configuration. In 
which case the compiler might deliberately assign different addresses to 
these variables for some more-or-less justified debugging purposes. E.g. 
it might be easier to identify how a dangling pointer became dangling 
when it used to point to a local variable with a unique address.

Or it might do it simply because it is easier in the current implementation.

And self-respecting compiler will discard the code inside `f` entirely, 
when working in any "serious" compilation mode.

-- 
Best regards,
Andrey

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web