Amiga.org
Operating System Specific Discussions => Amiga OS => Amiga OS -- Development => Topic started by: Jose on January 30, 2007, 05:52:21 PM
-
It seems that sizeof() works only with variable names themselves (or their types) but doesn't accept using a pointer to get the size of the variable pointed to. Any substitute for this ?
Goal is to use the sizeof result in a macro that accepts, among other things, a pointer to the variable. So I want it to be as short as possible and was trying to find a way to give the variable's size and ptr in one go (just give the pointer and the macro would get the size).
:pint:
P.S.
This is to improve the syntax of that general saver library I'm doing....
-
The sizeof() of any pointer is 4 (except your coding for an 64Bit OS that is).
For me it sounds like you mix up run-time features (like assigning a pointer) with compile-time features (like sizeof()).
-
i'm a bit lost cause it makes a lot of time that i don't type any code line in C, but... if u make a sizeof a pointer type you'll get the size of the pointer, not the size of the content that this pointer points to... then... why don't you call sizeof() using the expected type that pointer points to?
the macro can result different kind of types? then probably you can make a compiler directive, or something similar depending of the macro result type?
i repeat... i'm a bit lost with C now :-D
-
@Kronos
No, I was expecting the compiler to assume (compile-time of course) that sizeof (*VarPtr) would be the same as sizeof (Var), simply because it's logic. This is assuming that Var is the variable VarPtr points to.
@neuroflip
"...why don't you call sizeof() using the expected type that pointer points to?"
Because the goal is to make a syntax for a macro as short as possible. If the compiler understood sizeof (*VarPtr) I could simply pass VarPtr to the macro and it would be able to use VarPtr and the size of Var from it. Since it doesn't I need to pass 2 arguments: VarPtr and sizeof (Var), or VarPtr and Var ( in wich case the macro would get sizeof (Var) internally).
-
It seems that sizeof() works only with variable names themselves (or their types) but doesn't accept using a pointer to get the size of the variable pointed to.
Works fine here.
If you have pointer to pointer, and want to get size of it, then you obviously need to specify the type explicitly (or cast it, or if you know the type just use sizeof(type)).
No, I was expecting the compiler to assume (compile-time of course) that sizeof (*VarPtr) would be the same as sizeof (Var), simply because it's logic. This is assuming that Var is the variable VarPtr points to.
That is how it works.
-
Could you try passing the value at the address of the pointer? i.e. rather than:
char * mypointer;
sizeof(mypointer);
Which would only give you size of a pointer.
do:
sizeof(* mypointer);
Should give the size of the type to which the pointer is pointing at, as it were.
-
I don't get what the problem is.
Dereference the pointer and do sizeof as you seem to be doing.
#define GETMETHESIZEOFTHINGATENDOFPOINTER(ptr) sizeof(*ptr)
void dummyFunc( ThisThingIsbiggerThan4bytes *ptr )
{
assert( NULL!=ptr );
cout << sizeof(*ptr); // prints sizeof ThisThingIsbiggerThan4bytes
cout << sizeof(ptr); // prints 4
cout << GETMETHESIZEOFTHINGATENDOFPOINTER(ptr); // prints sizeof ThisThingIsbiggerThan4bytes
}
The macro will just be replaced by the call to sizeof. But it's not type safe, and it's a very bad idea.
Why exactly are you trying to do this? What are you hoping to achieve? Finally, NEVER do anything like what i just showed you above :-D
I just threw together a small test app and it did exactly what I'd expect.
Andy
-
You might also want to take a look at something like this page.
Writing CPP macros (http://www.ebyte.it/library/codesnippets/WritingCppMacros.html)
Then throw away all of your macros :-D
Writing good code generally means there won't be a lot of macros in it, not if I can avoid it anyway. I'll inline functions (type safety checking) if I want a function and I'll "const int blah = 1;" in a namespace if I want constants.
Just my opinion of course.
Andy
-
Piru wrote:
No, I was expecting the compiler to assume (compile-time of course) that sizeof (*VarPtr) would be the same as sizeof (Var), simply because it's logic. This is assuming that Var is the variable VarPtr points to.
That is how it works.
sizeof() and offsetof() are usually implemented as macros on most implementations. That's the first indication that you can't absolutely rely on their behaviour in all cases.
Given that, I should point out that it can only work with concrete types that have already been "seen" by the compiler.
Consider this:
struct Something; /* forward reference */
sizeof(struct Something); /* we haven't seen it defined yet. How big is it? */
Furthermore, in C++ if you tried this:
class Base { ... };
class Derived : public Base { ... };
size_t getSize(const Base* b)
{
/* return the size of the object pointed to */
if (b) {
return sizeof(*b);
}
throw std::invalid_argument();
}
the function would always return sizeof(Base) even when the object pointed to was of type "Derived". There is no way the compiler can know at compile time what the actual object pointed to really is at runtime.
-
@Karlos
sizeof() and offsetof() are usually implemented as macros on most implementations.
Wrong. 'sizeof' cannot be implemented with a macro. It's always builtin keyword in the compiler.
'offsetof' is a standard macro, in stddef.h (even standardized in POSIX these days).
That's the first indication that you can't absolutely rely on their behaviour in all cases.
Actually you can rely on sizeof.
Given that, I should point out that it can only work with concrete types that have already been "seen" by the compiler.
Well isn't that quite obvious, huh?
C++
C++ isn't C. ;-)
-
I'm sure I'd once seen a definition of sizeof() somewhere :-)
Anyway, my point was that these constructs are not functions, there are no language guarentees for their behaviour if you treat them as if they were.
Actually you can rely on sizeof
How big is this?
struct AudioObject {
unsigned long numSampleFrames;
unsigned short sampleRate;
...
signed short waveData[1]; /* memory beyond this point is wave data */
};
I've seen such "open ended" structures in a lot of places. Of course sizeof() cannot know you might have malloc()'ed this structure with an additional 200K worth of sample space.
And I've still seen people wonder why sizeof() didn't work for it, along with more comical examples, eg using sizeof() instead of strlen() for non-constant strings (and worse) :lol:
So, you can only rely on sizeof() when you fully understand its necessary limitations.
Well isn't that quite obvious, huh?
To you, yes. Never underestimate the ability of people to overlook the obvious however. I have seen code where I work that would give you hives.
C++ isn't C.
No, it's better in every significant way :-P
Seriously, that one word retort doesn't detract from the observation that sizeof() has no knowledge of the element actually pointed to. It simply trusts the developer to know what he has passed to it when dereferencing.
Consider the typical pointer casting frenzy that is the stock of amiga C coding. Often the pointer you deal with is not the genuine type of object pointed to, such as Task* v Process* . Getting the size of a Process by dereferencing a pointer that happens to be a Task* will return the size of the struct Task, not the struct Process.
You might sit there and complain this is totally obvious and I'd agree, but again people do make such silly assumptions, especually when they see such casts being used so loosely. You and I know that Process embeds a Task as its first member and therefore are not the same (or even comparable) structures, but it might not be as obvious to someone fairly new to the language.
In C++ the problem is compounded with abstract types as I describe and I have seen people who really ought to know a lot better attempt exactly what I demonstrated in that example.
So, obvious or not, such mistakes are made.
-
As for sizeof() being unimplementable as a macro:
For physical instances of any given elemental type or structure (or instances accessed via dereferencing of a pointer to that type):
#define SIZEOF(t) ((long)((&(t))+1) - (long)(&(t)))
behaves about as well as sizeof(). Of course, it doesnt handle arrays properly or handle SIZEOF(TypeName) at all ;-)
-
#define SIZEOF(t) ((long)((&(t))+1) - (long)(&(t)))
behaves about as well as sizeof(). Of course, it doesnt handle arrays properly or handle SIZEOF(TypeName) at all ;-)
/me vomits
-
How big is this?
struct AudioObject {
unsigned long numSampleFrames;
unsigned short sampleRate;
...
signed short waveData[1]; /* memory beyond this point is wave data */
};
This is of course not (old) standard ANSI-C, and therefore it is no surprise that sizeof() fails to generate the proper value. This hack did work unofficially on nearly every compiler out there, which is why it was merged into the C9X standard. And in that standard, the sizeof() result has been changed to return the size of the struct without the incomplete array. It also specifies what happens in the case of padding (it's added).
Granted, it may not be IOTTMCO (Intuitively Obvious To The Most Casual Observer), and I will concede to my foot now having more holes than actual foot for misunderstanding sizeof()---but that's what you get from not understanding the keyword itself, isn't it...?
(Later edit: Your example uses a complete array, namely with 1 element. Therefore sizeof() will return the size of the struct as defined. If you leave out the 1, then sizeof() returns the size of the struct at the moment the array would appear in memory.)
I've seen such "open ended" structures in a lot of places. Of course sizeof() cannot know you might have malloc()'ed this structure with an additional 200K worth of sample space.
See above.
So, you can only rely on sizeof() when you fully understand its necessary limitations.
See above, too.
To you, yes. Never underestimate the ability of people to overlook the obvious however. I have seen code where I work that would give you hives.
That's what makes these languages such a nightmare and so strangely addictive at the same time: by the time you feet are just shreds, and your head is now a mass of sores from pulling out the hairs and their follicles, and you do find the answer, you will NEVER forget the lesson you learned.
And then appreciate languages which hide such details all the more.
-
@Karlos
Nor does it handle sizeof variable.
-
Piru wrote:
@Karlos
Nor does it handle sizeof variable.
Of course not. The point was that it is possible to use a macro to evaluate the size of a structure/primitive type, nothing more. Just to demonstrate that (some of) the behaviour of sizeof() could be implemented as a macro, even if the actual sizeof() itself is not.
@Koafter
Agreed, it's disgusting and I'd want to shoot anybody I saw using anything quite like that*.
(*I have used some ugly macros in my time but only to abstract something that simply couldn't be represented more cleanly in the language itself. The above example naturally does not fall into this category).
C is a fantastic language but when you do end up having to depend on macros for things that you could readily do in C++ with inline functions and templates you really do see the point in moving up the language food chain ;-) Other than conditional compilation, I rarely use macros in C++ for anything.
I make no secret of the fact I regard C++ as utterly superior to C. Not because of the OO features per se (which I do like of course) but simply because it provides much cleaner ways of doing things that in C you would otherwise end up using the preprocessor or other contrivances for. It also provides greater error checking and general robustness and last but not least, still allows you to do things low level when you need to.
-
I make no secret of the fact I regard C++ as utterly superior to C. Not because of the OO features per se (which I do like of course) but simply because it provides much cleaner ways of doing things that in C you would otherwise end up using the preprocessor or other contrivances for. It also provides greater error checking and general robustness and last but not least, still allows you to do things low level when you need to.
Amen brother! A lot of what I do microcontroller wise is straight C, and my other projects are mostly procedural, but I really appreciate stuff from C++ land that makes my life easier, even though i don't usually do OOP unless i'm doing an MFC app, c++ stuff thats not OOP makes life easier for the C programmer.
-
Generally, I use the procedural paradigm where it makes sense and OO paradigm where it makes sense :-) I prefer the latter and for most systems I work on it's the right choice, but there are naturally lots of smaller things you have to do where it is just overkill.
C++ is so good simply because it gives you the choice. Unlike OO "pure" languages (read Java; forever lambasting C++ for its awkard syntax and then adopting the template syntax for its generics :lol:)) which force you to apply it to the simplest cases and of course procedural languages which make it awkward to do at all :-)