size of a struct without "sizeof"

S

srikar2097

I have got a struct and I want to find the size of this struct without
using "sizeof()". Here's the code-

struct node
{
int data;
struct node *next;
};

int main()
{
struct node *tmp = NULL;
int sizeof_struct = (int) ++tmp;
printf("Size of struct without sizeof(): %d\n", sizeof_struct);
return 0;
}

Here are my doubts:-
1) Why does this method work? (is it because just while initializing a
string C compiler puts in a '\0' to indicate end of string, is
something like this is happening here?)

2) Are there any other methods? I tried a few more ways to get this,
I'll post them here.

METHOD 2-
-------------------
/*Home Grown Method 2.*/
struct node *trial=NULL;
int *i;
printf ("Size of Struct - Home made2: %d\n", (&i - &trial));

METHOD 3-
 
H

Harald van Dijk

srikar2097 said:

Since tmp is a null pointer, it isn't pointing at anything. Therefore,
dereferencing it is a meaningless act, and the behaviour if you try is
undefined.

Incrementing it is equally undefined, but this is not as obvious as
dereferencing.
 
S

srikar2097

Are you sure the METHOD 1 given by me does not work?

I ran the program and got the size as 8bytes.
Then I ran the program using the sizeof() and got the size as 8
bytes.

Is this a coincidence? This method works. If in doubt you could try it
yourself.
 
S

Stephen Sprunk

srikar2097 said:
Are you sure the METHOD 1 given by me does not work?

I ran the program and got the size as 8bytes.
Then I ran the program using the sizeof() and got the size as 8
bytes.

Is this a coincidence? This method works. If in doubt you could try it
yourself.

It might appear to work on your particular OS, with your particular
compiler, but it will definitely not work on others. This hack relies
on undefined behavior and is unportable, which most of the regulars here
would not classify as "working".

If you want to find the size of something, use sizeof. That's what it's
there for; if there were a portable way to do the same thing without it,
it probably wouldn't be there. Ditto for offsetof(), in case that
happens to be your professor's next homework assignment...

S
 
K

Keith Thompson

srikar2097 said:
I have got a struct and I want to find the size of this struct without
using "sizeof()".

Why on Earth would you want to do something silly like that?

I'm not trying to be insulting, but the sizeof operator exists for a
very good reason: it gives you the size of something. There are other
valid ways to determine the size of something, but none that are as
convenient. *Why* exactly do you want to find the size of a struct
without using sizeof?
Here's the code-

struct node
{
int data;
struct node *next;
};

int main()
{
struct node *tmp = NULL;
int sizeof_struct = (int) ++tmp;
printf("Size of struct without sizeof(): %d\n", sizeof_struct);
return 0;
}

Here are my doubts:-
1) Why does this method work? (is it because just while initializing a
string C compiler puts in a '\0' to indicate end of string, is
something like this is happening here?)

Ok, I can understand why that could would *appear* to "work" on some
systems.

tmp is initially a null pointer. A null pointer, on most
implementations, is represented as all-bits-zero. Incrementing a
pointer to "struct node" advances the address it points to by
sizeof(struct node) bytes -- *if* it points to an actual object of
type "struct node". So the compiler is likely, on many systems, to
implement ++tmp by treating tmp as if it were an integer object and
adding the value sizeof(struct node) to it. (Incidentally, one of the
least serious problems with the code is its gratuitous use of the "++"
operator; "tmp + 1" would work as well (or as poorly) here.) tmp is
then converted from a pointer to type int; the result of such a
conversion is implementation-defined, but it's common for it simply to
reinterpret the representation. The final result is *likely* to be
that the int object sizeof_struct will contain the value of
sizeof(struct node).

Note that there are about half a dozen qualifications in my
description. The code depends very heavily on features that are
typical of many implementations, but that are absolutely not
guaranteed by the standard. The code, on some systems, happens to
compute a correct value for sizeof(struct node). It does *not* "work"
in any reasonable sense. Compile the same code on another system, or
with another compiler, or with another version of the same compiler,
or with different optimization options, or when it's dark on a
Tuesday, and you could get different results, or no results at all, or
it could fail to compile, or reformat your hard drive.
2) Are there any other methods? I tried a few more ways to get this,
I'll post them here.

