Unnamed compound object as "buffer" arguments

E

Eric Laberge

Aloha!

This question is meant to be about C99 and unnamed compound objects. As I
read, if such a construct as
int *p = (int[]){0};
is used within a function, then it has "automatic storage duration
associated with the enclosing block".

So I tried the annexed code, and it compiles without a warning, and works as
I expected.

I'm mostly puzzled by the object lifetime, ie.: if I can reasonably use such
a construct for temporary initialisation, by passing it as a function
parameter and then memcpy'ing it to another variable. By it being declared
as a function parameter, is this function the "enclosing block" and as such
I will lose the ability to correctly pass it's pointer back to memcpy, or
is its scope the entire "main" function?

Before somebody asks why I don't directly call "myfunc" with "a" or "b" as
parameters, I'm trying to chain some array-modifying functions together,
and mostly simply experimenting some stuff.

Thanks, I like reading this group.

/* BOF */
/* Tried with "gcc -std=c99 -pedantic -Wall file.c" */
#include <stdio.h>
#include <string.h>

unsigned int* myfunc(unsigned int* buffer)
{
unsigned int i;

for (i = 0; i < 5; i++)
buffer = i;

return buffer;
}

int main(void)
{
unsigned int a[5];
unsigned int b[5];
unsigned int i;

memcpy(a, myfunc((unsigned int[5]){0}), sizeof a);
memcpy(b, myfunc((unsigned int[5]){0}), sizeof b);

for (i = 0; i < 5; i++)
printf("a[%d]=%d\tb[%d]=%d\n", i, a, i, b);

return 0;
}
/* EOF */
 
R

Robert Gamble

Eric said:
Aloha!

This question is meant to be about C99 and unnamed compound objects. As I
read, if such a construct as
int *p = (int[]){0};
is used within a function, then it has "automatic storage duration
associated with the enclosing block".

So I tried the annexed code, and it compiles without a warning, and works as
I expected.

I'm mostly puzzled by the object lifetime, ie.: if I can reasonably use such
a construct for temporary initialisation, by passing it as a function
parameter and then memcpy'ing it to another variable. By it being declared
as a function parameter, is this function the "enclosing block" and as such
I will lose the ability to correctly pass it's pointer back to memcpy, or
is its scope the entire "main" function?

The storage duration of a compound literal at function scope is until
the end of the block in which it appears. A function call does not
constitute a block.
Before somebody asks why I don't directly call "myfunc" with "a" or "b" as
parameters, I'm trying to chain some array-modifying functions together,
and mostly simply experimenting some stuff.

Thanks, I like reading this group.

/* BOF */
/* Tried with "gcc -std=c99 -pedantic -Wall file.c" */
#include <stdio.h>
#include <string.h>

unsigned int* myfunc(unsigned int* buffer)
{
unsigned int i;

for (i = 0; i < 5; i++)
buffer = i;

return buffer;
}

int main(void)
{
unsigned int a[5];
unsigned int b[5];
unsigned int i;

memcpy(a, myfunc((unsigned int[5]){0}), sizeof a);
memcpy(b, myfunc((unsigned int[5]){0}), sizeof b);


The main function is the associated enclosing block, thus the storage
duration of the two compound literals continues until the end of your
main function.
for (i = 0; i < 5; i++)
printf("a[%d]=%d\tb[%d]=%d\n", i, a, i, b);

return 0;
}
/* EOF */


Robert Gamble
 
B

Barry Schwarz

Aloha!

This question is meant to be about C99 and unnamed compound objects. As I
read, if such a construct as
int *p = (int[]){0};
is used within a function, then it has "automatic storage duration
associated with the enclosing block".

So I tried the annexed code, and it compiles without a warning, and works as
I expected.

I'm mostly puzzled by the object lifetime, ie.: if I can reasonably use such
a construct for temporary initialisation, by passing it as a function
parameter and then memcpy'ing it to another variable. By it being declared
as a function parameter, is this function the "enclosing block" and as such

A function call does not create a block. The compound literal has
automatic storage duration associated with the block of code it is
defined in.
I will lose the ability to correctly pass it's pointer back to memcpy, or
is its scope the entire "main" function?

Before somebody asks why I don't directly call "myfunc" with "a" or "b" as
parameters, I'm trying to chain some array-modifying functions together,
and mostly simply experimenting some stuff.

Thanks, I like reading this group.

/* BOF */
/* Tried with "gcc -std=c99 -pedantic -Wall file.c" */
#include <stdio.h>
#include <string.h>

unsigned int* myfunc(unsigned int* buffer)
{
unsigned int i;

for (i = 0; i < 5; i++)
buffer = i;

return buffer;
}

int main(void)
{
unsigned int a[5];
unsigned int b[5];
unsigned int i;

memcpy(a, myfunc((unsigned int[5]){0}), sizeof a);


The compound literal here has automatic duration for the life of main.
memcpy(b, myfunc((unsigned int[5]){0}), sizeof b);

It is implementation defined whether this literal defines the same
object as the previous one (similar to the situation for multiple
occurrences of a string literal). Since myfunc doesn't use the
current values in the array, the issue is moot here. If myfunc did
use the original values, the first call would receive zeros but the
second call could receive zeros or the results of the first call.
for (i = 0; i < 5; i++)
printf("a[%d]=%d\tb[%d]=%d\n", i, a, i, b);

return 0;
}
/* EOF */



