At the CocoaHeads Öresund meeting yesterday, peylow had constructed a great ObjC quiz. The competition was intense and three people were left with the same score when the final question was to be evaluated: How many reserved keywords does Objective-C add to C?
Some spirited debate followed. All agreed that #interface, #implementation etc are all pre-processor directives rather than keywords, but how about something like in? It might be a keyword, but it's not a reserved keyword. For example, the following will compile without errors or warnings:
NSArray* in;
for (in in in)
NSLog(#"bwahahaa");
We concluded that ObjC adds no reserved keywords to C, and someone won a seemingly well-earned book.
But today I tried some more systematic abuse on the compiler by trying things like this:
int self = 45;
self++;
int y = self;
That compiles fine, and the same code works replacing self for BOOL, bycopy, inout, oneway, byref, SEL, and IMP.
Using id as the variable name, the first and last lines compile, but not the second one. The same goes for Protocol, and Class.
Using super, the first line compiles, but not the second and third.
With YES, NO, and NULL, all three lines fail to compile, probably because they are just defined as true, false, and nil.
It looks to me like a lot of this is gcc getting confused and I'm not so sure it reflects what is and isn't a reserved keyword in Objective-C. Why, for example, is it ok to use self as the name of an int, but not super?
The fact that the first assignment always works (except for with YES, NO, and NULL) would seem to support the idea that none of the candidates are technically reserved keywords that are not found in C. Or?
Could someone please give us an authoritative explication of this thorny issue?
Several people's honor is at stake.
EDIT: As Nikolai Ruhe pointed out, we need a clear definition of "keyword" to proceed. Niko cited a Wikipedia article saying that a keyword is "a word or identifier that has a particular meaning".
I think it is reasonable to use this definition from the same article:
In many languages, such as C and
similar environments like C++, a
keyword is a reserved word which
identifies a syntactic form. Words
used in control flow constructs, such
as if, then, and else are keywords. In
these languages, keywords cannot also
be used as the names of variables or
functions.
Furthermore, as the article states:
Typically, when a programmer attempts
to use a keyword for a variable or
function name, a compilation error
will be triggered.
In this sense, then, are there any reserved keywords that are predefined in the language’s formal specifications and cannot be used as a user-defined name?
All agreed that #interface, #implementation etc are all pre-processor directives rather than keywords
Then all were mistaken. #import and #pragma are preprocessor directives.
#interface, #implementation, #protocol and so forth are keywords of Objective-C, and they are compiler directives. They haven't been preprocessor directives since NeXT extended GCC to compile Objective-C without a Stepstone's original Objective-C pre-processor implementation.
Re: Nikolai Ruhe's suggest that self is a keyword
self is a parameter to an Objective-C method of type id (similar to how _cmd is also a param, of type SEL) and not a keyword. nil is a macro which expands to NULL. I'm a little disappointed that super doesn't expand to a macro, nor is it a parameter.
From the wikipedia entry:
Objective-C is a thin layer on top of C, and moreover is a strict superset of C. It is possible to compile any C program with an Objective-C compiler, and to freely include C code within an Objective-C class.
That would preclude Objective-C from adding any restricted keywords to the language.
Wikipedia defines keywords as:
In computer programming, a keyword is a word or identifier that has a particular meaning to the programming language.
I'd translate that to: a keyword in a language is a non-terminal in its grammar. (Btw, the grammar doesn't contain the word "keyword" just by itself, so no confusion there).
The terminals in the grammar would be:
void
char
short
int
long
float
double
signed
unsigned
id
const
volatile
in
out
inout
bycopy
byref
oneway
self
super
#interface
#end
#implementation
#end
#interface
#end
#implementation
#end
#protoco
#end
#class
Grammar in Appendix B of the original 1995 book defines super as "literal symbol" terminal and it's a special-case in message receiver syntax.
in literal symbol is part of protocol-qualifier in ObjC 1.0 and was reused in fast enumeration syntax in ObjC 2.0 (which has no formal grammar definition AFAIK).
id is defined as part of type-specifier alongside void, char, unsigned, typedefed types, etc. If you call void a keyword, then id is too.
A look at the Objective-C Programming Language gives you some clues about what is possible or not. As some "keywords" are defined in a header file, their substitution can lead to observed (and unexpected) behavior.
You could check out The Objective-C Programming Language.
As far as I can tell, that document doesn't classify anything as a "reserved word". The #implementation, #interface, etc. are called "compiler directives."
Related
During a talk at the #Scale 2014 conference (around 32:30), Facebook presented their implementation of a declarative UI approach. The slides for a more detailed version of the talk can be found here.
Basically they presented a function call like this (I made my own simplified example from the example in the talk):
[CPInsetComponent
newWithStyle:{
.margin = 15
}
];
My question is: Is this valid ObjC code? I tried to implement this myself
typedef struct {
uint margin;
} CPInsetComponentStyle;
#interface CPInsetComponent : NSObject
+ (SomeOtherStruct) newWithStyle:(CPInsetComponentStyle)style;
#end
but I still get an "expected expression" error on the newWithStyle:{ line. Could you give me a hint how the method declaration would look like?
No, that's not valid Objective-C code. A C99 compound literal of struct type looks like this:
(TheStructType) { .field1 = initializer1, .field2 = initializer2 }
where the field designators are optional.
I can imagine that the code they were presenting was actually Objective-C++. In C++11, the compiler can insert implicit calls to constructors taking an initializer list if certain conditions are met; hence, often you can pass just an initializer list to a function.
The compiler probably doesn't know if your literal struct declaration is of the correct type. For compound literals you need to provide the type in parenthesis followed by a brace-enclosed list of initializers.
[CPInsetComponent newWithStyle:(CPInsetComponentStyle){
.margin = 15
}];
Why the compiler gives an error in this case of method declaration -
-(void) someMethod (void);
But approves this -
-(void) someMethod;
(SomeClass.h)
I've read that it is better to declare (void) in parameters than not declaring, but probalby I miss some point.
You cannot do this for Objective-C.
In Objective-C, every parameter must be after : e.g.
- (void)someMethod:(int)i;
- (void)someMethod:(int)i withString:(NSString *)string;
- (void)someMethod:(int)i :(int)i2 :(int)i3; // you can do this but is bad style
and it does not make sense to make something like
- (void)someMethod:(void)what_goes_here;
so if you want a method without parameter:
- (void)someMethod;
However you can do it in C/C++
void someMethod(void);
And I didn't see any benefit of declare void parameters (explicitly declare things is not always good).
Expanding on #xlc's answer
The answer is a difference in syntax between Objective-C and "normal" C/C++.
Way back in the origins of Unix and C days, late 60's/early 70's, when declaring (not defining) a function, you didn't need to specify how many arguments it accepted, or what types they needed to be. Nor did you need to specify whether or not it returned a value.
Later, folks realized that this would be a good idea, both for better error detection at compile time and for greater efficiency of generated code. So implementers added the ability to specify argument types in the function declaration. This was standardized as part of ANSI C in the late 80's.
However, there was a need to retain backwards compatibility with existing code. So a function declaration of foo() couldn't be assumed to mean "function with no arguments". To solve this, the void keyword was introduced. That allowed you to say foo(void) to mean "function named foo which takes no arguments".
When Objective-C was invented in the 90's, they added a new syntax for defining methods. Because there was no legacy code to deal with, they simply said that a method has to declare all its arguments; if there are none, then the method takes no arguments.
Objective-C still uses the void keyword to indicate that a method returns no value, though.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
objective c difference between id and void *
why most of the objects we create in iphone are pointers
According to Stanford university course, 2010/2011
Lecture 3
The guy made something strange there (at least for me), which is that
NSString *digit = sender.titlelabel.text;
Why is digit a pointer?
The type of your digit is id, which is just basically just a C pointer to a certain struct. All references to objects in Objective-C have this primitive type, regardless of the Class of the object. So the answer to your question is, unfortunately, because that's the way Objective-C works.
So whether you're declaring an NSString*, or an UITableViewController*, or MyClass*, your variable has type id. This is the primary means by which the language implements polymorphism. So, for example, the following declarations are equivalent:
NSString *digit;
id digit;
And it's true of method prototypes as well. These are equivalent:
-(UITableViewCell *)tableView:(UITableView)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-(id)tableView:(id)tableView cellForRowAtIndexPath:(id)indexPath;
A variable of type id is not an object itself, it is a pointer to an object. It is the handle with which you manipulate an object. Objective-C does all of the class compatibility work at runtime.
Hope this helps. Any questions?
Updates
That's right: int, float, double, char, void, and the pointer combinations, are all C primitive types. You can and will still use these quite a bit, and they are just what they are in a C program. But Objective-C adds the id type as a way to bridge the gap between the primitive typing of C and the very high-level typing of objects by the Objective-C system. id itself is typedef'd as a pointer to a simple struct in objc.h. At the level of the compiler and the language itself, there really isn't too much meaning to the type. For example, you'll almost never declare an array of ids, certainly never perform any arithmetic with them.
In fact, it's not too far a stretch to say that Objective-C is just plain vanilla C with some added syntax (particularly, the square-bracket notation for method invocation), a few extra primitive types (id, IMP, SEL), and a big runtime library. It's this runtime library that handles all things Object-Oriented.
Anyway, to answer your question, when you're actually programming, you will most often (99% of the time) just use class names to declare your variables - NSString *, NSData *, UITableViewController *, and so on. And the compiler will know what you're talking about, and issue a warning if you write code that clearly tries to put an NSString* where an NSData* is expected. But the actual meaning of those types really exists only at runtime.
I've digressed a little, but I'm not sure where your understanding is failing you, so I thought I'd just explain things a bit. You might want to read Apple's The Objective-C Programming Language to get a feel for the language.
NSString is an Objective-C class and all object references in Objective-C are pointers. I would suggest reading through some of the documentation such as Learning Objective-C A Primer:
Notice the * in the first declaration. In Objective-C, object
references are pointers. If this doesn’t make complete sense to you,
don’t worry—you don’t have to be an expert with pointers to be able to
start programming with Objective-C. You just have to remember to put
the * in front of the variable names for strongly-typed object
declarations. The id type implies a pointer.
It's not a digit, it's the "text" from the label, which is (I'm guessing) a string of integers and such to express the time.
So, all NSString types are declared as pointers in Obj-c.
sender.titlelabel.text;
Returns a NSString *
Remember, it's the same as:
NSString *str = [sender.titlelabel getText];
Because text is too. Or more preceisly, because the getText message returns a pointer.
You can find an intersting about why it has to be a pointer:
NSString and Pointers
I Hope it will help you to understand it in a Objective-C way.
What's the difference between the variable declarations:
//version 1
MyClass* myVar = [[MyClass alloc] init];
//version 2
MyClass * myVar = [[MyClass alloc] init];
//version 3
MyClass *myVar = [[MyClass alloc] init];
what changes will occur with the object myVar for each version?
Purely stylistic, no difference. In C, developers tend to prefer the latter style, probably for the simple reason that it makes declaring multiple pointers clearer:
int *ptr1, *ptr2;
...
It's also the style of the original, popular authors when C came out like Kernighan and Ritchie's C Programming Language. Dennis Ritchie, by the way, created C.
However, a lot of modern C++ developers, including Stroustrup himself (creator of C++), tend to favor that first convention:
int* ptr = ...;
The rationale for that preference probably comes down to a couple of things:
In C++, we have templates which require us to specify types on their own. vector<int*> seems a bit more straightforward about emphasizing int* as a single type rather than vector<int *> or some other variant.
When adhering to C++ coding standards which are intended to promote safe designs, we don't find ourselves wanting to define multiple variables at once so often since we generally want to define them when they can be meaningfully initialized (avoiding potential errors by limiting scope and immediately initializing them). *
This is quite different from C where every variable is required to be declared at the top of the scope which causes many C developers to have the frequent habit of declaring multiple at a time.
There is no difference between any of the declarations MyClass* myVar, MyClass * myVar or MyClass *myVar: it is a programmer preference.
Many programmers prefer MyClass *myVar, as it prevents making the following simple mistake (if the programmer intended to declare two pointers to MyClass):
MyClass* myVar, myVar2;
where myVar2 is not a MyClass*, but a MyClass.
There is no semantic difference between your three suggestions.
Essentially, When a code file is parsed, the preprocessor splits everything into tokens, and all later passes of the compilation process works exclusively on these tokens. Thus, spacing
between the tokens is completely ignored.
The syntax for a simple pointer declaration (with a single element being declared and without initialization) consists of three tokens: a type specifier, an asterisk (which denotes that the variable is a pointer) and, finally, an identifier. Thus, you can have any amount of whitespaces between these three, without changing the semantics at all.
The reason people choose one way over another has to do with style and what it expresses about intent.
MyClass* myVar makes it clear that the type of myVar is MyClass.
MyClass *myVar makes it clear that the pointer token belongs to the myVar variable.
The second alternative is thus especially recommended if you decide to declare a list of variables in a single statement. Such as MyClass myVar, *myPointerToVar.
Another good alternative is to always use the MyClass* myVar variant, and never make a declaration listing several variables where some are pointers.
Say I have a class with a scalar property type:
#property (nonatomic, assign) int myInt;
And for clarity, synthesized like:
#synthesize myInt = _myInt;
If someone had asked me if the following line would work:
self.myInt++;
I would have said "No". The rationale being that we all know that the dot operator is just syntactic sugar for calling a compiler-generated getter method. So that line is literally:
[self myInt]++;
If you type that second line into Xcode, it won't compile, stating: "Assigning to 'readonly' return result of an objective-c message not allowed". This makes perfect sense, and it's what I would have expected. Even if that compiled, I would have expected the outcome to increment a copy of the backing ivar on the stack, not the ivar itself.
But, the instruction self.myInt++ does compile, and it works. It works just as if that dot operator were directly accessing _myInt. By supplying my own getters and setters, I can see that both the getter and the setter are used in the process, in that order, like it was actually:
[self setMyInt:[self myInt] + 1];
So, is this an exception to the rule that the dot operator is exactly the same as a method call, or are the {--, ++, +=, -=} operators given special attention by the Objective-C compiler when used with dot notation? I've always thought of them as a C language features with no special considerations for Objective-C. I could see that simple line being very confusing to someone unfamiliar with Objective-C dot notation.
You can look at the assembler output and see that it generates two _objc_msgSend calls.
I'd guess it's more a case of applying the rule that a++ is syntactic sugar for a = a + 1