Function Returning Anonymous Struct

S

Shao Miller

An interesting fellow in another C-devoted forum brought up a
question:

struct { char x; } f() {
/* ... */
/* What can we return? */
return TODO;
}

He/she suggested that all anonymous (tagless) 'struct's had
incompatible types, which didn't fit my recollection of 6.2.7,p1,
where I remembered "...are compatible if their tags and members
satisfy the following requirements..." However, upon re-reading, that
text is immediately preceded by "...declared in separate translation
units". :)

It also appears to be related to the common situation in Annex I,p2,
first sub-point.

So the best I could muster up were these:

-----
struct { char x; } f() {
/* ... */
/* Well actually, we won't return. ;) */
return f();
}
/* main() */
-----

-----
/**
* This code is non-portable due to:
* - Pointer arith. with a null pointer
* - Casting a pointer to size_t to yield
* a simple "byte address" integer
* - The assumption that "byte address 0" is
* suitably aligned for any type
* Furthermore, the function returns a _pointer_, unlike the original.
*/

#include <stddef.h>
#include <stdio.h>

#define TT (1 ? 0 : f())
#define sz (sizeof *f())

struct { char x; } *f(void) {
unsigned char scratch[sz * 2];
size_t off = (size_t)&scratch;
off += sz - off % sz;
off /= sz;
TT[off].x = 'C';
return TT + off;
}

int main(void) {
char c;
c = f()[0].x;
printf("Returned: '%c'\n", c);
return 0;
}
-----

-----
/**
* This code should be fine (right?) except, as was pointed
* out by the original questioner, that it's not thread-safe. ;)
* The function also returns a _pointer_, unlike the original.
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>

struct { char x; } *f(void) {
static void *scratch = NULL;
static int called_by_self = 0;

if (called_by_self)
return scratch;
if (!scratch)
scratch = malloc(sizeof *f());
if (!scratch)
return NULL;
called_by_self = 1;
f()->x = 'C';
called_by_self = 0;
return scratch;
}

int main(void) {
char c;

/* We should watch-out for a null pointer here, in practice. */
c = f()->x;
printf("Returned: '%c'\n", c);
return 0;
}
-----

Does anyone have any other ideas for how the function 'f' of the
original question might be able to return a value?

Thanks. :)

- Shao Miller
 
S

Shao Miller

... ... ...
struct { char x; } *f(void) {
  unsigned char scratch[sz * 2];
  size_t off = (size_t)&scratch;
  off += sz - off % sz;
  off /= sz;
  TT[off].x = 'C';
  return TT + off;
... ... ...
Oh, I admitted that this also returns a pointer to an object whose
lifetime expires immediately after the 'return', too. ;)
 
S

Shao Miller

Or we could use C99 compound literals. This is thread-safe, but in a
compound statement for an iteration statement, could result in
multiple 'auto' storage duration nameless objects. This still needs
to return a pointer, unlike the original question:

#include <stdio.h>

struct { char x; } *f_(void *vp, int self_called) {
if (self_called)
return vp;
f_(vp, 1)->x = 'C';
return vp;
}
#define f() (f_((char[sizeof *f_(0,0)]){ 0 }, 0))

int main(void) {
char c;
c = f()->x;
printf("Returned: '%c'\n", c);
return 0;
}
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top