variable length record using struct/union - help

P

Panchal V

I want to access a variable length record in C, the format is as
follows :

+---+---+-----------+
| A | L | D A T A |
+---+---+-----------+
A - Some Data (1 BYTE)
L - Length the Data that follows (1 BYTE)
then actual data

I want to access and represent this record using struct/union in c,
how can I do it...
Data is variable length, L tell the length of data (in bytes) that
follows...
So that I can access it in this manner :
pData->A = 56;
pData->data[pData->L - 1] = '\0';



Now I want to represent
+---+---+-----------+---+
| A | L | D A T A | B |
+---+---+-----------+---+

where B - is some data ( 1 byte)
I want to access it like this
pData->B
(Remember it is after variable length data)

How can I do it....????

-Neo
 
M

Mark A. Odell

(e-mail address removed) (Panchal V) wrote in

Now I want to represent
+---+---+-----------+---+
| A | L | D A T A | B |
+---+---+-----------+---+

where B - is some data ( 1 byte)
I want to access it like this
pData->B
(Remember it is after variable length data)

How can I do it....????

You can't.
 
N

nrk

Panchal said:
I want to access a variable length record in C, the format is as
follows :

+---+---+-----------+
| A | L | D A T A |
+---+---+-----------+
A - Some Data (1 BYTE)
L - Length the Data that follows (1 BYTE)
then actual data

I want to access and represent this record using struct/union in c,
how can I do it...
Data is variable length, L tell the length of data (in bytes) that
follows...
So that I can access it in this manner :
pData->A = 56;
pData->data[pData->L - 1] = '\0';



Now I want to represent
+---+---+-----------+---+
| A | L | D A T A | B |
+---+---+-----------+---+

where B - is some data ( 1 byte)
I want to access it like this
pData->B
(Remember it is after variable length data)

How can I do it....????

You can't really do what you want. But a reasonable alternative might be to
define something like:

struct Record {
unsigned char A;
unsigned char L;
unsigned char *data;
};

#define GETB(rptr) ((rptr)->data[(rptr)->L])
#define SETB(rptr, val) ((rptr)->data[(rptr)->L] = val)

and use it like this:
struct Record *rptr;
...
unsigned char b = GETB(rptr);
...
SETB(rptr, b);

-nrk.
 
X

xarax

Panchal V said:
I want to access a variable length record in C, the format is as
follows :

+---+---+-----------+
| A | L | D A T A |
+---+---+-----------+
A - Some Data (1 BYTE)
L - Length the Data that follows (1 BYTE)
then actual data

I want to access and represent this record using struct/union in c,
how can I do it...
Data is variable length, L tell the length of data (in bytes) that
follows...
So that I can access it in this manner :
pData->A = 56;
pData->data[pData->L - 1] = '\0';



Now I want to represent
+---+---+-----------+---+
| A | L | D A T A | B |
+---+---+-----------+---+

where B - is some data ( 1 byte)
I want to access it like this
pData->B
(Remember it is after variable length data)

How can I do it....????

===============================
/* Use the "struct hack" approach. */
typedef struct header
{
unsigned char a; /* something */
unsigned char len; /* number of "data" elements */
unsigned char data[1]; /* element count is a lie */
} Header, * Header_P;


/*
* get the value of "unsigned char B" that follows
* the variable-length "data" array.
*/
unsigned char getB(Header_P header_p)
{
return *(header_p->len + header_p->data);
}

/*
* set the value of "unsigned char B" that
* follows the "data" array.
*/
void setB(Header_P header_p, unsigned char b)
{
*(header_p->len + header_p->data) = b;
}
===============================


--
----------------------------
Jeffrey D. Smith
Farsight Systems Corporation
24 BURLINGTON DRIVE
LONGMONT, CO 80501-6906
http://www.farsight-systems.com
z/Debug debugs your Systems/C programs running on IBM z/OS!
Are ISV upgrade fees too high? Check our custom product development!
 
L

Leor Zolman

I want to access a variable length record in C, the format is as
follows :

+---+---+-----------+
| A | L | D A T A |
+---+---+-----------+
A - Some Data (1 BYTE)
L - Length the Data that follows (1 BYTE)
then actual data

I want to access and represent this record using struct/union in c,
how can I do it...
Data is variable length, L tell the length of data (in bytes) that
follows...
So that I can access it in this manner :
pData->A = 56;
pData->data[pData->L - 1] = '\0';



Now I want to represent
+---+---+-----------+---+
| A | L | D A T A | B |
+---+---+-----------+---+

where B - is some data ( 1 byte)
I want to access it like this
pData->B
(Remember it is after variable length data)

How can I do it....????

If, in your structure, you represent your "data" with a _pointer_ and
allocate storage for it dynamically on-the-fly as you are reading your
data in, then you'll be able to use your desired syntax (since
subscripting works for pointers "as if" they were arrays).
-leor

Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
K

Kevin D. Quitt

