473,386 Members | 1,785 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

endof

Is there a macro for determining the address of the end of an object? For
example, if f is a pointer to an instance of the below struct, endof(f->a)
would be equal to the address of member b.

struct foo {
int a[N];
int b;
};

If not, is the following sufficient in all cases?

#define endof(o) ((char *)(&(o)) + sizeof(o))

Mike

Nov 15 '05 #1
9 2177


Michael B Allen wrote:
Is there a macro for determining the address of the end of an object? For
example, if f is a pointer to an instance of the below struct, endof(f->a)
would be equal to the address of member b.

struct foo {
int a[N];
int b;
};

If not, is the following sufficient in all cases?

#define endof(o) ((char *)(&(o)) + sizeof(o))

We have just had a pretty long discussion on offsetof() macro, that
should
serve you well.Look at the FAQ & search the group, please.

Nov 15 '05 #2
Michael B Allen wrote:
Is there a macro for determining the address of the end of an object? For
example, if f is a pointer to an instance of the below struct, endof(f->a)
would be equal to the address of member b.
You mean the first address _after_ the end of an object.
struct foo {
int a[N];
int b;
};
Note that there may be padding between structure members
even in this case.
The "relative address" of b within a struct foo can be found
by using the offsetof macro from <stddef.h>
If not, is the following sufficient in all cases?

#define endof(o) ((char *)(&(o)) + sizeof(o))


Nope. Think of arrays passed (via pointer to their first element)
to a function.
It should work for scalar types and struct and union types.
Depending on the intended use, I would consider casting the
calculated address to void *.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 15 '05 #3
Michael B Allen wrote:
Is there a macro for determining the address of the end of an object? For
example, if f is a pointer to an instance of the below struct, endof(f->a)
would be equal to the address of member b.
I hope you are aware that the "end" of a and the beginning of b are not
necessarily the same.
And no, there is no macro for that in the standard library. And if there
were, I'd wonder why.
struct foo {
int a[N];
int b;
};

If not, is the following sufficient in all cases?

#define endof(o) ((char *)(&(o)) + sizeof(o))


If that is really what you want, then it's correct ;)
What do you intend to use it for?
Christian
Nov 15 '05 #4
On Mon, 27 Jun 2005 09:07:21 +0200, Michael Mair wrote:

....
If not, is the following sufficient in all cases?

#define endof(o) ((char *)(&(o)) + sizeof(o))
Nope. Think of arrays passed (via pointer to their first element)
to a function.


The macro still works, but it gives you (one past) the end of the object
you specify i.e. a pointer in that case.
It should work for scalar types and struct and union types.


It works for arrays too, as long as you use on the actual array and not a
pointer. For example with:
struct foo {
int a[N];
int b;
};


struct foo s;

then

endof(s.a);

will give you the address of the character just after the end of s.a.

Lawrence
Nov 15 '05 #5
Lawrence Kirby wrote:
On Mon, 27 Jun 2005 09:07:21 +0200, Michael Mair wrote:

...

If not, is the following sufficient in all cases?

#define endof(o) ((char *)(&(o)) + sizeof(o))


Nope. Think of arrays passed (via pointer to their first element)
to a function.


The macro still works, but it gives you (one past) the end of the object
you specify i.e. a pointer in that case.


Yep. I just wanted to warn about it.

It should work for scalar types and struct and union types.


It works for arrays too, as long as you use on the actual array and not a
pointer. For example with:
struct foo {
int a[N];
int b;
};


struct foo s;

then

endof(s.a);

will give you the address of the character just after the end of s.a.


Thanks, this was too sloppy on my part.

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 15 '05 #6
On Mon, 27 Jun 2005 09:58:56 +0200, Christian Kandeler wrote:
struct foo {
int a[N];
int b;
};

If not, is the following sufficient in all cases?

#define endof(o) ((char *)(&(o)) + sizeof(o))


If that is really what you want, then it's correct ;)
What do you intend to use it for?


I'll give you two examples.

1) I have a habit of using limit pointers where someone might normally
pass a size. For example instead of using strncpy I prefer the following
function instead:

int
str_copy(const unsigned char *src,
const unsigned char *slim,
unsigned char *dst,
unsigned char *dlim,
int n);

The idea is that it's a little less error prone to assert 'src < slim'
as opposed to 'n > 0' and then also have to adjust n by some appropriate
amount. Now if all of your string processing functions are designed
like this, they tend to cascade together resulting in overall smaller
code. This is safer because slim never changes.

So sometimes I find myself computing where the end of an object is. For
example:

struct foo {
int i;
char name[NAME_MAX];
};

str_copy(src, slim, f->name, endof(f->name));

