Simulation of Sizeof operator

S

sabarish

Hi to one and all

one of the developer asked me "Can u implement one user defined funtion
similar to the sizeof operaor in C Programming Language".
is it possible in C ?
 
W

Walter Roberson

one of the developer asked me "Can u implement one user defined funtion
similar to the sizeof operaor in C Programming Language".
is it possible in C ?

We went over this at length just a few weeks ago.

The quick summary is: No, not portably. But you can do it for
machines in which the NULL pointer -happens- to be address 0.
 
A

Alexei A. Frounze

sabarish said:
one of the developer asked me "Can u implement one user defined funtion
similar to the sizeof operaor in C Programming Language".
is it possible in C ?

Most probably yes, but I'm not sure whether or not there are any nasal
demons, portability issues :).
Consider sizeof(type) being mimicked as ((size_t)((type*)0+1)).

Alex
 
A

Alexei A. Frounze

Alexei A. Frounze said:
Most probably yes, but I'm not sure whether or not there are any nasal
demons, portability issues :).
Consider sizeof(type) being mimicked as ((size_t)((type*)0+1)).

Alex

Right, as Walter just said, there can be problems if NULL (or 0) pointer
isn't address 0.

Alex
 
S

Skarmander

Alexei said:
Right, as Walter just said, there can be problems if NULL (or 0) pointer
isn't address 0.
Actually, it's more subtle; you can avoid the null pointer issue, but
you can't avoid the possibility of 0 (or 0 + sizeof type) not being a
valid address, even if not dereferenced.

Then again, that's why we *have* sizeof, and people should stop asking
this. :)

S.
 
K

Kenneth Brody

Is there some C class out there that keeps getting this inane question
over and over?

I suppose one _could_ look at it as "how well do you understand C?"
Right, as Walter just said, there can be problems if NULL (or 0) pointer
isn't address 0.

Not if you cast it to (char*) and subtract (char*)NULL from it, as
someone's posting of offsetof() did. (ie: think of sizeof in terms
of offsetof() the start of type_array[1].)

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
A

Alexei A. Frounze

Kenneth Brody said:
Is there some C class out there that keeps getting this inane question
over and over?

I suppose, yes. And I believe, there're *many*.
I suppose one _could_ look at it as "how well do you understand C?"
Certainly.
Right, as Walter just said, there can be problems if NULL (or 0) pointer
isn't address 0.

Not if you cast it to (char*) and subtract (char*)NULL from it, as
someone's posting of offsetof() did. (ie: think of sizeof in terms
of offsetof() the start of type_array[1].)

Maybe. Actually, I've though about something similar recently -- I'd simply
declare an array of 1 element of the given type and return difference
between address of 1st and 0th elements... But that would only work for
small types like base types numeric and pointers.

Alex
 
Z

Zara

We went over this at length just a few weeks ago.

The quick summary is: No, not portably. But you can do it for
machines in which the NULL pointer -happens- to be address 0.

IMHO, the answer is yes, and in a portable manner:

#define SIZEOF(return,type)\
{\
type set[2];\
return=(char*)(set+1)-(char *)set;\
}

But it adds szie to code and decreases speed, so it is infefficient
 
K

Keith Thompson

Zara said:
We went over this at length just a few weeks ago.

The quick summary is: No, not portably. But you can do it for
machines in which the NULL pointer -happens- to be address 0.

IMHO, the answer is yes, and in a portable manner:

#define SIZEOF(return,type)\
{\
type set[2];\
return=(char*)(set+1)-(char *)set;\
}

But it adds szie to code and decreases speed, so it is infefficient