METHOD 2-
-------------------
/*Home Grown Method 2.*/
struct node *trial=NULL;
int *i;
printf ("Size of Struct - Home made2: %d\n", (&i - &trial));

Did you try this? I can't think of any reason, even a grossly
system-specific one, why this would work. It shouldn't even compile.
(I could write something similar to this that might "work" on some
systems, but I won't.)
METHOD 3-
------------------
/*Home Grown Method 3.*/
struct node trial2[2];
printf ("Size of Struct - Home made3: %d\n", &trial2[1] - &trial2
[0]);

Subtracting two pointer values yields a result of type ptrdiff_t. In
this case, the result of &trial2[1] - &trial2[0] is guaranteed to be
exactly 1 (the difference is computed in terms of the size of the type
the pointers point to, not in bytes). Using "%d" to print a ptrdiff_t
value *might* work, but it can fail badly. Again, did you try this?

I want to drive a screw, but I don't want to use a screwdriver; can I
use a hammer? I want to steer my car, but I don't want to use the
steering wheel; can I just slide along the railing at the side of the
road?

The best answer to "How do I compute the size of something without
using sizeof?" is "Use sizeof anyway." Or at least provide a clear
reason why you don't want to use sizeof.
 
R

Richard Tobin

Keith Thompson said:
The best answer to "How do I compute the size of something without
using sizeof?" is "Use sizeof anyway." Or at least provide a clear
reason why you don't want to use sizeof.

It must be obvious by now that the reason this question keeps coming
up is that one or more C courses ask it. And the course authors no
doubt know perfectly well that there is no reason to avoid sizeof() in
real code, but think it's a good way to help students understand how C
variables are laid out in memory. This seems plausible (in an
affirming-the-consequent sort of way) because anyone who *does*
understand how C variables are laid out will be able to see how
sizeof() is related to the addresses of variables.

-- Richard
 
S

srikar2097

Sorry guys, I think I was not clear enough. It's not that I don't want
to use sizeof(). I was browsing for some resources on C and found this
problem on some website with the solution (as given in METHOD I). I
got curious about its workings and posted it here for discussions.

The other 2 methods are my doings and I know they are obviously wrong
(for this purpose). I just wanted to put across my attempts in this
regard.

So it's not that I don't want to use sizeof() or I don't trust sizeof
(). It's just as Richard Tobin mentioned it, to know the inner
workings of C compiler.

Now guys If the methods I have posted are wrong, it there a way to
solve find the size of a structure (or any other variable) without
using sizeof()?? Which works as reliably across all platforms as
"sizeof()" would have...

I am currently running my programs on a BSD Terminal with a gcc
compiler.
 
R

Richard Tobin

srikar2097 said:
Now guys If the methods I have posted are wrong, it there a way to
solve find the size of a structure (or any other variable) without
using sizeof()?? Which works as reliably across all platforms as
"sizeof()" would have...

No. For a start, sizeof() takes either a type name or an object, and
you won't be able to replicate that.

As you've seen, the obvious way to get an approximation to sizeof() is
to compare the addresses of two consecutive elements of an array. The
many variations of this illustrate some details of C, such as the fact
that you can address a fictitious element at the end of array, and
that you can typically do things with a null pointer that aren't
technically legal.

-- Richard
 
E

Eric Sosman

srikar2097 said:
I have got a struct and I want to find the size of this struct without
using "sizeof()".

That's nice. I have got a steaming bowl of delicious
clam chowder and I want to eat it without using my mouth.
Here's the code-

struct node
{
int data;
struct node *next;
};

int main()
{
struct node *tmp = NULL;
int sizeof_struct = (int) ++tmp;

Undefined behavior. Adding a pointer and an integer is
valid only if the result would point within or just after the
array containing the pointed-to object (a stand-alone object
is considered an array of one element for this purpose). Since
NULL does not point to any object at all, the non-object that
it doesn't point to is not in any array and the addition is
not defined.

Here's a possible rescue:

struct node dummy;
int sizeof_struct = (char*)(&dummy + 1) - (char*)&dummy;

.... but even this will fail if the struct's size is greater
than INT_MAX, which could be as low as 32767. It would be
better to use a `size_t' variable -- and, of course, it would
be better to use `sizeof'.
printf("Size of struct without sizeof(): %d\n", sizeof_struct);

Undefined behavior. printf() is a function with a variable-
length argument list, and such functions *must* be called with
an appropriate prototyped declaration in scope. You ought to
have #include'd said:
return 0;
}

Here are my doubts:-
1) Why does this method work?