This case is a little too simple to illustrate its usefulness but I do
a lot of complex decoding and encoding of formats and find techniques
like this important.

2) Another case is when I embed a bitset at the end of a struct to allow
the number of bits to be variable like:

struct fancy_array {
...
void *blim; /* endof bitset */
char bitset[1]; /* incomplete */
}
struct foo {
struct fancy_array bar;
char bar_bitset[MAX_BARS / 8];
...

So bar_bitset just reserves space for the fancy_array's bitset. But to
initialize this I need to pass the end of bar_bitset so we can set blim:

fancy_array_init(&f->bar, endof(f->bar_bitset));

Mike

Nov 15 '05 #7
Michael B Allen wrote:
#define endof(o) ((char *)(&(o)) + sizeof(o))
If that is really what you want, then it's correct ;)
What do you intend to use it for?


I'll give you two examples.

1) I have a habit of using limit pointers where someone might normally
pass a size.


That's okay, then. As you may have noticed, some of us were afraid you'd use
it to compute the offset of struct members.
For example instead of using strncpy I prefer the following
function instead:

int
str_copy(const unsigned char *src,
const unsigned char *slim,
unsigned char *dst,
unsigned char *dlim,
int n);

The idea is that it's a little less error prone to assert 'src < slim'
as opposed to 'n > 0' and then also have to adjust n by some appropriate
amount. Now if all of your string processing functions are designed
like this, they tend to cascade together resulting in overall smaller
code. This is safer because slim never changes.
I don't see how that makes things safer. On the contrary, you are
introducing redundancy (and a source for errors) by adding the additional
constraint of (dlim - dst == slim - src). And on top of all that, you still
pass n. I would stick with the canonical way.
So sometimes I find myself computing where the end of an object is. For
example:

struct foo {
int i;
char name[NAME_MAX];
};

str_copy(src, slim, f->name, endof(f->name));

This case is a little too simple to illustrate its usefulness but I do
a lot of complex decoding and encoding of formats and find techniques
like this important.
The technique of passing the same information with a higher number of
arguments? ;)
2) Another case is when I embed a bitset at the end of a struct to allow
the number of bits to be variable like:

struct fancy_array {
...
void *blim; /* endof bitset */
char bitset[1]; /* incomplete */
Huh? Why is blim the end of bitset?
}
struct foo {
struct fancy_array bar;
char bar_bitset[MAX_BARS / 8];
...

So bar_bitset just reserves space for the fancy_array's bitset. But to
initialize this I need to pass the end of bar_bitset so we can set blim:

fancy_array_init(&f->bar, endof(f->bar_bitset));


You completely lost me here... Either this makes no sense or I am stupid.
Christian
Nov 15 '05 #8
Christian Kandeler wrote:
Michael B Allen wrote:

#define endof(o) ((char *)(&(o)) + sizeof(o))

If that is really what you want, then it's correct ;)
What do you intend to use it for?
I'll give you two examples.

1) I have a habit of using limit pointers where someone might normally
pass a size.


That's okay, then. As you may have noticed, some of us were afraid you'd use
it to compute the offset of struct members.
For example instead of using strncpy I prefer the following
function instead:

int
str_copy(const unsigned char *src,
const unsigned char *slim,
unsigned char *dst,
unsigned char *dlim,
int n);

The idea is that it's a little less error prone to assert 'src < slim'
as opposed to 'n > 0' and then also have to adjust n by some appropriate
amount. Now if all of your string processing functions are designed
like this, they tend to cascade together resulting in overall smaller
code. This is safer because slim never changes.


I don't see how that makes things safer. On the contrary, you are
introducing redundancy (and a source for errors) by adding the additional
constraint of (dlim - dst == slim - src). And on top of all that, you still
pass n. I would stick with the canonical way.


Yep, but n can now be easily larger than slim-src, or slim-src and/or
n can be larger than dlim-dst and you can easily implement the whole
thing safely.

So sometimes I find myself computing where the end of an object is. For
example:

struct foo {
int i;
char name[NAME_MAX];
};

str_copy(src, slim, f->name, endof(f->name));

This case is a little too simple to illustrate its usefulness but I do
a lot of complex decoding and encoding of formats and find techniques
like this important.


The technique of passing the same information with a higher number of
arguments? ;)


Nope. Think of copying something other than strings -- there you
need some way of finding out about maximum number of bytes to be
copied and maximum number of bytes the destination can hold.
At least with the above way of going about it, of course.

2) Another case is when I embed a bitset at the end of a struct to allow
the number of bits to be variable like:

