Showing posts with label Compilation. Show all posts
Showing posts with label Compilation. Show all posts

Wednesday, December 4, 2013

Functions


C is a function-based language. A function is a block of code defining what should happen; when other code calls (invokes) that function, the function’s code does happen. A function returns a value, which is substituted for the call to that function.

Here’s a definition of a function that accepts an integer and returns its square:
    int square(int i) {
        return i * i;
}
Now I’ll call that function:
int i = square(3);
Because of the way square is defined, that is exactly like saying:
int i = 9;
That example is extremely simple, but it illustrates many key aspects of functions. Let’s analyze how a function is defined:
int(1) square(2) ((3) int i) {(4)return i * i;
}

Note: The Text in red color is explained below.

(1) We start with the type of value that the function returns; here, it returns an int. 
(2) Then we have the name of the function, which is square.
(3) Then we have parentheses, and here we place the data type and name of any values that this function expects to receive. Here, square expects to receive one value, an int, which we are calling i. The name i (along with its expected data type) is a parameter; when the function is called, its value will be supplied as an argument. If a function expects to receive more than one value, multiple parameters in its definition are separated by a comma (and when the function is called, the arguments supplied are likewise separated by a comma).
(4) Finally, we have curly braces containing the statements that are to be executed when the function is called.


Those curly braces constitute a scope; variables declared within them are local to the function. The names used for the parameters in the function definition are also local to the function; in other words, the i in the first line of the function definition is the same as the i in the second line of the function definition, but it has nothing to do with any i used outside the function definition (as when the result of the function call is assigned to a variable called i). The value of the i parameter in the function definition is assigned from the corresponding argument when the function is called; in the previous example, it is 3, which is why the function result is 9. Supplying a function call with arguments is thus a form of assignment. Suppose a function is defined like this:
    int myfunction(int i, int j) { // ...
And suppose we call that function:
int result = myfunction(3, 4);
That function call effectively assigns 3 to the function’s i parameter and 4 to the func‐
tion’s j parameter.
When a return statement is encountered, the value accompanying it is handed back as the result of the function call, and the function terminates. It is legal for a function to return no value; in such a case, the return statement has no accompanying value, and the definition states the type of value returned by the function as void. It is also legal to call a function and ignore its return value even if it has one. For example, we could say:
square(3);
That would be a somewhat silly thing to say, because we have gone to all the trouble of calling the function and having it generate the square of 3 — namely 9 — but we have done nothing to capture that 9. It is exactly as if we had said:
9;
You’re allowed to say that, but it doesn’t seem to serve much purpose. On the other hand, the point of a function might be not so much the value it returns as other things it does as it is executing, so then it might make perfect sense to ignore its result.

The parentheses in a function’s syntax are crucial. Parentheses are how C knows there’s a function. Parentheses after the function name in the function definition are how C knows this is a function definition, and they are needed even if this function takes no parameters. Parentheses after the function name in the function call are how C knows this is a function call, and they are needed even if this function call supplies no argu‐ ments. Using the bare name of a function is possible, because the name is the name of something, but it doesn’t call the function. (I’ll talk later about something it does do.)
Let’s return to the simple C function definition and call that I used as my example earlier. Suppose we combine that function definition and the call to that function into a single program:
    int square(int i) {
        return i * i;
    }
    int i = square(3);
That is a legal program, but only because the definition of the square function precedes the call to that function. If we wanted to place the definition of the square function elsewhere, such as after the call to it, we would need at least to precede the call with a declaration of the square function (Example 1-3). The declaration looks just like the first line of the definition, but it is a statement, ending with a semicolon rather than a left curly brace.
Example 1-3. Declaring, calling, and defining a function
int square(int i);
int i = square(3);
int square(int i) {
return i * i; }
The parameter names in the declaration do not have to match the parameter names in the definition, but all the types (and, of course, the name of the function) must match. The types constitute the signature of this function. In other words, it does not matter if the first line, the declaration, is rewritten thus:
    int square(int j);
What does matter is that, both in the declaration and in the definition, square is a function taking one int parameter and returning an int. (In a modern Objective-C pro‐ gram, though, the function declaration usually won’t be necessary, even if the function call precedes its definition; see “Modern Objective-C Function and Method Declara‐ tions”)
In Objective-C, when you’re sending a message to an object, you won’t use a function call; you’ll use a method call. But you will most definitely use plenty of C function calls as well. For example, earlier we initialized a CGPoint by setting its x element and its y element, but what you’ll usually do to make a new CGPoint is to call CGPointMake, which is declared like this:
    CGPoint CGPointMake (
       CGFloat x,
CGFloat y );
Despite its multiple lines and its indentations, this is indeed a C function declaration, just like the declaration for our simple square function. It says that CGPointMake is a C function that takes two CGFloat parameters and returns a CGPoint. So now you know (I hope) that it would be legal (and typical) to write this sort of thing:
    CGPoint myPoint = CGPointMake(4.3, 7.1); 

 
 
 

Tuesday, December 3, 2013

Variable Declaration, Initialization, and Data Types (Learn C Programming)


C is a strongly typed language. Every variable must be declared, indicating its data type, before it can be used. Declaration can also involve explicit initialization, giving the variable a value; a variable that is declared but not explicitly initialized is of uncertain value (and should be regarded as dangerous until it is initialized). In K&R C, declarations must precede all other statements, but in modern versions of C, this rule is relaxed so that you don’t have to declare a variable until just before you start using it:
int height = 2;
    int width = height * 2;
    height = height + 1; 
    int area = height * width;

The basic built-in C data types are all numeric: char (one byte), int (four bytes), float and double (floating-point numbers), and varieties such as short (short integer), long (long integer), unsigned short, and so on. A numeric literal may optionally express its type through a suffixed letter or letters: for example, 4 is an int, but 4UL is an unsigned long; 4.0 is a double, but 4.0f is a float. Objective-C makes use of some further numeric types derived from the C numeric types (by way of the typedef statement, K&R 6.7) designed to respond to the question of whether the processor is 64-bit; the most im‐ portant of these are NSInteger (along with NSUInteger) and CGFloat. You don’t need to use them explicitly unless an API tells you to, and even when you do, just think of NSInteger as int and CGFloat as float, and you’ll be fine.
To cast (or typecast) a variable’s value explicitly to another type, precede the variable’s name with the other type’s name in parentheses:
    int height = 2;
    float fheight = (float)height;
In that particular example, the explicit cast is unnecessary because the integer value will be cast to a float implicitly as it is assigned to a float variable, but it illustrates the notation. You’ll find yourself typecasting quite a bit in Objective-C, mostly to subdue the worries of the compiler.
Another form of numeric initialization is the enumeration, or enum (K&R 2.3). It’s a way of assigning names to a sequence of numeric values and is useful when a value represents one of several possible options. The Cocoa API uses this device a lot. For example, the three possible types of status bar animation might be defined like this:
    typedef enum {
       UIStatusBarAnimationNone,
       UIStatusBarAnimationFade,
       UIStatusBarAnimationSlide,
    } UIStatusBarAnimation;
That definition assigns the value 0 to the name UIStatusBarAnimationNone, the value 1 to the name UIStatusBarAnimationFade, and the value 2 to the name UIStatusBar- AnimationSlide. The upshot is that you can use the suggestively meaningful names without caring about, or even knowing, the arbitrary numeric values they represent. It’s a useful idiom, and you may well have reason to define enumerations in your own code.
That definition also assigns the name UIStatusBarAnimation to this enumeration as a whole. A named enumeration is not a data type, but you can pretend that it is, and the compiler can warn you if you mix enumeration types. For example, suppose you were to write this code: 

UIStatusBarAnimation anim = UIInterfaceOrientationPortrait;
That isn’t illegal; UIInterfaceOrientationPortrait is another name for 0, just as if you had said UIStatusBarAnimationNone. However, it comes from a different named enumeration, namely UIInterfaceOrientation. The compiler detects this, and warns you. Just as with a real data type, you can even squelch that warning by typecasting.
In iOS 7, the status bar animation types are defined like this:
    typedef NS_ENUM(NSInteger, UIStatusBarAnimation) {
        UIStatusBarAnimationNone,
        UIStatusBarAnimationFade,
        UIStatusBarAnimationSlide,
};
That notation was introduced in LLVM compiler version 4.0, which made its debut in Xcode 4.4. NS_ENUM is a macro, a form of preprocessor text substitution discussed at the end of this chapter; when the text substitution is performed, that code turns out to be shorthand for this:
    typedef enum UIStatusBarAnimation : NSInteger UIStatusBarAnimation;
    enum UIStatusBarAnimation : NSInteger {
        UIStatusBarAnimationNone,
        UIStatusBarAnimationFade,
        UIStatusBarAnimationSlide,
};
That looks almost exactly like the old way of expressing the same enumeration, but the new way involves some notation that isn’t part of standard C, telling the compiler what variety of integer value is being used here (it’s an NSInteger). This makes UIStatusBar‐ Animation even more like a genuine data type; in addition, the new enum notation lets Xcode help you more intelligently when performing code completion, as discussed in Chapter 9. Another macro, NS_OPTIONS, evaluates in Objective-C as a synonym of NS_ENUM (they are distinct only in C++ code, which is not discussed in this book).
There appears to be a native text type (a string) in C, but this is something of an illusion; behind the scenes, it is a null-terminated array of char. For example, in C you can write a string literal like this:
"string"
But in fact this is stored as 7 bytes, the numeric (ASCII) equivalents of each letter fol‐ lowed by a byte consisting of 0 to signal the end of the string. This data structure, called a C string, is rarely encountered while programming iOS. In general, when working with strings, you’ll use an Objective-C object type called NSString. An NSString is totally different from a C string; it happens, however, that Objective-C lets you write a literal NSString in a way that looks very like a C string:
@"string" 

Notice the at-sign! This expression is actually a directive to the Objective-C compiler to form an NSString object. A common mistake is forgetting the at-sign, thus causing your expression to be interpreted as a C string, which is a completely different animal.
Because the notation for literal NSStrings is modeled on the notation for C strings, it is worth knowing something about C strings, even though you won’t generally encounter them. For example, K&R lists a number of escaped characters (K&R 2.3), which you can also use in a literal NSString, including the following:

\n
A Unix newline character

\t 

A tab character

\"
A quotation mark (escaped to show that this is not the end of the string literal)

\\
A backslash 


K&R also mention a notation for concatenating string literals, in which multiple string literals separated only by white space are automatically concatenated and treated as a single string literal. This notation is useful for splitting a long string into multiple lines for legibility, and Objective-C copies this convention for literal NSStrings as well, except that you have to remember the at-sign:
    @"This is a big long literal string "
    @"which I have broken over two lines of code.";




Compilation, Statements, and Comments (Learn C language)


C is a compiled language. You write your program as text; to run the program, things proceed in two stages. First your text is compiled into machine instructions; then those machine instructions are executed. Thus, as with any compiled language, you can make two kinds of mistake:
  • Any purely syntactic errors (meaning that you spoke the C language incorrectly) will be caught by the compiler, and the program won’t even begin to run.
  • If your program gets past the compiler, then it will run, but there is no guarantee that you haven’t made some other sort of mistake, which can be detected only by noticing that the program doesn’t behave as intended.
    The C compiler is fussy, but you should accept its interference with good grace. The compiler is your friend: learn to love it. It may emit what looks like an irrelevant or incomprehensible error message, but when it does, the fact is that you’ve done some‐ thing wrong and the compiler has helpfully caught it for you. Also, the compiler can warn you if something seems like a possible mistake, even though it isn’t strictly illegal; these warnings, which differ from outright errors, are also helpful and should not be ignored.
    I have said that running a program requires a preceding stage: compilation. But in fact there is another stage that precedes compilation: preprocessing. Preprocessing modifies your text, so when your text is handed to the compiler, it is not identical to the text you wrote. Preprocessing might sound tricky and intrusive, but in fact it proceeds only according to your instructions and is helpful for making your code clearer and more compact.
    Xcode allows you to view the effects of preprocessing on your program text (choose Product → Perform Action → Preprocess [Filename]), so if you think you’ve made a mistake in instructing the preprocessor, you can track it down. I’ll talk more later about some of the things you’re likely to say to the preprocessor.
    C is a statement-based language; every statement ends in a semicolon. (Forgetting the semicolon is a common beginner’s mistake.) For readability, programs are mostly writ‐ ten with one statement per line, but this is by no means a hard and fast rule: long statements (which, unfortunately, arise very often because of Objective-C’s verbosity) are commonly split over multiple lines, and extremely short statements are sometimes written two or three to a line. You cannot split a line just anywhere, however; for example, a literal string can’t contain a return character. Indentation is linguistically meaningless and is purely a matter of convention (and C programmers argue over those conventions with near-religious fervor); Xcode helps “intelligently” by indenting automatically, and you can use its automatic indentation both to keep your code readable and to confirm that you’re not making any basic syntactic mistakes. 
Comments are delimited in K&R C by /* ... */; the material between the delimiters can consist of multiple lines (K&R 1.2). In modern versions of C, a comment also can be denoted by two slashes (//); the rule is that if two slashes appear, they and everything after them on the same line are ignored:
    int lower = 0; // lower limit of temperature table
These are sometimes called C++-style comments and are much more convenient for brief comments than the K&R comment syntax.
Throughout the C language (and therefore, throughout Objective-C as well), capitali‐ zation matters. All names are case-sensitive. There is no such data type as Int; it’s low‐ ercase “int.” If you declare an int called lower and then try to speak of the same variable as Lower, the compiler will complain. By convention, variable names tend to start with a lowercase letter.