one element array as name of struct typedef

  • Thread starter Ron Peterson (012ED25E)
  • Start date
R

Ron Peterson (012ED25E)

I ran into something like the following while looking into how the GNU
MP library implements its mpz_t type.

typedef struct {
int len;
char *buf;
} foo[1];

This is an interesting technique. I'm unfamiliar with declaring the
name of a typedef as a one element array. Is this part of the C
standard? Is it portable? Does this technique have a name?
 
M

Mark Bluemel

Ron said:
I ran into something like the following while looking into how the GNU
MP library implements its mpz_t type.

typedef struct {
int len;
char *buf;
} foo[1];

This is an interesting technique. I'm unfamiliar with declaring the
name of a typedef as a one element array. Is this part of the C
standard? Is it portable? Does this technique have a name?


Hmmm.... I think you're mistaken in what this means.

My reading (which could easily be incorrect) is that it makes "foo" a
typedef for a single dimension, single element, array of such structures.

I'm trying to work out what the value of such a technique would be.
 
R

Richard Tobin

typedef struct {
int len;
char *buf;
} foo[1];
[/QUOTE]
I'm trying to work out what the value of such a technique would be.

My guess is that it's a neat trick for having objects that are (in
effect) automatically passed by reference. If it had been

typedef struct {...} foo;

you would have to use &foo all over the place, and it it had been

typedef struct {...} *foo;

you would have to allocate the data as well as declaring a variable.

-- Richard
 
R

Ravishankar S

I ran into something like the following while looking into how the GNU
MP library implements its mpz_t type.

typedef struct {
int len;
char *buf;
} foo[1];

This is an interesting technique. I'm unfamiliar with declaring the
name of a typedef as a one element array. Is this part of the C
standard? Is it portable? Does this technique have a name?

typeof(foo) == array of the given struct of 1 element

so the actual array may be declared or defined as:

foo fooarray; /* Note: No dimension info required */

the technique is useful when a pointer to an array (i mean entire array, not
just pointer to element data type) is required.
read C FAQ. Ther is a entire chapter devoted to pointers and array.
 
R

Ravishankar S

Richard Tobin said:
typedef struct {
int len;
char *buf;
} foo[1];
I'm trying to work out what the value of such a technique would be.

My guess is that it's a neat trick for having objects that are (in
effect) automatically passed by reference. If it had been

typedef struct {...} foo;[/QUOTE]

No. The typedef is similar to , say..

typedef unsigned int length_t;

Do we use &length_t anywhere ? the length_t is the *name* of a *type*.

similarly with foo. could have been named better as "foo_array_type"
 
A

Army1987

Ron said:
I ran into something like the following while looking into how the GNU
MP library implements its mpz_t type.

typedef struct {
int len;
char *buf;
} foo[1];

This is an interesting technique. I'm unfamiliar with declaring the
name of a typedef as a one element array. Is this part of the C
standard? Is it portable? Does this technique have a name?


Hmmm.... I think you're mistaken in what this means.

My reading (which could easily be incorrect) is that it makes "foo" a
typedef for a single dimension, single element, array of such structures.

I'm trying to work out what the value of such a technique would be.
On glibc, jmp_buf is declared as an array with one element.
 
R

Richard Tobin

My guess is that it's a neat trick for having objects that are (in
effect) automatically passed by reference. If it had been

typedef struct {...} foo;
[/QUOTE]
No. The typedef is similar to , say..

Sorry, I just made a mistake in the line you snipped. What I should
have said was:

If it had been

typedef struct {...} mpz_t;

than after declaring

mpz_t x;

you would have to use &x all over the place.

Declaring the type as a single-element array is a way of hiding from
the user the fact that it's a structure and needs to have its address
passed to the library functions.

-- Richard
 
R

Ron Peterson (012ED25E)

typedef struct {
int len;
char *buf;
} foo[1];
I'm trying to work out what the value of such a technique would be.

My guess is that it's a neat trick for having objects that are (in
effect) automatically passed by reference. If it had been

typedef struct {...} foo;

you would have to use &foo all over the place, and it it had been

typedef struct {...} *foo;

you would have to allocate the data as well as declaring a variable.[/QUOTE]

Yes. I was trying to emulate the way the MP library worked, and that
is how I discovered this. It lets you avoid ampersands, and
automatically allocates the structure. So you can do 'foo avar;', and
then pass avar to an initialization function, say, that would take
care of setting the values of 'len' and 'buf'. I rather like the
technique, I'm mostly just wondering if it's standard and portable.
 
M

Mark Bluemel

Richard said:
typedef struct {
int len;
char *buf;
} foo[1];
I'm trying to work out what the value of such a technique would be.

My guess is that it's a neat trick for having objects that are (in
effect) automatically passed by reference. If it had been

typedef struct {...} foo;

you would have to use &foo all over the place, and it it had been

typedef struct {...} *foo;

you would have to allocate the data as well as declaring a variable.[/QUOTE]

And how is this worse than having to artificially use a "[0]" subscript
all the time?

Oh! Is it the case that the code which declares items of type "foo"
never actually work with their contents - effectively treating them as
opaque? Clever, I guess...
 
R

Richard Tobin

And how is this worse than having to artificially use a "[0]" subscript
all the time?

You don't...
Oh! Is it the case that the code which declares items of type "foo"
never actually work with their contents - effectively treating them as
opaque? Clever, I guess...

Exactly. This is code provided by a library.

A more common approach would be to declare the type as a pointer, and
require you to call a function to allocate the object. But this way
you can just declare it in the usual way. Unfortunately it looks as
if you would still have to do something explicit to free it, since it
contains a pointer to a buffer.

(I haven't used the library, I'm just inferring this from the definition.)

-- Richard
 
B

Bart van Ingen Schenau

