Can it be done at compile time?

A

Ark

Hello NG,
I arrange data in structs like
{
members...
uint16_t crc;
more members, maybe...
}
Then I need to save them, up to and including crc, in non-volatile
memory or a file, as the case may be.
The data size I need for type T is offsetof(struct T, crc) +
sizeof(uint16_t).
(Even if there are no more-members, this, depending on alignment, may be
shorter than sizeof(struct T).

The trouble comes when I try to test, at compile time, that I haven't
exceeded the max size of NV memory or of the file.
For expressions involving sizeof, I learned the routine:
#define SIZE ...sum up accordingly...
extern char dummy[(SIZE<=SIZE_MAX)?1:-1];
This won't take offsetof though 'cause it uses pointer type internally
and is not an "integer expression".
Is there any creative way to test the size limit at compile time?

BTW, I believe it is portable to assume that members are before crc and
more-members are after it. Is this correct? (Oh, /assumption/ is
portable, but you know what I mean :)

Thanks
- Ark
 
T

Tom St Denis

Ark said:
Hello NG,
I arrange data in structs like
{
members...
uint16_t crc;
more members, maybe...
}
Then I need to save them, up to and including crc, in non-volatile
memory or a file, as the case may be.
The data size I need for type T is offsetof(struct T, crc) +
sizeof(uint16_t).
(Even if there are no more-members, this, depending on alignment, may be
shorter than sizeof(struct T).

I don't get your question.... but assuming it's something like

1. You want data in a structure
2. You want said data to include a CRC of said data....

Just write a script called from your makefile that generates a .c file
that has a structure in it.

Tom
 
W

Wojtek Lerch

Ark said:
This won't take offsetof though 'cause it uses pointer type internally and
is not an "integer expression".

Then your implementation is broken. The C standard requires offsetof to be
an integer constant expression:

7.17 Common definitions <stddef.h>
[...]
3 The macros are

NULL

which expands to an implementation-defined null pointer constant; and

offsetof(type, member-designator)

which expands to an integer constant expression that has type size_t, the
value of which is the offset in bytes, to the structure member (designated
by member-designator), from the beginning of its structure (designated by
type). [...]

[Followups restricted to comp.lang.c]
 
A

Ark

Wojtek said:
Ark said:
This won't take offsetof though 'cause it uses pointer type internally and
is not an "integer expression".

Then your implementation is broken. The C standard requires offsetof to be
an integer constant expression:

7.17 Common definitions <stddef.h>
[...]
3 The macros are

NULL

which expands to an implementation-defined null pointer constant; and

offsetof(type, member-designator)

which expands to an integer constant expression that has type size_t, the
value of which is the offset in bytes, to the structure member (designated
by member-designator), from the beginning of its structure (designated by
type). [...]

[Followups restricted to comp.lang.c]
Well, most of the time it is like
#define offsetof(type, member) ((size_t)&((type *)0)->member))
or something to that end.
That ain't good enough for array dimension.

Thanks,

Ark
 
K

Keith Thompson

Ark said:
I arrange data in structs like
{
members...
uint16_t crc;
more members, maybe...
}
Then I need to save them, up to and including crc, in non-volatile
memory or a file, as the case may be.
The data size I need for type T is offsetof(struct T, crc) +
sizeof(uint16_t).
(Even if there are no more-members, this, depending on alignment, may
be shorter than sizeof(struct T).

The trouble comes when I try to test, at compile time, that I haven't
exceeded the max size of NV memory or of the file.
For expressions involving sizeof, I learned the routine:
#define SIZE ...sum up accordingly...
extern char dummy[(SIZE<=SIZE_MAX)?1:-1];
This won't take offsetof though 'cause it uses pointer type internally
and is not an "integer expression".
Is there any creative way to test the size limit at compile time?

This is a C programming question, not a question about the standard.
Followups redirected to comp.lang.c.
BTW, I believe it is portable to assume that members are before crc
and more-members are after it. Is this correct? (Oh, /assumption/ is
portable, but you know what I mean :)

Yes, struct members are guaranteed to be allocated in their declared
order.
 
M

Michael Mair

Ark said:
Wojtek said:
This won't take offsetof though 'cause it uses pointer type
internally and is not an "integer expression".

Then your implementation is broken. The C standard requires offsetof
to be an integer constant expression:

7.17 Common definitions <stddef.h>
[...]
3 The macros are

NULL

which expands to an implementation-defined null pointer constant; and

offsetof(type, member-designator)

which expands to an integer constant expression that has type size_t,
the value of which is the offset in bytes, to the structure member
(designated by member-designator), from the beginning of its structure
(designated by type). [...]

[Followups restricted to comp.lang.c]
Well, most of the time it is like
#define offsetof(type, member) ((size_t)&((type *)0)->member))
or something to that end.
That ain't good enough for array dimension.

_How_ offetof is implemented is the implementation's problem.
The standard says how offsetof behaves -- and this is what you
can rely on for a conforming implementation.
Reread what Wojtek Lerch wrote and consider

,---
$ cat offsetof.c
#include <stddef.h>

#define SIZE_MAX 9
#define CRC_SIZE(T) (offsetof(T, crc) \
+ sizeof(unsigned short))
#define CHECK(Tag, Limit) \
static int baz_##Tag[CRC_SIZE(struct Tag) < (size_t) (Limit) \
? 1 : -1]

struct foo {
int bar;
unsigned short crc;
};

CHECK(foo, SIZE_MAX);

int main (void)
{
return 0;
}

$ gcc -std=c89 -pedantic -Wall -Wextra -O offsetof.c -c
offsetof.c:15: warning: 'baz_foo' defined but not used

$ splint -checks offsetof.c
Splint 3.1.1 --- 02 May 2003

offsetof.c:15:104: File static variable baz_foo declared but not used
A variable is declared but never used. Use /*@unused@*/ in front of
declaration to suppress message. (Use -varuse to inhibit warning)

Finished checking --- 1 code warning

`---

where my implementation's offsetof is defined in the way you
describe above.
For
#define SIZE_MAX 1
I get an error because of negative array size.


Cheers
Michael
 
K

Keith Thompson

Ark said:
Wojtek said:
Ark said:
This won't take offsetof though 'cause it uses pointer type
internally and is not an "integer expression".
Then your implementation is broken. The C standard requires
offsetof to be an integer constant expression:
7.17 Common definitions <stddef.h>
[...]
3 The macros are
NULL
which expands to an implementation-defined null pointer constant; and
offsetof(type, member-designator)
which expands to an integer constant expression that has type
size_t, the value of which is the offset in bytes, to the structure
member (designated by member-designator), from the beginning of its
structure (designated by type). [...]
[Followups restricted to comp.lang.c]
Well, most of the time it is like
#define offsetof(type, member) ((size_t)&((type *)0)->member))
or something to that end.
That ain't good enough for array dimension.

Read it again. The standard requires offsetof() to expand to an
integer constant expression. If the following:

#include <stddef.h>
void foo(void)
{
struct s {
int a;
int b;
};
int arr[offsetof(struct s, b)];
}

doesn't compile, your compiler is broken. (Possibly a compiler might
need to support additional forms of constant expression to make this
work.)
 
A

Ark

Keith said:
Ark said:
Wojtek said:
This won't take offsetof though 'cause it uses pointer type
internally and is not an "integer expression".
Then your implementation is broken. The C standard requires
offsetof to be an integer constant expression:
7.17 Common definitions <stddef.h>
[...]
3 The macros are
NULL
which expands to an implementation-defined null pointer constant; and
offsetof(type, member-designator)
which expands to an integer constant expression that has type
size_t, the value of which is the offset in bytes, to the structure
member (designated by member-designator), from the beginning of its
structure (designated by type). [...]
[Followups restricted to comp.lang.c]
Well, most of the time it is like
#define offsetof(type, member) ((size_t)&((type *)0)->member))
or something to that end.
That ain't good enough for array dimension.

Read it again. The standard requires offsetof() to expand to an
integer constant expression. If the following:

#include <stddef.h>
void foo(void)
{
struct s {
int a;
int b;
};
int arr[offsetof(struct s, b)];
}

doesn't compile, your compiler is broken. (Possibly a compiler might
need to support additional forms of constant expression to make this
work.)
Sorry, I just made a fool of myself: offsetof was redefined in my
environment.
Thank you all and sorry again.
- Ark
 
D

Douglas A. Gwyn

Ark said:
Is there any creative way to test the size limit at compile time?

No, because it would have to be done by the preprocessor, which
doesn't know what types are being used in the program (and thus
does not know their sizes).

I usually let the linker tell me about such things.
 
H

Hans-Bernhard Broeker

No, because it would have to be done by the preprocessor, which
doesn't know what types are being used in the program (and thus
does not know their sizes).

Huh? Since when is "at compile time" synonymous with "at preprocessing
time"? The compiler can certainly be abused to test assertions at
compile time. The OP himself even demonstrated one way of doing that:
by modulating an array size to become negative if the condition fails.
Sure, the error message will be cryptic, but it's a compile time test
all the same.

The OP's problem apparently was that his compiler's implementation of
the offsetof() macro is broken. Not much can be done about that.
 
D

Douglas A. Gwyn

Hans-Bernhard Broeker said:
Huh? Since when is "at compile time" synonymous with "at preprocessing
time"?

When one is "testing at compile time".
The compiler can certainly be abused to test assertions at compile time.

I assumed he wanted to do something more constructive after testing.
 
D

David R Tribble

When one is "testing at compile time".
I assumed he wanted to do something more constructive after testing.

There are macros in <limits.h> that allow the preprocessor to deduce
primitive type sizes.

Unfortunately, that's about all it can glean from any of the standard
headers and macros. I suggested many years ago that we need more
(standard) macros so that portable code can deal with issues like
alignment, endianness, etc.:
http://david.tribble.com/text/c9xmach.txt

Currently, code that needs this kind of information must rely on
hand-written or automatically generated (e.g., from GNU 'config')
header files, none of which are universal.

-drt
 
H

Hans-Bernhard Broeker

When one is "testing at compile time".

I had expected you to know better than that. "Compile time" is
divided into translation phases, only the first few of which are
"preprocessing". What the OP wanted to do can't be done in those
phases, but since he actually wanted an assertion, not a an arbitrary
condition test, it *can* be done later, by triggering a compiler error
if the test condition fails:

char dummy_array[(condition)?1:-1];

I assumed he wanted to do something more constructive after testing.

Why? He clearly wanted just a compile-time assert().
 

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,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top