Difference between revisions of "Objective-C Variable Scope and Storage Class"

From Techotopia
Jump to: navigation, search
m (Text replacement - "<google>ADSDAQBOX_FLOW</google>" to "<htmlet>adsdaqbox_flow</htmlet>")
m (Text replacement - "<google>BUY_OBJC</google>" to "<htmlet>objc<htmlet>")
Line 7: Line 7:
 
<hr>
 
<hr>
  
<google>BUY_OBJC</google>
+
<htmlet>objc<htmlet>
  
 
In previous chapters we have invested a considerable amount of time talking about variables in terms of the various types available and how they are defined. One area we have yet to cover involves the places from which a variable is accessible once it has been declared. This is a concept known as ''variable scope'' and the scope of a variable is very much dependent upon where it is declared within the Objective-C code of a program.  
 
In previous chapters we have invested a considerable amount of time talking about variables in terms of the various types available and how they are defined. One area we have yet to cover involves the places from which a variable is accessible once it has been declared. This is a concept known as ''variable scope'' and the scope of a variable is very much dependent upon where it is declared within the Objective-C code of a program.  

Revision as of 21:05, 1 February 2016

PreviousTable of ContentsNext
Objective-C Dynamic Binding and Typing with the id TypeAn Overview of Objective-C Functions

