Open In App

Internal Linkage and External Linkage in C

Last Updated : 16 Jun, 2022
Comments
Improve
Suggest changes
Like Article
Like
Save
Share
Report
News Follow

It is often quite hard to distinguish between scope and linkage, and the roles they play. This article focuses on scope and linkage, and how they are used in C language.
Note: All C programs have been compiled on 64 bit GCC 4.9.2. Also, the terms “identifier” and “name” have been used interchangeably in this article.


Definitions

  • Scope : Scope of an identifier is the part of the program where the identifier may directly be accessible. In C, all identifiers are lexically (or statically) scoped.
  • Linkage : Linkage describes how names can or can not refer to the same entity throughout the whole program or one single translation unit.
    The above sounds similar to Scope, but it is not so. To understand what the above means, let us dig deeper into the compilation process.
  • Translation Unit : A translation unit is a file containing source code, header files and other dependencies. All of these sources are grouped together to form a single translation unit which can then be used by the compiler to produce one single executable object. It is important to link the sources together in a meaningful way. For example, the compiler should know that printf definition lies in stdio header file.

In C and C++, a program that consists of multiple source code files is compiled one at a time. Until the compilation process, a variable can be described by it’s scope. It is only when the linking process starts, that linkage property comes into play. Thus, scope is a property handled by compiler, whereas linkage is a property handled by linker.

The Linker links the resources together in the linking stage of compilation process. The Linker is a program that takes multiple machine code files as input, and produces an executable object code. It resolves symbols (i.e, fetches definition of symbols such as “+” etc..) and arranges objects in address space.

Linkage is a property that describes how variables should be linked by the linker. Should a variable be available for another file to use? Should a variable be used only in the file declared? Both are decided by linkage.
Linkage thus allows you to couple names together on a per file basis, scope determines visibility of those names.
There are 2 types of linkage:

  1. Internal Linkage: An identifier implementing internal linkage is not accessible outside the translation unit it is declared in. Any identifier within the unit can access an identifier having internal linkage. It is implemented by the keyword static. An internally linked identifier is stored in initialized or uninitialized segment of RAM. (note: static also has a meaning in reference to scope, but that is not discussed here).
    Some Examples:

    Animals.cpp




    // C code to illustrate Internal Linkage
    #include <stdio.h>
      
    static int animals = 8;
    const int i = 5;
      
    int call_me(void)
    {
        printf("%d %d", i, animals);
    }

    
    

    The above code implements static linkage on identifier animals. Consider Feed.cpp is located in the same translation unit.

    Feed.cpp




    // C code to illustrate Internal Linkage
    #include <stdio.h>
      
    int main()
    {
        call_me();
        animals = 2;
        printf("%d", animals);
        return 0;
    }

    
    

    On compiling Animals.cpp first and then Feed.cpp, we get

    Output : 5 8 2
    

    Now, consider that Feed.cpp is located in a different translation unit. It will compile and run as above only if we use #include "Animals.cpp".
    Consider Wash.cpp located in a 3rd translation unit.

    Wash.cpp




    // C code to illustrate Internal Linkage
    #include <stdio.h>
    #include "animal.cpp" // note that animal is included.
      
    int main()
    {
        call_me();
        printf("\n having fun washing!");
        animals = 10;
        printf("%d\n", animals);
        return 0;
    }

    
    

    On compiling, we get:

    Output : 5 8
    having fun washing!
    10
    

    There are 3 translation units (Animals, Feed, Wash) which are using animals code.
    This leads us to conclude that each translation unit accesses it’s own copy of animals. That is why we have animals = 8 for Animals.cpp, animals = 2 for Feed.cpp and animals = 10 for Wash.cpp. A file. This behavior eats up memory and decreases performance.

    Another property of internal linkage is that it is only implemented when the variable has global scope, and all constants are by default internally linked.

    Usage : As we know, an internally linked variable is passed by copy. Thus, if a header file has a function fun1() and the source code in which it is included in also has fun1() but with a different definition, then the 2 functions will not clash with each other. Thus, we commonly use internal linkage to hide translation-unit-local helper functions from the global scope. For example, we might include a header file that contains a method to read input from the user, in a file that may describe another method to read input from the user. Both of these functions are independent of each other when linked.

  2. External Linkage: An identifier implementing external linkage is visible to every translation unit. Externally linked identifiers are shared between translation units and are considered to be located at the outermost level of the program. In practice, this means that you must define an identifier in a place which is visible to all, such that it has only one visible definition. It is the default linkage for globally scoped variables and functions. Thus, all instances of a particular identifier with external linkage refer to the same identifier in the program. The keyword extern implements external linkage.

    When we use the keyword extern, we tell the linker to look for the definition elsewhere. Thus, the declaration of an externally linked identifier does not take up any space. Extern identifiers are generally stored in initialized/uninitialized or text segment of RAM.

    Please do go through Understanding extern keyword in C before proceeding to the following examples.
    It is possible to use an extern variable in a local scope. This shall further outline the differences between linkage and scope. Consider the following code:




    // C code to illustrate External Linkage
    #include <stdio.h>
      
    void foo()
    {
        int a;
        extern int b; // line 1
    }
      
    void bar()
    {
        int c;
        c = b; // error
    }
      
    int main()
    {
        foo();
        bar();
    }

    
    

    Error: 'b' was not declared in this scope
    


    Explanation :
    The variable b has local scope in the function foo, even though it is an extern variable. Note that compilation takes place before linking; i.e scope is a concept that can be used only during compile phase. After the program is compiled there is no such concept as “scope of variable”.

    During compilation, scope of b is considered. It has local scope in foo(). When the compiler sees the extern declaration, it trusts that there is a definition of b somewhere and lets the linker handle the rest.

    However, the same compiler will go through the bar() function and try to find variable b. Since b has been declared extern, it has not been given memory yet by the compiler; it does not exist yet. The compiler will let the linker find the definition of b in the translation unit, and then the linker will assign b the value specified in definition. It is only then that b will exist and be assigned memory. However, since there is no declaration given at compile time within the scope of bar(), or even in global scope, the compiler complains with the error above.

    Given that it is the compiler’s job to make sure that all variables are used within their scopes, it complains when it sees b in bar(), when b has been declared in foo()‘s scope. The compiler will stop compiling and the program will not be passed to the linker.

    We can fix the program by declaring b as a global variable, by moving line 1 to before foo‘s definition.

    Let us look at another example




    // C code to illustrate External Linkage
    #include <stdio.h>
      
    int x = 10;
    int z = 5;
      
    int main()
    {
      
        extern int y; // line 2
        extern int z;
        printf("%d %d %d", x, y, z);
    }
      
    int y = 2;

    
    

    Output: 10 2 5
    

    We can explain the output by observing behaviour of external linkage. We define 2 variables x and z in global scope. By default, both of them have external linkage. Now, when we declare y as extern, we tell the compiler that there exists a y with some definition within the same translation unit. Note that this is during the compile time phase, where the compiler trusts the extern keyword and compiles the rest of the program. The next line, extern int z has no effect on z, as z is externally linked by default when we declared it as a global variable outside the program. When we encounter printf line, the compiler sees 3 variables, all 3 having been declared before, and all 3 being used within their scopes (in the printf function). The program thus compiles successfully, even though the compiler does not know the definition of y

    The next phase is linking. The linker goes through the compiled code and finds x and z first. As they are global variables, they are externally linked by default. The linker then updates value of x and z throughout the entire translation unit as 10 and 5. If there are any references to x and z in any other file in the translation unit, they are set to 10 and 5.

    Now, the linker comes to extern int y and tries to find any definition of y within the translation unit. It looks through every file in the translation unit to find definition of y. If it does not find any definition, a linker error will be thrown. In our program, we have given the definition outside main(), which has already been compiled for us. Thus, the linker finds that definition and updates y.



    Previous Article
    Next Article

