COP 3223H Lecture -*- Outline -*- * Information Hiding in C ** information hiding ------------------------------------------ MODULES TERMINOLOGY Modules interface between: client code: implementation code: The interface is described by: ------------------------------------------ ... code that uses a module (e.g., calls its functions) ... code that makes the functions work (i.e., what you do for homework) ... a specification including names and types as well as behavior (pre/post-conditions) ------------------------------------------ INFORMATION HIDING def: *information hiding* means Examples of informtion hiding: ------------------------------------------ keeping implementation decisions inside a module, so that changes to those decisions do not affect the clients of that module ... algorithm (code) used to implement a function local variable names used in a function data structures (e.g., arrays) used in a module a benefit is to reduce the size of the global namespace ** C language mechanisms for information hiding and export ------------------------------------------ C LANGUAGE MECHANISMS FOR INFO. HIDING Aside from macros, names in a C file are: hidden if they are: - declared inside functions (qualifier "auto", the default) - declared at the top level with exported to clients if they are: - top-level declarations with ------------------------------------------ ... qualifier "static" ... qualifier "extern" (or no qualifier, as extern is the default) *** example ------------------------------------------ EXAMPLE MODULE stack module (stack.c and stack.h) stack.h declares (and specifies): #define MAX_STACK_SIZE 5000 extern void stack_push(int e); extern int stack_top(); extern void stack_pop(); extern int stack_size(); stack.c implements these functions using static int rep[MAX_STACK_SIZE]; static int sz = 0; Design decisions hidden: - - - ------------------------------------------ describe the operations on stack using an abstract sequence (see stack.h) ... the data structure used to store the stack (an array) ... the way that the size of the stack is stored (an int variable) ... the algorithms for these functions *** example client ------------------------------------------ CLIENT OF STACK MODULE // file stackmain.c #include #include # include "stack.h" // compute 3*2 - (2+3) int main() { stack_push(3); int r1 = 2; int r2 = stack_top(); stack_pop(); stack_push(r1 * r2); stack_push(2); r1 = 3; r2 = stack_top(); stack_pop(); stack_push(r1 + r2); r2 = stack_top(); stack_pop(); r1 = stack_top(); stack_pop(); r2 = r1 - r2; printf("3*2 - (2+3) is %d\n", r2); return EXIT_SUCCESS; } ------------------------------------------ Q: Do we have to change this client code if the implementation of stack changes? No, that is the advantage of information hiding ** Data abstraction as a design principle ------------------------------------------ DATA ABSTRACTION def: *data abstraction* means Important because ------------------------------------------ ... treating data using a specified interface, so that the data structure is hidden A data structure is a technique used to organize data (e.g., an array is a data structure) Q: What information is hidden by the stack module? declarations for the data decisions about how the variables relate to each other algorithms for operating on the data ... data structures often change ** scope rules for C ------------------------------------------ SCOPE RULES FOR C def: scope is the area of program text where In C the scope of a declaration extends from ------------------------------------------ ... a declaration (or definition in C terminology) has effect ... the declaration to the end of the block (or function or file) in which the declaration appears Note: no declaration has scope that extends beyond a file Q: Can already_included be used in main below: main() { /* ... */ } char already_included[500][100]; string_set_has(char s[]) { /* ... */ } Can it be used in string_set_has? *** definition vs. declaration ------------------------------------------ C TERMINOLOGY: DECLARATION VS. DEFINITION def: a *declaration* introduces a name and its type (and other attributes) def: a *definition* is a declaration that either: - allocates storage or - implements a function example WHICH ONE? ======================================= int x; const int five = 5; extern int x; int inc(int x) { return x+1; } extern int inc(int x); ------------------------------------------ ... definition ... definition ... declaration ... definition ... declaration see decls_vs_defs.c and try tweaking it ------------------------------------------ MULTIPLE DEFINITIONS NOT ALLOWED It's illegal to have multiple definitions of a name in a program Why? ------------------------------------------ ... it prevents inconsistencies ** lifetimes: (storage classes, extent) in C can separately describe a variable's lifetime from its scope ------------------------------------------ LIFETIMES OR STORAGE CLASSES IN C def: the *lifetime* (or dynamic extent) of a variable is ------------------------------------------ ... when (or how long) that variable is available to the program *** infinite = whole program's execution (called static extent) ------------------------------------------ INFINITE LIFETIME (OR STATIC EXTENT) def: infinite lifetime is Properties: - initialized when program starts running - only one instance - default for functions and top-level definitions both extern and static Static variables in local scopes also have infinite lifetime e.g., seed in random number generator ------------------------------------------ ... the whole program's execution *** limited to activation of a function (called auto) ------------------------------------------ STACK ALLOCATED (OR AUTO) def: a stack-allocated variable has a lifetime that is Properties: - allocated on the run-time stack - more than one instance if have recursion - can be placed in registers! - default for function and block locals, and register vars ------------------------------------------ ... the time that the function surrounding it is running *** initialization of variables ------------------------------------------ INITIALIZATION Variables can be initialized in their definitions Examples: int i = 0; double e = 2.73; Important for const variables const double pi = 3.14159; Important for locals with static extent static int seed = 64954; Initializers must be ------------------------------------------ ... constant expresions (known at compile time) Q: Can initializer of an external variable involve a function call? no, must be a constant expression because need to know value before running program. Q: Can initializer of an auto variable involve a function call? yes Q: Should you use initialized declarations? yes, if it makes the program easier to read... ------------------------------------------ ARRAY INITIALIZATION Arrays can be initialized with a special form: int primes[] = {2, 3, 5, 7, 11, 13}; const char greeting[] = {'h', 'i', '!', '\0'}; // equivalent to the above const char greeting[] = "hi!"; ------------------------------------------