That macro expands to a compound statement, which can't be used as an
expression. (The use of "return" as a macro argument name is, um,
interesting, but I don't think it will cause any problems.)
 
P

pete

Zara said:
We went over this at length just a few weeks ago.

The quick summary is: No, not portably. But you can do it for
machines in which the NULL pointer -happens- to be address 0.

IMHO, the answer is yes, and in a portable manner:

#define SIZEOF(return,type)\
{\
type set[2];\
return=(char*)(set+1)-(char *)set;\
}

If "type" is a user defined type, like a very large array,
then it's possible that:
1 ((char*)(set+1)-(char *)set) might excede
the limits of ptrdiff_t and cause undefined behavior, or
2 there's the possibility that type set[2] is too big too compile.
 
Z

zikaizhang

since NULL may not be 0, why not try this?

#define Sizeof(type) ((char *)((type*)NULL + 1) - NULL)
#define SizeofObject(obj) ((char *)(&obj + 1) - (char*)&obj)

btw. what will NULL be if it is not equal to 0 ?

the problem says "user defined *funtion* similar to the sizeof
operaor". what if it must NOT be a macro ?
 
F

Flash Gordon

since NULL may not be 0, why not try this?

#define Sizeof(type) ((char *)((type*)NULL + 1) - NULL)

Pointer arithmetic is only defined for pointers that point to an object
null pointers do not point to objects. So this is invokes undefined and
anything could happen.
#define SizeofObject(obj) ((char *)(&obj + 1) - (char*)&obj)

This is fine. You are allowed to calculate the address of one passed an
object.
btw. what will NULL be if it is not equal to 0 ?

the problem says "user defined *funtion* similar to the sizeof
operaor". what if it must NOT be a macro ?

Then you are stuck since there is no method to pass a type in to an object.

I've yet to see what I would consider a good reason for wanting to do
this anyway since C has a sizeof operator.
 
K

kaikai

Flash said:
Pointer arithmetic is only defined for pointers that point to an object
null pointers do not point to objects. So this is invokes undefined and
anything could happen.

I think pointer arithmetic is performed at compile time, so I guess if
the compiler knows the type it may do that. Do you mean some compilers
will check the object and refuse to do pointer arithmetic when the
object is invalid?
 
F

Flash Gordon

kaikai said:
I think pointer arithmetic is performed at compile time, so I guess if
the compiler knows the type it may do that.

The compiler *might* do it at compilation time, but it is under no
obligation to do that.
> Do you mean some compilers
will check the object and refuse to do pointer arithmetic when the
object is invalid?

A processor might trap at run time when an invalid address is loaded in
to a pointer variable.

At compile time, if it does the pointer arithmetic at compile time, and
NULL represented as something other than all bits zero the compiler
might suffer from an integer overflow when doing the arithmetic causing
to to produce an incorrect result. Undefined behaviour does not require
a diagnostic, so the compiler could silently produce incorrect code in
this instance and still be conforming.

The point is that it is undefined behaviour so *anything* can happen,
including what you want. However, C has the sizeof operator and the
offsetof macro provided as part of the standard, so you don't have any
need to do such tricks.

Well, on embedded systems you do sometimes have to strange things when,
for example, accessing memory mapped devices, but by then you are well
in to the realms of system specific code anyway so as long as your
compiler guarantees it you are OK.
 
P

pete

NULL may be zero.

Undefined behavior, yes.
The compiler *might* do it at compilation time, but it is under no
obligation to do that.

It's "constant expressions" which the compiler has the option
to calculate during compile time.

There's nothing special about pointer arithmetic,
a far as compile time vs. run time issues are concerned.
A processor might trap at run time when an
invalid address is loaded in to a pointer variable.

I'm not following.
There's neither objects nor variables in that Sizeof() macro.

(type*)NULL is a null pointer.

(null pointer + 1) is undefined: it's just that simple.

N869
7.17 Common definitions <stddef.h>
[#3] The macros are
NULL
which expands to an implementation-defined null pointer
constant

6.3.2.3 Pointers
[#3] If a null pointer constant is
converted to a pointer type, the resulting pointer, called a
null pointer, is guaranteed to compare unequal to a pointer
to any object or function.

6.5.6 Additive operators
[#8] If both the
pointer operand and the result point to elements of the same
array object, or one past the last element of the array
object, the evaluation shall not produce an overflow;
otherwise, the behavior is undefined.
 
F

Flash Gordon

pete said:
NULL may be zero.
Indeed.


Undefined behavior, yes.
Yes.


It's "constant expressions" which the compiler has the option
to calculate during compile time.

There's nothing special about pointer arithmetic,
a far as compile time vs. run time issues are concerned.

Yes. What I said applies to *all* constant expressions. The compiler can
choose to compute any or all of them at run time.
I'm not following.
There's neither objects nor variables in that Sizeof() macro.

(type*)NULL is a null pointer.
Yes.

(null pointer + 1) is undefined: it's just that simple.

<snip stuff I agree with>

Yes. I'm sure I have stated that in this thread somewhere.

I was trying to point out to kaikai one of the infinite number of ways
the code could actually fail because people are often more willing to
accept that something might not always work if you can show them
something that will cause it to fail.
 
P

pete

pete said:
NULL may be zero.


Undefined behavior, yes.


It's "constant expressions" which the compiler has the option
to calculate during compile time.

There's nothing special about pointer arithmetic,
a far as compile time vs. run time issues are concerned.


I'm not following.
There's neither objects nor variables in that Sizeof() macro.

(type*)NULL is a null pointer.

.... which is also a constant expresssion.

N869
6.6 Constant expressions
[#9] An address constant is a null pointer, a pointer to an
lvalue designating an object of static storage duration, or
to a function designator;
(null pointer + 1) is undefined: it's just that simple.

N869
7.17 Common definitions <stddef.h>
[#3] The macros are
NULL
which expands to an implementation-defined null pointer
constant

6.3.2.3 Pointers
[#3] If a null pointer constant is
converted to a pointer type, the resulting pointer, called a
null pointer, is guaranteed to compare unequal to a pointer
to any object or function.

6.5.6 Additive operators
[#8] If both the
pointer operand and the result point to elements of the same
array object, or one past the last element of the array
object, the evaluation shall not produce an overflow;
otherwise, the behavior is undefined.
 
K

kaikai

oh... I used to think compilers will convert pointer arithmetic to
numerical arithmetic by multiplying sizeof pointed type.
sth. like
Type *pA;
pA = pA + n;
will become
(char*)pA = (char*)pA + n * sizeof(Type);
at compile time.
A real processor does not know what a type is, it just add pA with a
constant value.
 
D

Dave Thompson

regarding (type*)NULL + 1, without quoting: as posted here thousands
of times over the past few weeks, if using the google broken beta, do
not just click Reply, click on Show Options and use that Reply to get
the previous article quoted, and then following normal good practice
edit it down to the point(s) you are responding to. And complain to
google that they made correct practice more difficult.
oh... I used to think compilers will convert pointer arithmetic to
numerical arithmetic by multiplying sizeof pointed type.
sth. like
Type *pA;
pA = pA + n;
will become
(char*)pA = (char*)pA + n * sizeof(Type);
at compile time.
A real processor does not know what a type is, it just add pA with a
constant value.

That syntax is a GCC extension, standardly you need
pA = (Type*)( (char*)pA + n * sizeof(Type) );

With that trivial fix, in practice on mainstream byte-addressed
machines they do. Similarly on _most_ implementations offsetof(a,b)
can be just (size_t) & ((a*)NULL) ->b . But the standard doesn't
require it, and implementations can differ, as Flash Gordon said.
- David.Thompson1 at worldnet.att.net
 

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,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top