I want to access a variable length record in C, the format is as
follows :

+---+---+-----------+
| A | L | D A T A |
+---+---+-----------+
A - Some Data (1 BYTE)
L - Length the Data that follows (1 BYTE)
then actual data

I want to access and represent this record using struct/union in c,
how can I do it...
Data is variable length, L tell the length of data (in bytes) that
follows...
So that I can access it in this manner :
pData->A = 56;
pData->data[pData->L - 1] = '\0';

struct
{
char A;
char L;
char data[];
} fred;

struct fred *pData;

Now I want to represent
+---+---+-----------+---+
| A | L | D A T A | B |
+---+---+-----------+---+

where B - is some data ( 1 byte)
I want to access it like this
pData->B
(Remember it is after variable length data)

How can I do it....????

You can't by name. The struct hack^W^W flexible array member has to be
the last member of the structure.

pData->data[ pData->L ] points to B.
 
O

Old Wolf

Now I want to represent
+---+---+-----------+---+
| A | L | D A T A | B |
+---+---+-----------+---+

where B - is some data ( 1 byte)
I want to access it like this
pData->B
(Remember it is after variable length data)

How can I do it....????

-Neo

typedef unsigned char *NEO_PTR;
#define NEO_A(np) ((np)[0])
#define NEO_L(np) ((np)[1])
#define NEO_DATA(np) ((np) + 2)
#define NEO_DATA_END(np) (NEO_DATA(np) + NEO_L(np))
#define NEO_B(np) (NEO_DATA_END(np)[0])

You can't access with the pointer syntax as you described.
Also, remember that these are macros so don't go "++" in them, etc.

NEO_PTR np = somewhere;
printf("B=%d, L=%d, A=%d, data=%s",
NEO_B(np), NEO_L(np), NEO_A(np), NEO_DATA(np));
NEO_B(np) = 15;
 
J

Jack Klein

Panchal V said:
I want to access a variable length record in C, the format is as
follows :

+---+---+-----------+
| A | L | D A T A |
+---+---+-----------+
A - Some Data (1 BYTE)
L - Length the Data that follows (1 BYTE)
then actual data

I want to access and represent this record using struct/union in c,
how can I do it...
Data is variable length, L tell the length of data (in bytes) that
follows...
So that I can access it in this manner :
pData->A = 56;
pData->data[pData->L - 1] = '\0';



Now I want to represent
+---+---+-----------+---+
| A | L | D A T A | B |
+---+---+-----------+---+

where B - is some data ( 1 byte)
I want to access it like this
pData->B
(Remember it is after variable length data)

How can I do it....????

===============================
/* Use the "struct hack" approach. */

No, don't, it's undefined behavior.
 
P

Panchal V

Now I want to represent
+---+---+-----------+---+
| A | L | D A T A | B |
+---+---+-----------+---+

where B - is some data ( 1 byte)
I want to access it like this
pData->B
(Remember it is after variable length data)

How can I do it....????

-Neo

typedef unsigned char *NEO_PTR;
#define NEO_A(np) ((np)[0])
#define NEO_L(np) ((np)[1])
#define NEO_DATA(np) ((np) + 2)
#define NEO_DATA_END(np) (NEO_DATA(np) + NEO_L(np))
#define NEO_B(np) (NEO_DATA_END(np)[0])

You can't access with the pointer syntax as you described.
Also, remember that these are macros so don't go "++" in them, etc.

NEO_PTR np = somewhere;
printf("B=%d, L=%d, A=%d, data=%s",
NEO_B(np), NEO_L(np), NEO_A(np), NEO_DATA(np));
NEO_B(np) = 15;

This approach seems to be good as compared to other hacks... if
side-effects are taken care of (sequence points) etc.

Thanks for your views...

- Neo
 
P

Panchal V

Jack Klein said:
Panchal V said:
I want to access a variable length record in C, the format is as
follows :

+---+---+-----------+
| A | L | D A T A |
+---+---+-----------+
A - Some Data (1 BYTE)
L - Length the Data that follows (1 BYTE)
then actual data

I want to access and represent this record using struct/union in c,
how can I do it...
Data is variable length, L tell the length of data (in bytes) that
follows...
So that I can access it in this manner :
pData->A = 56;
pData->data[pData->L - 1] = '\0';



Now I want to represent
+---+---+-----------+---+
| A | L | D A T A | B |
+---+---+-----------+---+

where B - is some data ( 1 byte)
I want to access it like this
pData->B
(Remember it is after variable length data)

How can I do it....????

===============================
/* Use the "struct hack" approach. */

No, don't, it's undefined behavior.

What's undefined?

-Neo
 
P

Panchal V

Kevin D. Quitt said:
I want to access a variable length record in C, the format is as
follows :

+---+---+-----------+
| A | L | D A T A |
+---+---+-----------+
A - Some Data (1 BYTE)
L - Length the Data that follows (1 BYTE)
then actual data