By happenstance, by chance, by pure dumb luck. If you
wear a blindfold while driving a car, it is possible that
your journey will be uneventful.
(is it because just while initializing a
string C compiler puts in a '\0' to indicate end of string, is
something like this is happening here?)

This seems completely confused, and I'm at a loss to
imagine why you think strings have anything to do with it.
The only string in your code is the printf() format.
2) Are there any other methods?

sizeof.
I tried a few more ways to get this,
I'll post them here.

METHOD 2-
-------------------
/*Home Grown Method 2.*/
struct node *trial=NULL;
int *i;
printf ("Size of Struct - Home made2: %d\n", (&i - &trial));

Undefined behavior. Since the behavior is undefined there
is no certainty of any particular result, but among the more
likely outcomes are the number of bytes in a *pointer* to a
`struct node', or their negative, divided by two or by four.
METHOD 3-
------------------
/*Home Grown Method 3.*/
struct node trial2[2];
printf ("Size of Struct - Home made3: %d\n", &trial2[1] - &trial2
[0]);

Almost right, but the answer (if you get one) is likely
to be 1, no matter how big a `struct node' is.

Sorry, gotta go now: I'm going to lie down in a bathtub
full of clam chowder and try to absorb it through my skin.
 
T

Tomás Ó hÉilidhe

I have got a struct and I want to find the size of this struct without
using "sizeof()".


struct MyStruct obj;

printf( "Size = %u bytes\n", (unsigned)(&obj+1 - &obj) );
 
R

Richard Bos

srikar2097 said:
I have got a struct and I want to find the size of this struct without
using "sizeof()".

No, you don't. _Your teacher has told you_ to do so.

Stop lying to the people whose help you want. You third-rate first-year
students will never learn anything if you don't stop lying.

Richard
 
P

Phil Carmody

Richard Heathfield said:
Eric Sosman said:


Not quite true. You're guaranteed a diagnostic message.

On top of the constraint violation (incompatible types), it's
UB according to n1256:

-- Pointers that do not point into, or just beyond, the same array object are subtracted (6.5.6).

Phil
 
K

Keith Thompson

Richard Heathfield said:
srikar2097 said:

So it's not that I don't want to use sizeof()

Just sizeof. It's a keyword, not a function.

or I don't trust
sizeof (). It's just as Richard Tobin mentioned it, to know the
inner workings of C compiler.

Now guys If the methods I have posted are wrong,

Um, there's no "if" about it. They're wrong.
it there a way to
solve find the size of a structure (or any other variable) without
using sizeof()?? Which works as reliably across all platforms as
"sizeof()" would have...

One of your techniques, whilst still wrong, was actually pretty
close, but missed an important step:

struct whatever array[2];
unsigned char *first = (unsigned char *)&array[0];
unsigned char *second = (unsigned char *)&array[1];

printf("%d\n", (int)(second - first));

Converting the ptrdiff_t result of the subtraction to int is
unnecessary. It's possible (if unlikely) that sizeof(struct whatever)
could exceed INT_MAX.

And there's no need for an explicit array:

struct whatever obj;
const size_t sizeof_struct_whatever = (char*)(&obj+1) - (char*)&obj;
assert(sizeof_struct_whatever == sizeof(struct whatever));

&obj is the address of obj, of type struct whatever*. Adding one to
this value yields a valid (but non-deferenceable) address just past
the end of obj.

You could write a macro, similar to offsetof, that takes advantage of
certain assumptions about a system's addressing scheme that could take
a type name and yield the size of that type. If the sizeof operator
didn't exist, it's possible that the language would have defined such
a macro.

(Richard knows all this; the explanation is for the original poster.)
 
K

Keith Thompson