Cannot find HTML file objc<htmlet> In previous chapters we have invested a considerable amount of time talking about variables in terms of the various types available and how they are defined. One area we have yet to cover involves the places from which a variable is accessible once it has been declared. This is a concept known as ''variable scope'' and the scope of a variable is very much dependent upon where it is declared within the Objective-C code of a program. In this chapter we will also look at the Objective-C variable storage classes. These are specifiers that tell the Objective-C compiler information about how the variable is going to be used within the application code. == Variable Scope == An Objective-C program will consist of code divided up into functions, classes and code structures (such as ''do .. while'' and ''for'' loops). Invariably a typical program will make extensive use of variables to store and manipulate data. Once a variable has been declared it may or may not be accessible to other sections of the program code. This accessibility depends on where and how the variable was declared and where the code is that needs to access it. This is known as ''variable scope'' and falls into a number of categories, each of which will be covered in this chapter. == Block Scope == Objective-C code is divided into sequences of code blocks and files that define the structure of a program. Each block, referred to as a ''statement block'', is encapsulated by braces ({}). For example, a ''for'' loop typically contains a statement block: <pre> int x; for (x = 0; x < 10; x++) { int j = x + 10; NSLog (@"j = %i", j); } <pre> In the above example, variable ''j'' is declared within the statement block of the ''for'' loop and as such is considered to be ''local'' to that block. This means that the variable can be accessed from within the ''for'' loop statement block but is essentially invisible and inaccessible to code anywhere else in the program code. Any attempt to access variable ''j'' outside the ''for'' loop will result in a compile error. For example: <pre> int x; for (x = 0; x < 10; x++) { int j = x + 10; NSLog (@"j = %i", j); } j += 20; illegal - j is now out of scope <pre> An attempt to compile the above code within the context of an application will result in a compilation error along the lines of the following: <tt>error: use of undeclared identifier 'j'<tt> An interesting side effect of variable scope within this context is that it enables us to have more than one variable with the same name as long as they are in different scopes. For example, we can have a variable named ''j'' declared outside the ''for'' loop and a variable named ''j'' declared inside the for loop. Although these variables have the same name they occupy different memory locations and contain different values. This can be illustrated using a simple application that contains two ''j'' variables: <pre> #import <FoundationFoundation.h> int main (int argc, const char * argv[]) { @autoreleasepool { int x; int j = 54321; for (x = 0; x < 10; x++) { int j = x + 10; NSLog (@"Varible j in for loop is %i", j); } NSLog (@"Variable j outside for loop is %i", j); } return 0; } <pre> As we can see from the above code, variable ''j'' is declared twice but in two different scopes. When compiled and executed we can see that modifying the value of ''j'' within the ''for'' loop has no effect on the value assigned to the variable ''j'' declared outside the for loop: <pre> 2009-10-19 15:09:39.875 t[8130:10b] Variable j in for loop is 10 2009-10-19 15:09:39.877 t[8130:10b] Variable j in for loop is 11 2009-10-19 15:09:39.877 t[8130:10b] Variable j in for loop is 12 2009-10-19 15:09:39.878 t[8130:10b] Variable j in for loop is 13 2009-10-19 15:09:39.878 t[8130:10b] Variable j in for loop is 14 2009-10-19 15:09:39.879 t[8130:10b] Variable j in for loop is 15 2009-10-19 15:09:39.879 t[8130:10b] Variable j in for loop is 16 2009-10-19 15:09:39.879 t[8130:10b] Variable j in for loop is 17 2009-10-19 15:09:39.880 t[8130:10b] Variable j in for loop is 18 2009-10-19 15:09:39.880 t[8130:10b] Variable j in for loop is 19 2009-10-19 15:09:39.881 t[8130:10b] Variable j outside for loop is 54321 <pre> == Function Scope == Objective-C code is typically structured into a number of classes and code units called ''functions'' (for more details on functions see the chapter entitled [[An Overview of Objective-C Functions]]). In terms of variable scope, functions are really little more than statement blocks in that they are encapsulated in braces and variables declared within those braces are ''local'' to that function block. The following example is intended to illustrate this concept and contains two functions named ''main()'' and ''multiply()'' respectively. <pre> #import <FoundationFoundation.h> int main (int argc, const char * argv[]) { @autoreleasepool { int j = 10; int k = 20; int result; result = mutliply(); } return 0; } int multiply() { return j * k; } <pre> An attempt to compile the above code example will result in a compiler error similar to the following: <pre> In function 'multiply': error: 'j' undeclared (first use in this function) error: (Each undeclared identifier is reported only once error: for each function it appears in.) error: 'k' undeclared (first use in this function) <pre> The reason for this error is that variables ''j'' and ''k'' are declared in the ''main()'' function and are, therefore, local to that function. As such, these variables are not visible to the ''multiply()'' function resulting in an error when we try to reference them. If we wanted to have access to the values of those variables we would have to pass them through as arguments to the multiply function (for details on function arguments refer to [[An Overview of Objective-C Functions]]) or specify them as global or static variables (discussed below). As with block scope, it is possible to have multiple variables with the same name inside a single function as long as each instance appears within its own local scope. For example, we can add a while loop to our ''main()'' that has its own local variable also named ''j'': <pre> int main (int argc, const char * argv[]) { @autoreleasepool { int j = 10; int k = 20; int result; while (k > 0) { int j = 0; j =+ k; k--; } } return 0; } <pre> == Global Scope == A variable that has ''global scope'' is potentially accessible to code anywhere else in an Objective-C program, regardless of whether the code is in a separate file to the one in which the variable is declared. Global variables are declared ''outside'' of any statement blocks and are typically placed near the top of a source file. The following is a code listing from an Objective-C source file named ''main.m'': <pre> #import <FoundationFoundation.h> int myVar = 321; int main (int argc, const char * argv[]) { @autoreleasepool { NSLog (@"myVar = %i", myVar); } return 0; } <pre> As we can see, the global variable ''myVar'' is declared outside of the ''main()'' function and is not embedded into a statement block or class declaration of any kind. Because this is a global variable, it is directly accessible inside the main function and would also be accessible from any other functions and statement blocks within the context of the ''main.m'' code file. As previously stated, global variables are potentially accessible across all the source files that constitute an Objective-C program. The key word here is ''potentially'', and we say this because global access across multiple source files is not the default for a global variable. Take, for example, the following two code files. The first file, ''main.m'' contains the declaration of the global variable ''myVar'' and calls a function named ''displayit()'': <pre> #import <FoundationFoundation.h> int myVar = 321; void displayit(); int main (int argc, const char * argv[]) { @autoreleasepool { NSLog (@"myVar = %i", myVar); displayit(); [pool drain]; } return 0; } <pre> The second file, named ''displayit.m'' contains the code for the ''displayit()'' function and displays the value currently assigned to the global ''myVar'' variable: <pre> #import <FoundationFoundation.h> void displayit() { NSLog (@"MyVar from different source file is %i", myVar); } <pre> If we try to compile these two code files into an executable either using Xcode or from the command-line we will get an error that reads as follows: <pre> clang -framework Foundation main.m displayit.m -o main displayit.m:7:59: error: use of undeclared identifier 'myVar' NSLog (@"MyVar from different source file is %i", myVar); <pre> The reason for this is that although the variable was declared as global in ''main.m'' we still need to take one extra step in ''displayit.m'' to make the variable accessible in this file. This step involves declaring that the variable is ''external'' to the local file. This declaration is achieved using the ''extern'' specifier keyword. For example, to make ''myVar'' accessible in ''displayit.m'' the following code would be required: <pre> extern int myVar; void displayit() { NSLog (@"MyVar from different source file is %i", myVar); } <pre> Having made this change, the code will now compile and run. == File Scope == In the preceding section on ''global scope'' we talked about how a variable declared outside of any statement blocks is considered to be global and may be accessed both by code in the same file, or by code in different files. Suppose, however, that you wanted a variable to be accessible ''only'' to code within the file where the variable is declared. This is achieved by using the ''static'' specifier when declaring the variable. For example, the following code is from a file named ''main.m''. This file declares variable ''myVar'' to be static. As such, the variable will be accessible only to code within the ''main.m'' file and cannot be accessed by code in any other file: <pre> #import <FoundationFoundation.h> static int myVar = 543; void displayit(); int main (int argc, const char * argv[]) { @autoreleasepool { NSLog (@"myVar = %i", myVar); displayit(); } return 0; } <pre> <htmlet>adsdaqbox_flow.html

Variable Storage Class

Variable storage class specifiers are used when declaring a variable to give the compiler information about how a variable is likely to be used and accessed within the program being compiled. So far in this chapter we have actually already looked at two storage class specifiers in the form of extern and static. A full list of variable storage class specifiers supported by Objective-C is as follows:

  • extern - Specifies that the variable name is referencing a global variable specified in a different source file to the current file.
  • static - Specifies that the variable is to be accessible only within the scope of the current source file.
  • auto - The default value for variable declarations. Specifies the variable is to be local or global depending on where the declaration is made within the code. Since this is the default setting this specifier is rarely, if ever, used.
  • const - Declares a variable as being read-only. In other words, specifies that once the variable has been assigned a value, that value will not be subsequently changed.
  • volatile - Specifies that the value assigned to a variable will be changed in subsequent code. The default behavior for variable declarations.

<google>BUY_OBJC_BOTTOM</google>


PreviousTable of ContentsNext
Objective-C Dynamic Binding and Typing with the id TypeAn Overview of Objective-C Functions