If I\'m not mistaken, structs mean objects, and struct pointers mean pointer to objects right? In an article, It says that classes are structs which means that they are obje
Classes are structs, but Class
is a pointer type, being defined as
typedef struct objc_class *Class;
and this answers the first part of the question.
Now, if you take a look at <objc/objc.h>
you'll find
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;
const char *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
and in <obj/runtime.h>
you'll find
/// Represents an instance of a class.
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
meaning that in Objective-C 2.0 objc_object
and objc_class
are identical structs, both having an isa
field.
That's why you can pass a Class
where an id
is required: classes are objects after all.
You would normally expect a warning about the incompatible pointers type, but apparently the Obj-C compiler uses an ad-hoc treatment this specific case.
I have no references to support this, though.
I finally found a reference in the clang source code:
In ASTContext.cpp
, this is the Class
declaration
TypedefDecl *ASTContext::getObjCClassDecl() const {
if (!ObjCClassDecl) {
QualType T = getObjCObjectType(ObjCBuiltinClassTy, 0, 0);
T = getObjCObjectPointerType(T);
TypeSourceInfo *ClassInfo = getTrivialTypeSourceInfo(T);
ObjCClassDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
getTranslationUnitDecl(),
SourceLocation(), SourceLocation(),
&Idents.get("Class"), ClassInfo);
}
return ObjCClassDecl;
}
and this is the id
declaration
TypedefDecl *ASTContext::getObjCIdDecl() const {
if (!ObjCIdDecl) {
QualType T = getObjCObjectType(ObjCBuiltinIdTy, 0, 0);
T = getObjCObjectPointerType(T);
TypeSourceInfo *IdInfo = getTrivialTypeSourceInfo(T);
ObjCIdDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
getTranslationUnitDecl(),
SourceLocation(), SourceLocation(),
&Idents.get("id"), IdInfo);
}
return ObjCIdDecl;
}
In both cases the type is set to the result of getObjCObjectPointerType
. This causes the compiler to consider both Class
and id
as pointers to Objective-C objects.
If I'm not mistaken, structs mean objects, and struct pointers mean pointer to objects right?
Mostly, yes. But since in Objective-C, objects (including classes) can only be manipulated using pointers, the shorthand "object" is used instead of a more correct "pointer to an object", even in pieces of official documentation.
So, if it says that classes are structs, then how will they fit in the argument of
objc_msgSend()
?
They pass a pointer to a struct which is an object. Class
is a typedef for struct objc_class *
, whereas id
is a typedef for struct objc_object *
. Both are (non-function) pointers, and both structures contain an isa
field, they can be used interchangeably as far as you know what you are doing.