Similar Reads

Difference Between Hive Internal and External Tables
Hive can be used to manage structured data on the top of Hadoop. The data is stored in the form of a table inside a database. In Hive, the user is allowed to create Internal as well as External tables to manage and store data in a database. In this article, we will be discussing the difference between Hive Internal and external tables with proper p
6 min read
Internal static variable vs. External static variable with Examples in C
The static variable may be internal or external depending on the place of declaration. Both kinds of static variables are stored in initialized data segments. Internal Static Variables Internal Static variables are defined as those having static variables which are declared inside a function and extend up to the end of the particular function. Synt
2 min read
marshal — Internal Python object serialization
Serializing a data means converting it into a string of bytes and later reconstructing it from such a string. If the data is composed entirely of fundamental Python objects, the fastest way to serialize the data is by using marshal module (For user defined classes, Pickle should be preferred). Marshal module contains functions that can read and wri
2 min read
How to Fix a 500 Internal Server Error?
The "HTTP 500 - Internal Server Error" is a frustrating and common issue that indicates something has gone wrong on the server's side. This error is a catch-all message indicating that something went wrong on the web server but the server cannot specify what exactly the problem is. It's a common server-side error, meaning the issue stems from the s
10 min read
Resetting a root password in Linux without external media
We have to follow 8 steps to crack root password without using any external media Step-1 : Reboot the system and interrupt the boot loader countdown timer by pressing any key except enter. Step-2 :  Find the entry that is normally booted, and change it to halt execution during the initial ram disk. 2.1. Use the cursor keys to highlight the entry th
2 min read
Difference and Similarities between PHP and C
PHP is a server-side scripting language designed specifically for web development. It can be easily embedded in HTML files and HTML codes can also be written in a PHP file. The thing that differentiates PHP from a client-side language like HTML is, PHP codes are executed on the server whereas HTML codes are directly rendered on the browser. C is a
3 min read
Rearrange array such that arr[i] &gt;= arr[j] if i is even and arr[i]&lt;=arr[j] if i is odd and j &lt; i
Given an array of n elements. Our task is to write a program to rearrange the array such that elements at even positions are greater than all elements before it and elements at odd positions are less than all elements before it.Examples: Input : arr[] = {1, 2, 3, 4, 5, 6, 7} Output : 4 5 3 6 2 7 1 Input : arr[] = {1, 2, 1, 4, 5, 6, 8, 8} Output : 4
11 min read
Find speed of man from speed of stream and ratio of time with up and down streams
Program to find the speed of man in km/hr, given the speed of stream in km/hr. Assume that the man takes n times (where n &gt; 1) as long to row upstream as to row downstream the river.Examples: Input : 5.5 4 Output : speed of man is 9.16667 km/hr Input : 4 3 Output : speed of man is 8 km/hr Approach Used :Let speed of the man in still water = x km
4 min read
Lex program to take input from file and remove multiple spaces, lines and tabs
FLEX (Fast Lexical Analyzer Generator) is a tool/computer program for generating lexical analyzers (scanners or lexers) written by Vern Paxson in C around 1987. Lex reads an input stream specifying the lexical analyzer and outputs source code implementing the lexer in the C programming language. The function yylex() is the main flex function which
2 min read
Similarities and Differences between Ruby and C language
Similarities between Ruby and C There are many similarities between C and Ruby, and some of them are: Like C, in Ruby also… A programmer is able to program procedurally if they like to do. But still, behind the scenes, it will be object-oriented.Both the languages have the same operators, for example, compound assignment and bitwise operators. But
3 min read
Getting System and Process Information Using C Programming and Shell in Linux
Whenever you start a new process in Linux it creates a file in /proc/ folder with the same name as that of the process id of the process. In that folder, there is a file named "status" which has all the details of the process. We can get those Process Information Through shell as follows: cat /proc/1/status As can be seen, it displays most of the i
2 min read
Maximum distance between i and j such that i ≤ j and A[i] ≤ B[j]
Given two non-increasing arrays A[] and B[] of size N, the task is to find the maximum distance between i and j such that i ≤ j and A[i] ≤ B[j]. Examples: Input: A[] = {2, 2, 2}, B[] = {10, 10, 1}Output: 1Explanation: The valid pairs satisfying the conditions are (0, 0), (0, 1), and (1, 1).Therefore, the maximum distance is 1 between the indices 0
11 min read
Need of Data Structures and Algorithms for Deep Learning and Machine Learning
Deep Learning is a field that is heavily based on Mathematics and you need to have a good understanding of Data Structures and Algorithms to solve the mathematical problems optimally. Data Structures and Algorithms can be used to determine how a problem is represented internally or how the actual storage pattern works &amp; what is happening under
6 min read
Count N-length arrays of made up of elements not exceeding 2^K - 1 having maximum sum and Bitwise AND equal to 0
Given two integers N and K, the task is to find the number of N-length arrays that satisfies the following conditions: The sum of the array elements is maximum possible.For every possible value of i ( 1 ? i ? N ), the ith element should lie between 0 and 2K - 1.Also, Bitwise AND of all the array elements should be 0. Note: Since, the answer can be
7 min read
10 Tips and Tricks to Crack Internships and Placements
“All our dreams can come true if we have the courage to pursue them.” - Walt Disney The placement season has already started and many of you must be gearing up for placements. However, many of you must be having doubts like what exactly we should prepare, what are the expectations of an interviewer, are placements too difficult to crack, how to cle
6 min read
Avoiding elif and ELSE IF Ladder and Stairs Problem
This article focuses on discussing the elif and else if ladder and stairs problem and the solution for the same in the C and Python Programming languages. The ELIF and ELSE IF Ladder and Stairs ProblemThere are programmers who shy away from long sequences of IF, ELSE IF, ELSE IF, ELSE IF , etc. typically ending with a final ELSE clause. In language
6 min read
Code Optimization Technique (logical AND and logical OR)
Logical AND (&amp;&amp;)While using &amp;&amp; (logical AND), we must put the condition first whose probability of getting false is high so that compiler doesn’t need to check the second condition if the first condition is false. C/C++ Code #include &lt;bits/stdc++.h&gt; using namespace std; // Function to check whether n is odd bool isOdd(int n) {
7 min read
How to Upgrade Pip and Python on Windows, Linux, and MacOS?
Python is a programming language with standard libraries and a great ecosystem of third-party packages. On the other side, Pip is the default package manager for Python that installs, upgrades and manages Python, including its dependencies. Pip simplifies the process of installing external libraries and tools which are written in Python. Pip allows
5 min read
What are the differences between bitwise and logical AND operators in C/C++?
A Bitwise And operator is represented as '&amp;' and a logical operator is represented as '&amp;&amp;'. The following are some basic differences between the two operators. a) The logical and operator '&amp;&amp;' expects its operands to be boolean expressions (either 1 or 0) and returns a boolean value. The bitwise and operator '&amp;' work on Inte
4 min read
Check if array elements are consecutive in O(n) time and O(1) space (Handles Both Positive and negative numbers)
Given an unsorted array of distinct numbers, write a function that returns true if array consists of consecutive numbers. Examples : Input : arr[] = {5, 4, 2, 1, 3} Output : Yes Input : arr[] = {2, 1, 0, -3, -1, -2} Output : YesRecommended: Please solve it on “PRACTICE ” first, before moving on to the solution. We have discussed three different app
6 min read
Minimum number with digits as 4 and 7 only and given sum
Lucky numbers are the positive integers whose decimal representations contain only the lucky digits 4 and 7. What minimum lucky number has the sum of digits equal to n. Examples: Input : sum = 11 Output : 47 Sum of digits in 47 is 11 and 47 is the smallest number with given sum. Input : sum = 10 Output : -1 Recommended PracticeLucky number and a su
6 min read
Maximize sum of squares of array elements possible by replacing pairs with their Bitwise AND and Bitwise OR
Given an array arr[] consisting of N integers, the task is to find the maximum sum of the squares of array elements possible from the given array by performing the following operations: Select any pair of array elements (arr[i], arr[j])Replace arr[i] by arr[i] AND arr[j]Replace arr[j] by arr[i] OR arr[j].Examples: Input: arr[] = {1, 3, 5}Output: 51
14 min read
Data Structures and Algorithms Online Courses : Free and Paid
Data Structures and Algorithms is one of the most important skills that every computer science student must-have. It is often seen that people with good knowledge of these technologies are better programmers than others and thus, crack the interviews of almost every tech giant. Now, you must be thinking to opt for a quality DSA Course to build
7 min read
INT_MAX and INT_MIN in C/C++ and Applications
Most of the time, in competitive programming, there is a need to assign the variable, the maximum or minimum value that data type can hold, but remembering such a large and precise number comes out to be a difficult job. Therefore, C/C++ has certain macros to represent these numbers, so that these can be directly assigned to the variable without ac
7 min read
Change/add only one character and print '*' exactly 20 times
In the below code, change/add only one character and print '*' exactly 20 times. int main() { int i, n = 20; for (i = 0; i &lt; n; i--) printf("*"); getchar(); return 0; } Solutions:1. Replace i by n in for loop's third expression C/C++ Code #include &lt;iostream&gt; using namespace std; int main() { int i, n = 20; for (i = 0; i &lt; n; n--) cout
5 min read
Return values of printf() and scanf() in C/C++
What values do the printf() and scanf() functions return ? printf() : It returns total number of Characters Printed, Or negative value if an output error or an encoding error Example 1: The printf() function in the code written below returns 6. As 'CODING' contains 6 characters. C/C++ Code // C/C++ program to demonstrate return value // of printf()
2 min read
What is return type of getchar(), fgetc() and getc() ?
In C, return type of getchar(), fgetc() and getc() is int (not char). So it is recommended to assign the returned values of these functions to an integer type variable. char ch; /* May cause problems */ while ((ch = getchar()) != EOF) { putchar(ch); } Here is a version that uses integer to compare the value of getchar(). int in; while ((in = getcha
1 min read
Write one line functions for strcat() and strcmp()
Recursion can be used to do both tasks in one line. Below are one line implementations for stracat() and strcmp(). /* my_strcat(dest, src) copies data of src to dest. To do so, it first reaches end of the string dest using recursive calls my_strcat(++dest, src). Once end of dest is reached, data is copied using (*dest++ = *src++)? my_strcat(dest, s
2 min read
Data type of character constants in C and C++
In C, data type of character constants is int, but in C++, data type of same is char. If we save below program as test.c then we get 4 as output (assuming size of integer is 4 bytes) and if we save the same program as test.cpp then we get 1(assuming size of char is 1 byte) C/C++ Code // C++ program demonstrating that data type of character // const
1 min read
Can We Use Function on Left Side of an Expression in C and C++?
In C, it is not possible to have function names on the left side of an expression, but it's possible in C++. How can we use the function on the left side of an expression in C++? In C++, only the functions which return some reference variables can be used on the left side of an expression. The reference works in a similar way to pointers, so whenev
1 min read
Practice Tags :