struct fancy_array {
...
void *blim; /* endof bitset */
char bitset[1]; /* incomplete */


Huh? Why is blim the end of bitset?


It is not. But it is intended to _hold_ the end (see below)
}
struct foo {
struct fancy_array bar;
char bar_bitset[MAX_BARS / 8];
...

So bar_bitset just reserves space for the fancy_array's bitset. But to
initialize this I need to pass the end of bar_bitset so we can set blim:

fancy_array_init(&f->bar, endof(f->bar_bitset));


You completely lost me here... Either this makes no sense or I am stupid.


Neither. Think of it as a variant of the struct hack. Instead of
allocating the excess memory, you use automatic (or static)
struct variables. You can access everything by a pointer to struct
fancy_array, so fancy_array only has to know its "real" size or
its ends (stored in blim or passed explicitly to functions from
the outside.

Maybe the OP can clarify this further if I did not get all of it
(or are completely off the track).
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 15 '05 #9
On Wed, 29 Jun 2005 09:08:21 +0200, Michael Mair wrote:
For example instead of using strncpy I prefer the following

Perhaps it is best if I just provide the function in question:

int
str_copy(const unsigned char *src,
const unsigned char *slim,
unsigned char *dst,
unsigned char *dlim,
int n)
{
unsigned char *start = dst;

if (dst == NULL || dst >= dlim) {
return 0;
}
if (src == NULL || src >= slim) {
*dst = '\0';
return 0;
}
while (n-- && *src) {
*dst++ = *src++;
if (src == slim || dst == dlim) {
dst = start;
break;
}
}
*dst = '\0';

return dst - start;
}
I don't see how that makes things safer. On the contrary, you are
introducing redundancy (and a source for errors) by adding the additional
constraint of (dlim - dst == slim - src). And on top of all that, you still
pass n. I would stick with the canonical way.
Yep, but n can now be easily larger than slim-src, or slim-src and/or
n can be larger than dlim-dst and you can easily implement the whole
thing safely.


Right. The lim pointers are just "fence post"s. When you decode or
encode something you usually know where the end of your buffer is and
that never changes (the limit pointer). Regardless of what hula-hoops
your code goes through the lim pointers should never change. This makes
the src < slim check very consistent and less prone to error because
you're not recomputing the sentinel all the time.

Admittedly that function might not be ideal to illustrate my point because
it does add the additional constaint of 'n'. Perhaps my alternative to
strlen is better:

int
str_length(const unsigned char *src, const unsigned char *slim)
{
const unsigned char *start = src;

if (src == NULL || src >= slim) {
return 0;
}
while (*src) {
src++;
if (src == slim) {
return 0;
}
}

return src - start;
}
Neither. Think of it as a variant of the struct hack. Instead of
allocating the excess memory, you use automatic (or static)
struct variables. You can access everything by a pointer to struct
fancy_array, so fancy_array only has to know its "real" size or
its ends (stored in blim or passed explicitly to functions from
the outside.

Maybe the OP can clarify this further if I did not get all of it
(or are completely off the track).


That's exactly right. I didn't describe it very well but you get it.

Mike

Nov 15 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Comcast | last post by:
Greetings, I am writing a very simple script that pulls a resultset out of a database. These rows are then made into form variables where the user has the option to update multiple entries, hit...
7
by: techno | last post by:
Dear all, Our bitmap has some x00 values ( '\0' ) and i am storing it in char* array. the problem is that the '\0' is treated as eos character in c and it is truncating it so the characters...
9
by: Fred Zwarts | last post by:
What is the recommended way to loop over all enum values of a certain enum type? Consider the following definition: typdef enum {A=2, B, C=5, D} E; then for (E x = A; x <= D; ++x) { ... }
9
by: shaun | last post by:
Dear all, I realized an error in a previous post, I reproduce it here because I'm still not sure how to solve it: I want to make a templated function which points to one-past-the-end of a...
3
by: Matthew Warren | last post by:
I have the following piece of code, taken from a bigger module, that even as I was writing I _knew_ there were better ways of doing it, using a parser or somesuch at least, but learning how wasn't...
2
by: Quentin | last post by:
Any code on how to start write to a new file would be appreciated. In the example below: How would I start the write to a file on the word "Recipe" and then write every line beneath it until "End...
4
by: MikeJ | last post by:
make a While loop ofs = TextFileServer("somefile") string srow while (ofs=false) { srow=ofs.getRow(); Console.Writeline(srow); }
4
by: Rymfax | last post by:
Greetings, I have an app that uses HttpWebRequest to download a rather large file (100 MB). I have a while loop set up so that it reads 4096 bytes at a time from the ResponseStream() until it...
2
by: Question123 | last post by:
Hi i have one database table Table1.which contains almost 20000000 recordes. record to this table are inserted through storedprocedure. storedprocedure takes parameter as "value", Beginningdate,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.