I want to access and represent this record using struct/union in c,
how can I do it...
Data is variable length, L tell the length of data (in bytes) that
follows...
So that I can access it in this manner :
pData->A = 56;
pData->data[pData->L - 1] = '\0';

struct
{
char A;
char L;
char data[];
} fred;

struct fred *pData;

Now I want to represent
+---+---+-----------+---+
| A | L | D A T A | B |
+---+---+-----------+---+

where B - is some data ( 1 byte)
I want to access it like this
pData->B
(Remember it is after variable length data)

How can I do it....????

You can't by name. The struct hack^W^W flexible array member has to be
the last member of the structure.

pData->data[ pData->L ] points to B.

char data[];
This doesn't seem to work on All implementations (compilers)

I'm using c51 by KEIL, it reports unknown array size...

And lets say we define one more variable after it, compiler starts
complaining, in GCC too...

-Neo
 
K

Kevin D. Quitt

Kevin D. Quitt said:
You can't by name. The struct hack^W^W flexible array member has to be
the last member of the structure.

char data[];
This doesn't seem to work on All implementations (compilers)

I'm using c51 by KEIL, it reports unknown array size...

Then it's not a C99 compiler. Per the Standard, 6.7.2.1:

16 As a special case, the last element of a structure with more than one
named member may have an incomplete array type; this is called a flexible
array member. With two exceptions, the flexible array member is ignored.
First, the size of the structure shall be equal to the offset of the last
element of an otherwise identical structure that replaces the flexible
array member with an array of unspecified length.106) Second, when a . (or
->) operator has a left operand that is (a pointer to) a structure with a
flexible array member and the right operand names that member, it behaves
as if that member were replaced with the longest array (with the same
element type) that would not make the structure larger than the object
being accessed; the offset of the array shall remain that of the flexible
array member, even if this would differ from that of the replacement
array. If this array would have no elements, it behaves as if it had one
element but the behavior is undefined if any attempt is made to access
that element or to generate a pointer one past it.


And lets say we define one more variable after it, compiler starts
complaining, in GCC too...

Of course, because the flexible array member must be the last member.
 
R

Richard Bos

Kevin D. Quitt said:
No, it isn't. It's part of C99, although they call it "flexible array
member".

But what xanax (to whom Jack Klein replied) demonstrated wasn't a C99
flexible array member, but a C89 mini-array-and-malloc struct hack. And
that _is_ undefined.

Richard
 
K

Kevin D. Quitt

But what xanax (to whom Jack Klein replied) demonstrated wasn't a C99
flexible array member, but a C89 mini-array-and-malloc struct hack. And
that _is_ undefined.

Indeed - my bad.
 
O

Old Wolf

struct
{
char A;
char L;
char data[];
} fred;
char data[];
This doesn't seem to work on All implementations (compilers)

I'm using c51 by KEIL, it reports unknown array size...

This is a very horrible compiler (probably you have no choice though?)
You may find you have to employ many non-standard hacks, to get
anything useful done.

Go
char data[1];
instead.
 
M

Mark A. Odell

(e-mail address removed) (Old Wolf) wrote in

struct
{
char A;
char L;
char data[];
} fred;
char data[];
This doesn't seem to work on All implementations (compilers)

I'm using c51 by KEIL, it reports unknown array size...

This is a very horrible compiler (probably you have no choice though?)

It is a *very good* C51 compiler for the 8051. There are other choices but
this is one of the best. As for C you cannot use char data[];
You may find you have to employ many non-standard hacks, to get
anything useful done.

Go
char data[1];
instead.

You mean you must do char data[1] instead since C89 will not allow char
data[]. Keil good, undimensioned arrays - not permitted.
 
O

Old Wolf

I'm using c51 by KEIL, it reports unknown array size...
This is a very horrible compiler (probably you have no choice though?)

It is a *very good* C51 compiler for the 8051. There are other choices but
this is one of the best. As for C you cannot use char data[];

Perhaps I just have an old version then? (V4.01)
Or perhaps I just remember hours and hours of mucking around with
platform-specific issues and linker memory allocation bugs (eg.
putting concurrently-used variables at overlapping locations),
and am tarring the compiler with the same brush.
You may find you have to employ many non-standard hacks, to get
anything useful done.

Go
char data[1];
instead.

You mean you must do char data[1] instead since C89 will not allow char
data[]. Keil good, undimensioned arrays - not permitted.

I didn't mean to imply that Keil was bad for requiring "char data[1]"
(although I do consider accessing members past the end of an
array to be a 'nonstandard hack').
 
M

Mark A. Odell

(e-mail address removed) (Old Wolf) wrote in

I'm using c51 by KEIL, it reports unknown array size...

This is a very horrible compiler (probably you have no choice
though?)

It is a *very good* C51 compiler for the 8051. There are other choices
but this is one of the best. As for C you cannot use char data[];

Perhaps I just have an old version then? (V4.01)

Old would be an understatment. My god man, upgrade now!

:)
 

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,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top