<<Remove the del for email>>
 
K

Kevin Bracey

In message <[email protected]>
Barry Schwarz said:
memcpy(a, myfunc((unsigned int[5]){0}), sizeof a);

The compound literal here has automatic duration for the life of main.
memcpy(b, myfunc((unsigned int[5]){0}), sizeof b);

It is implementation defined whether this literal defines the same
object as the previous one (similar to the situation for multiple
occurrences of a string literal). Since myfunc doesn't use the
current values in the array, the issue is moot here. If myfunc did
use the original values, the first call would receive zeros but the
second call could receive zeros or the results of the first call.

Incorrect. Every compound literal has separate storage, and is a distinct
object. The exception is for compound literals with const-qualified type -
like string literals, compound literals need not be distinct objects (and you
can't modify them).
 
F

Flash Gordon

Kevin said:
In message <[email protected]>
Barry Schwarz said:
memcpy(a, myfunc((unsigned int[5]){0}), sizeof a);

The compound literal here has automatic duration for the life of main.
memcpy(b, myfunc((unsigned int[5]){0}), sizeof b);

It is implementation defined whether this literal defines the same
object as the previous one (similar to the situation for multiple
occurrences of a string literal). Since myfunc doesn't use the
current values in the array, the issue is moot here. If myfunc did
use the original values, the first call would receive zeros but the
second call could receive zeros or the results of the first call.

Incorrect. Every compound literal has separate storage, and is a distinct
object. The exception is for compound literals with const-qualified type -
like string literals, compound literals need not be distinct objects (and you
can't modify them).

String literals do *not* have a const-qualified type. The reason they
"cannot" be modified is because the standard says modifying them invokes
undefined behaviour (which means on some systems you will get away with
it) and IIRC the standard explicitly allows them to share storage. I
don't know about compound literals.
 
M

Michael Wojcik

String literals do *not* have a const-qualified type.

Kevin didn't say they did; he said that compound literals of const-
qualified type were like string literals in that they need not be
distinct objects.

What he wrote is not ambiguous if you understand the dash as
separating two clauses - which is the preferred usage. You can only
read "like string literals" as an appositive to "compound literals
with const-qualified type" if you see the dash as separating two
phrases in the same clause, which would be rather sloppy. (As Kevin
wrote it, "like string literals" is an adjectival phrase in
apposition to the phrase "compound literals need not be distinct
objects".
 
F

Flash Gordon

Michael said:
Kevin didn't say they did; he said that compound literals of const-
qualified type were like string literals in that they need not be
distinct objects.

OK, I can accept that was his intent.
What he wrote is not ambiguous if you understand the dash as
separating two clauses - which is the preferred usage. You can only
read "like string literals" as an appositive to "compound literals
with const-qualified type" if you see the dash as separating two
phrases in the same clause, which would be rather sloppy. (As Kevin
wrote it, "like string literals" is an adjectival phrase in
apposition to the phrase "compound literals need not be distinct
objects".

I'm always willing to learn, but my experience is that using a dash to
separate two clauses is not very common. Using it to separate two
phrases in the same clause is also not very common in my experience.
 
M

Michael Wojcik

I'm always willing to learn, but my experience is that using a dash to
separate two clauses is not very common.

No? That's how I used it in the quoted text above - it's separating
an independent clause from a dependent clause. And in the previous
sentence it's separating two independent clauses.
Using it to separate two
phrases in the same clause is also not very common in my experience.

That would be the only other option, in a normal English sentence.
Sentences are composed of phrases. Any two adjacent phrases must
either be in the same clause or in two adjacent clauses. (Note
also that clauses are themselves phrases, and phrases can contain
phrases.)

So, if you have "X - Y", X and Y are by definition phrases, and
the dash is separating them. (All of "X - Y" may also be a phrase,
but within that phrase "X" and "Y" maintain their status as
distinct (nested) phrases because they're separated by the dash.)
Further, they're either in the same clause or not; and if not, those
two clauses are obviously adjacent, so the dash is separating them.

Among English stylists the dash seems generally to be regarded as
having two preferred uses in ordinary prose: to set off short
parenthetical (substituting for parentheses) or appositional (substi-
tuting for commas) phrases, and to separate independent clauses
(substituting for the semicolon or for a comma and coordinating
conjunction). Tom Wolfe, for example, uses the former to excess;
most good writers employ it sparingly.

Of course, this has gotten entirely OT.

--
Michael Wojcik (e-mail address removed)

They had forgathered enough of course in all the various times; they had
again and again, since that first night at the theatre, been face to face
over their question; but they had never been so alone together as they were
actually alone - their talk hadn't yet been so supremely for themselves.
-- Henry James
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,233
Latest member
AlyssaCrai

Latest Threads

Top