Ron said:
I ran into something like the following while looking into how the GNU
MP library implements its mpz_t type.

typedef struct {
int len;
char *buf;
} foo[1];

This is an interesting technique. I'm unfamiliar with declaring the
name of a typedef as a one element array. Is this part of the C
standard? Is it portable? Does this technique have a name?

Yes, the semantics of this declaration are fully defined by the C
standard, and the technique is therefor portable.
I am not familiar with using it, so I can't tell if it has a name or
not.

Bart v Ingen Schenau
 
R

Ron Peterson (012ED25E)

Mark Bluemel said:
And how is this worse than having to artificially use a "[0]" subscript
all the time?

You don't...
Oh! Is it the case that the code which declares items of type "foo"
never actually work with their contents - effectively treating them as
opaque? Clever, I guess...

Exactly. This is code provided by a library.

A more common approach would be to declare the type as a pointer, and
require you to call a function to allocate the object. But this way
you can just declare it in the usual way. Unfortunately it looks as
if you would still have to do something explicit to free it, since it
contains a pointer to a buffer.

(I haven't used the library, I'm just inferring this from the definition.)

Yeah. GNU MP has you do:

mpz_t avar;
mpz_init( avar );
....do something with avar
mpz_clear( avar );

I think this seems cleaner than

struct astruct *avar = NULL;
avar = malloc( sizeof( struct astruct ) );
init_function( &avar );
...do something
clear_function( &avar );
free( avar );

....which, AFAIKT, is the least amount of code you'd have to write to
do the same thing without the clever one element array.
 
R

Ron Peterson (012ED25E)

And how is this worse than having to artificially use a "[0]" subscript
all the time?
You don't...
Exactly. This is code provided by a library.
A more common approach would be to declare the type as a pointer, and
require you to call a function to allocate the object. But this way
you can just declare it in the usual way. Unfortunately it looks as
if you would still have to do something explicit to free it, since it
contains a pointer to a buffer.
(I haven't used the library, I'm just inferring this from the definition.)

Yeah. GNU MP has you do:

mpz_t avar;
mpz_init( avar );
...do something with avar
mpz_clear( avar );

I think this seems cleaner than

struct astruct *avar = NULL;
avar = malloc( sizeof( struct astruct ) );
init_function( &avar );
..do something
clear_function( &avar );
free( avar );

...which, AFAIKT, is the least amount of code you'd have to write to
do the same thing without the clever one element array.

whoops, forget the ampersands of course...
 
O

Old Wolf

Yeah. GNU MP has you do:

mpz_t avar;
mpz_init( avar );
...do something with avar
mpz_clear( avar );

I think this seems cleaner than

struct astruct *avar = NULL;
avar = malloc( sizeof( struct astruct ) );
init_function( &avar );
..do something
clear_function( &avar );
free( avar );

...which, AFAIKT, is the least amount of code you'd have to write to
do the same thing without the clever one element array.

You overlooked:
avar_t avar;
init_func(&avar);
......
clear_func(&avar);

which is no more complicated than the mpz variation. I
find the technique distasteful, as its only function
appears to be to obfuscate the code. Code which looks
like it passes objects by value, actually modifies the
objects.
 
K

Keith Thompson

Army1987 said:
Ron said:
I ran into something like the following while looking into how the GNU
MP library implements its mpz_t type.

typedef struct {
int len;
char *buf;
} foo[1];

This is an interesting technique. I'm unfamiliar with declaring the
name of a typedef as a one element array. Is this part of the C
standard? Is it portable? Does this technique have a name?

Hmmm.... I think you're mistaken in what this means.

My reading (which could easily be incorrect) is that it makes "foo" a
typedef for a single dimension, single element, array of such structures.

I'm trying to work out what the value of such a technique would be.
On glibc, jmp_buf is declared as an array with one element.

The standard specifically requires jmp_buf to be an array type.
 
R

Richard Tobin

On glibc, jmp_buf is declared as an array with one element.
[/QUOTE]
The standard specifically requires jmp_buf to be an array type.

Because historically it was just an array of a few ints, into which
some registers were copied.

-- Richard
 
A

Army1987

The standard specifically requires jmp_buf to be an array type.

Because historically it was just an array of a few ints, into which
some registers were copied.

-- Richard[/QUOTE]
And it continued to be an array, in order to be able to pass it
"by reference" without using unary &. See the C99 rationale:
7.13 Nonlocal jumps <setjmp.h>
jmp_buf must be an array type for compatibility with existing practice: programs typically
omit the address operator before a jmp_buf argument, even though a pointer to the argument is
20 desired, not the value of the argument itself. Thus, a scalar or structure type is unsuitable. Note
that a one-element array of the appropriate type is a valid definition.
 
J

James Antill

Richard said:
Mark Bluemel said:
typedef struct {
int len;
char *buf;
} foo[1];
I'm trying to work out what the value of such a technique would be.

My guess is that it's a neat trick for having objects that are (in
effect) automatically passed by reference. If it had been

typedef struct {...} foo;

you would have to use &foo all over the place, and it it had been

typedef struct {...} *foo;

you would have to allocate the data as well as declaring a variable.

And how is this worse than having to artificially use a "[0]" subscript
all the time?

Well you can use foo->len etc. which I've done before, although I don't
hide it in typedef's.
 
B

Ben Pfaff

typedef struct {
int len;
char *buf;
} foo[1];
I'm trying to work out what the value of such a technique would be.

My guess is that it's a neat trick for having objects that are (in
effect) automatically passed by reference. [...][/QUOTE]

For what it's worth, the canonical example of this technique is
the jmp_buf type declared in <setjmp.h>.
 

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,776
Messages
2,569,602
Members
45,182
Latest member
BettinaPol

Latest Threads

Top