No, you don't. _Your teacher has told you_ to do so.

Stop lying to the people whose help you want. You third-rate first-year
students will never learn anything if you don't stop lying.

Here's what the OP wrote in a followup:

Sorry guys, I think I was not clear enough. It's not that I don't
want to use sizeof(). I was browsing for some resources on C and
found this problem on some website with the solution (as given in
METHOD I). I got curious about its workings and posted it here for
discussions.

It's possible that he's lying, I suppose, but I see no reason to
assume he's not being honest.
 
K

Keith Thompson

Richard Heathfield said:
Keith Thompson said at the end of his article:
(Richard knows all this; the explanation is for the original
poster.)

Well, I appreciate the vote of confidence, but I thought I'd better
check that I *do* know all this... and it seems that I don't know
some of it.

Keith had previously written:
One of your techniques, whilst still wrong, was actually pretty
close, but missed an important step:

struct whatever array[2];
unsigned char *first = (unsigned char *)&array[0];
unsigned char *second = (unsigned char *)&array[1];

printf("%d\n", (int)(second - first));

Converting the ptrdiff_t result of the subtraction to int is
unnecessary.

This is one bit that I don't know. Now, on reflection I should have
made it long int rather than int, but I still think the cast is
required.
It's possible (if unlikely) that sizeof(struct
whatever) could exceed INT_MAX.

The cast will neither exacerbate nor mitigate that problem.

If we can assume for the moment that I really wrote this:

printf("%ld\n", (long int)(second - first));

would you still say that the cast is unnecessary? If so, why?

Sorry, I was unclear. The cast is necessary if you want to print the
value (note that C99's <inttypes.h> doesn't provide format macros for
ptrdiff_t). Your "I really wrote this" code is the best way to print
the value in C90; in C99 you'd want to use intmax_t (with a cast, of
course). But if all you're doing is computing the value, you can just
store it in an object of type size_t or ptrdiff_t.
 
R

Richard Tobin

Richard Heathfield said:
If we can assume for the moment that I really wrote this:

printf("%ld\n", (long int)(second - first));

would you still say that the cast is unnecessary? If so, why?

If you used C99, you could avoid the cast:

printf("%td\n", second - first);

-- Richard
 
S

Stephen Sprunk

srikar2097 said:
Sorry guys, I think I was not clear enough. It's not that I don't want
to use sizeof(). I was browsing for some resources on C and found this
problem on some website with the solution (as given in METHOD I). I
got curious about its workings and posted it here for discussions.

The other 2 methods are my doings and I know they are obviously wrong
(for this purpose). I just wanted to put across my attempts in this
regard.

So it's not that I don't want to use sizeof() or I don't trust sizeof
(). It's just as Richard Tobin mentioned it, to know the inner
workings of C compiler.

That makes sense. Just keep in mind that any answers about the "inner
workings" of your C compiler may only apply to the compiler you test
them on. Other OSes, other versions, etc. may give different answers.
The C Standard deliberately provides a lot of leeway in how
implementations work, in order to accommodate all kinds of systems that,
beneath the hood, look absolutely nothing like each other.
Now guys If the methods I have posted are wrong, it there a way to
solve find the size of a structure (or any other variable) without
using sizeof()?? Which works as reliably across all platforms as
"sizeof()" would have...

The trick with a null pointer isn't necessarily "wrong"; it's just not
portable. There _are_ a great many systems that it will probably work
on, and you may never encounter any where it doesn't. There's nothing
inherently "wrong" with writing unportable code, as long as you know
that's what you're doing.

However, the trick of using an array _is_ portable and about the same
amount of work, so why _not_ use that method? And, of course, using
sizeof() itself is almost always the best solution.

S
 
B

Ben Pfaff

It doesn't need to: there's a built-in "t" modifier.

The "t" modifier is less useful in a program that needs to be
portable than a format macro would be: I can easily supply a
suitable <inttypes.h> for a new system (and it is possible to
write a version that works correctly on most systems, at least),
but it is much more work to supply a suitable implementation of
printf() and related functions.
 

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,776
Messages
2,569,603
Members
45,190
Latest member
ClayE7480

Latest Threads

Top