edits: 01/26/2008


Puzzles E31 ... E40

Linkage

These are additional puzzles that deal with linkage. For reference, here again are the rules for linkage.


Linkage Rules

Linkage determines how multiple occurrences of the same identifier refer to the same or different entities. There are three kinds of linkage: no linkage, external linkage, and internal linkage.

1. No Linkage:

1.1 Each declaration of an identifier with no linkage denotes a unique entity. If there are several entities in the project with the same name and no linkage, scope determines which one a statement refers to.

1.2 The following have no linkage:

  1. an identifier declared to be anything other than a variable or a function,
  2. a function parameter,
  3. a identifier declared inside a block (and not explicitly declared external.)

2. External Linkage:

2.1 Several source files and libraries may declare a particular identifier with external linkage. Each declaration of that particular identifier denotes the same entity. It is the job of the linker to ensure that there is just one entity for that identifier in the executable file.

2.2 A variable declared outside of any function has external linkage unless otherwise specified. Sometimes variables declared like this are called global variables.

2.3 A function name has external linkage unless otherwise specified.

2.4 The keyword extern gives external linkage to an identifier and gives access to an entity defined in another file. If an identifier would already have external linkage, declaring it extern does not affect it.

3. Internal Linkage:

3.1 An identifier that has internal linkage is unique within its source file, but is invisible to other source files. If other source files use this same identifier, they refer to other entities.

3.2 The keyword static gives internal linkage to an identifier that otherwise would have external linkage. (This is the only way to get internal linkage.)


Puzzle E31 — Rule 3.1 and 3.2

To show linkage in action, you must create a project that consists of several files. Here are three files:


/* --- fileA.c --- */ int x = 10;
/* --- fileB.c --- */ int x; static int bar(int val) { printf(" static bar.\n"); return 2*val; } foo() { printf(" entering foo.\n"); x = bar(x); printf(" exiting foo.\n"); }
/* --- fileC.c --- */ int x; bar() { printf(" entering extern bar x: %d\n", x); x += 10; printf(" exiting extern bar x: %d\n", x); } main() { printf("entering main x: %d\n", x ); bar(); foo(); printf("exiting main x: %d\n", x ); system("pause"); }

Remember that function names are identifiers, so the rules for the linkage of identifiers applies to them.

Question: What does the above project write to the monitor when it is executed?


Puzzle E32 — Rules 3.1 and 3.2

What does the following code write to the monitor? (Make a plausible guesses about the numbers.)


* --- goodMath.c --- */ #include <stdio.h> #include <math.h> void goodMath( double angle ) { printf("good cos( %lf ) = %lf\n", angle, cos(angle) ); printf("good sin( %lf ) = %lf\n", angle, sin(angle) ); }
/* --- main.c --- */ static double sin( double x ) { return x; } static double cos( double x ) { return 1 - x/2.0; } void badMath( double angle ) { printf("bad cos( %lf ) = %lf\n", angle, cos(angle) ); printf("bad sin( %lf ) = %lf\n\n", angle, sin(angle) ); } main() { double angle = .05 ; /* radians */ badMath ( angle ); goodMath( angle ); system("pause"); }

The functions cos() and sin() are contained in the standard math library, which will automatically be linked into the executable when you compile and run the above program. However, the file main.c has its own cos() and sin(), which, since they have internal linkage, will not conflict with the other file.


Puzzle E33

What does the following code write to the monitor?


/* --- rect.h --- */ void setWidth( int w ); void setHeight( int h ); int getArea();
/* --- rect.c --- */ static int width = 0; static int height = 0; void setWidth( int w ) { width = w; } void setHeight( int h ) { height = h; } int getArea() { return height*width; }
/* --- mainRect.c --- */ #include <stdio.h> #include "rect.h" int main() { setHeight( 4 ); setWidth( 3 ); printf("Area: %d\n", getArea() ); system("pause"); }

The header file rect.h is useful so that mainRect.c does not need to have explicitly list all the function prototypes.


Puzzle E34

Will the following code compile?


/* --- rect.h --- */ void setWidth( int w ); void setHeight( int h ); int getArea();
/* --- rect.c --- */ static int width = 0; static int height = 0; void setWidth( int w ) { width = w; } void setHeight( int h ) { height = h; } int getArea() { return height*width; }
/* --- mainRect.c --- */ #include <stdio.h> #include "rect.h" int main() { height = 4; width = 3; printf("Area: %d\n", getArea() ); system("pause"); }

Note that extern has been removed from some of the declarations.


Puzzle E35

Does the following fix the problem? Will it compile and run?


/* --- rect.h --- */ void setWidth( int w ); void setHeight( int h ); int getArea();
/* --- rect.c --- */ static int width = 0; static int height = 0; void setWidth( int w ) { width = w; } void setHeight( int h ) { height = h; } int getArea() { return height*width; }
/* --- mainRect.c --- */ #include <stdio.h> #include "rect.h" extern int height; extern int width; int main() { height = 4; width = 3; printf("Area: %d\n", getArea() ); system("pause"); }


