Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

variable addresses on the stack

62 views
Skip to first unread message

Thiago Adams

unread,
Aug 19, 2022, 1:22:10 PM8/19/22
to
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?


Thiago Adams

unread,
Aug 19, 2022, 1:27:22 PM8/19/22
to
Also..
Was this block scopes variables valid in previous versions of C?
I tried gcc -std=c89 and it works.

Keith Thompson

unread,
Aug 19, 2022, 1:59:21 PM8/19/22
to
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.T...@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

Kaz Kylheku

unread,
Aug 19, 2022, 4:58:30 PM8/19/22
to
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

Joe Pfeiffer

unread,
Aug 19, 2022, 5:47:58 PM8/19/22
to
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.

Andrey Tarasevich

unread,
Aug 19, 2022, 9:47:28 PM8/19/22
to
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

Thiago Adams

unread,
Sep 21, 2022, 8:09:15 AM9/21/22
to
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;
}
}

Thiago Adams

unread,
Sep 21, 2022, 8:18:59 AM9/21/22
to
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..


David Brown

unread,
Sep 21, 2022, 9:34:44 AM9/21/22
to
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).


Keith Thompson

unread,
Sep 21, 2022, 6:23:39 PM9/21/22
to
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

unread,
Sep 21, 2022, 6:30:26 PM9/21/22
to
Thiago Adams <thiago...@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/
0 new messages