Puzzle E36

Add the function getPerimeter() to the following project:


/* --- rect.h --- */ void setWidth( int w ); void setHeight( int h ); int getArea();
/* --- rect.c --- */ static int width = 0; static int height = 0; void setWidth( int w ) { width = w; } void setHeight( int h ) { height = h; } int getArea() { return height*width; }
/* --- mainRect.c --- */ #include <stdio.h> #include "rect.h" int main() { setHeight( 4 ); setWidth( 3 ); printf("Area: %d Perimeter: %d\n", getArea(), getPerimeter() ); system("pause"); }

Think of this as adding the method getPerimeter() to a class (in object oriented programming).


Puzzle E37

What does the following project write to the monitor?


/* --- stack.h --- */ void push( int item ); int pop(); int empty(); int full();
/* --- stack.c --- */ #define stackSize 16 static int stack[stackSize]; /* top indexes the item at the top of the stack */ static int top = -1; void push( int item ) { top++ ; stack[top] = item; } int pop() { int item; item = stack[top]; top--; return item; } int empty() { return top == -1; } int full() { return top == stackSize; }
/* --- mainStack.c --- */ #include <stdio.h> #include "stack.h" int main() { if ( !full() ) push( 13 ); if ( !full() ) push( -1 ); if ( !full() ) push( 8 ); if ( !full() ) push( 12 ); if ( !empty() ) printf("%d\n", pop() ); if ( !empty() ) printf("%d\n", pop() ); if ( !empty() ) printf("%d\n", pop() ); system("pause"); }


Static Storage

When a variable with block scope is declared to be static, it is implemented in the same section of memory as variables that have file scope (those variables declared outside of any function). This section of memory is sometimes called "static memory". Otherwise, variables with block scope are implemented on the run-time stack.

Variables implemented in static memory are persistent. They remain in existence for as long as the program is running. A value assigned to a variable in static memory will be available anywhere the variable is in scope. The value will not change unless another value is assigned to it.

A variable implemented on the run-time stack is created (pushed onto the stack) when control enters the variable's block. It is destroyed (popped off the stack) when control leaves the block. Such variables are called automatic because they are automatically created on entry to a block and automatically destroyed on exit from a block. Values assigned to an automatic variable are available only when control is inside the variable's block.

If a static variable inside a block is initialized, that initialization is done only once, the first time control enters the block. If a value is assigned to the variable later in the block, that value will be retained even after control leaves the block. The initialization will not be performed the next time control enters the block.

If an automatic variable inside a block is initialized, that initialization is done every control enters the block. If a value is assigned to the variable later in the block, that value will be lost when after control leaves the block.

static variables are initialized to zero, by default. Automatic variables are not initialized by default. They should be initialized in the declaration or with explicit assignment statements.

Here is a table that summarizes some of these rules:

Location of Variable Declaration Scope
Linkage
Storage
variable not declared as static
variable is declared as static
variable not declared as static
variable is declared as static

outside of any block

(global variable)

File Scope
External
Internal Linkage
Static
Static

inside a block

(local variable)

Block Scope
No Linkage
No Linkage
Automatic (on the stack)
Static
in a parameter list Block Scope
No Linkage
---
Automatic (on the stack)
---

Puzzle E38 — static storage class

What does the following write to the monitor?

#include <stdio.h>

void foo()
{
  int var=0;
  static int stVar=0;
  
  var++ ;
  stVar++ ;
  printf( "var: %d   stVar: %d\n", var, stVar );
}

main()
{
  foo();
  foo();
  foo();
  
  system("pause");
}


Puzzle E39 — More Static

What does the following write to the monitor?

#include <stdio.h>

int nextPrime()
{
  static int primes[] = { 2, 3, 5, 7, 11, 13, 17, 23 };
  static int index = -1;
  index++ ;
  return primes[index];
}

int main()
{
  printf("prime: %d\n", nextPrime() );
  printf("prime: %d\n", nextPrime() );
  printf("prime: %d\n", nextPrime() );
  system("pause");
}


Puzzle E40

What does the following write to the monitor?

#include <stdio.h>

static int x = 44;

foo()
{
  int j = 0, x = 0;

  {
    static int x = 100;
    printf("    inner x: %d\n", x );
    x++ ;
  }

  printf("    outer x: %d\n", x );
}

main()
{
  int x;

  for ( x=10; x<15; x++ )
  {
    printf("main x: %d\n", x );
    foo();
  }
  system("pause");
}

This puzzle involves a number of scoping rules and linkage rules. As always, try to figure out how many varialbes x there are and where they can be seen.


— Return to the main contents page