Internal Linkage And External Linkage In C

Internal Linkage And External Linkage In C

In the world of C programming, we need to understand how variables and functions are connected within our code. Two important ideas in this context are “Internal Linkage” and “External Linkage.” These concepts determine where variables and functions can be used and shared in a C program. In simple terms, we’ll explore what Internal Linkage and External Linkage mean in C and how they affect your code, offering guidance on managing variables and functions effectively. Let’s dive into these concepts in C programming!

Definitions

Scope: Scope refers to where in a program an identifier can be directly accessed. In C, all identifiers follow lexical (or static) scoping.

Linkage: Linkage, on the other hand, is about whether names can refer to the same thing across the entire program or within a single translation unit.

Translation Unit: A translation unit is like a package containing source code, header files, and other dependencies. These elements are bundled together to form a single translation unit, which the compiler uses to create a single executable object. It’s crucial to link these sources together effectively. For example, the compiler needs to know that the definition of “printf” can be found in the “stdio” header file.

So, while scope deals with where identifiers can be used, linkage is about how names can refer to the same thing across the program or a translation unit.

Note :

In C and C++, when you have a program made up of multiple source code files, each file is compiled one by one. During the compilation process, variables are described by their scope, which is handled by the compiler. However, it’s only when the linking process begins that the concept of linkage becomes important. So, scope is a property managed by the compiler, while linkage is a property managed by the linker.

The Linker, in the linking stage of the compilation process, brings all the program’s resources together. It’s like a program that takes multiple machine code files as input and generates an executable object code. The Linker’s job includes resolving symbols (like finding the definitions of symbols such as “+”) and organizing objects in the program’s memory address space.

What is Linkage

Linkage in programming refers to how variables and symbols are connected or linked together by the linker during the compilation process. It determines whether a variable or function can be used across different parts of a program or within a single translation unit. Linkage is an important concept in ensuring the correct organization and functioning of a program.

Types Of Linkage

Internal Linkage: Internal linkage in programming means that an identifier is not accessible from outside the translation unit in which it is declared. However, any identifier within the same unit can access an identifier with internal linkage. Internal linkage is achieved by using the “static” keyword. Identifiers with internal linkage are stored in a segment of RAM, whether it’s initialized or uninitialized. It’s important to note that the term “static” can have different meanings in reference to both linkage and scope in programming, but here we’re focusing on linkage.

Example

// 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 an identifier animals. We have to 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;
}

Output

5 8 2

Then, we have to 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".
Suppose Wash. cpp is 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 will get output as

output : 5 8
having fun washing!
10

In a situation where you have three translation units (Animals, Feed, and Wash) using the “animals” code, each translation unit has its own copy of the “animals” identifier. This is why you observe different values for “animals” in each translation unit: 8 for Animals.cpp, 2 for Feed.cpp, and 10 for Wash.cpp. Each translation unit maintains its own separate instance of the “animals” variable.

This behavior can consume memory and potentially decrease performance, especially if multiple copies of the same data are being stored in different parts of the program.

It’s important to note that internal linkage is applied when a variable has global scope, and all constants are by default internally linked. This means that variables with internal linkage are not visible outside their translation unit and are not shared across different parts of the program.

Internal linkage serves a useful purpose in managing the organization of functions and variables within a program. When a variable has internal linkage, it is passed by copy. This means that if a header file contains a function, let’s say “fun1(),” and the source code in which it’s included also defines “fun1()” with a different implementation, there won’t be a conflict. This is because these two functions with internal linkage are independent of each other within their respective translation units.

This feature allows us to use internal linkage to hide translation-unit-local helper functions from the global scope. For example, you might include a header file containing a method to read input from the user in a file that also describes another method to read input. These two functions, with internal linkage, remain separate and don’t interfere with each other when linked together in the final program. This helps keep the code organized and reduces the likelihood of naming conflicts.

External Linkage :

External linkage in programming means that an identifier is visible to every translation unit, or in other words, it’s visible throughout the entire program. Externally linked identifiers are shared between different parts of the program and are considered to exist at the outermost level of the program. For an externally linked identifier, there must be only one visible definition in the entire program. This means that you need to define it in a place that’s visible to all parts of the program so that there’s only a single definition.

External linkage is the default linkage for globally scoped variables and functions. When you use the “extern” keyword, you’re telling the linker to look for the definition of the identifier elsewhere. Therefore, the declaration of an externally linked identifier doesn’t occupy any space.

Externally linked identifiers are typically stored in the initialized/uninitialized or text segment of the computer’s memory (RAM). This allows them to be accessible and shared across different parts of the program, ensuring that all instances of a particular identifier with external linkage refer to the same identifier in the program.

Example

// 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 within the function “foo,” even though it is declared as an extern variable. It’s important to understand that the concept of scope is primarily used during the compilation phase of a program. After the program is compiled, there is no concept of “scope of variable.”

During compilation, the compiler takes into account the scope of “b.” In this case, “b” has local scope within the “foo()” function. When the compiler encounters the extern declaration, it assumes that there is a definition of “b” somewhere else and defers the task of finding it to the linker.

However, when the compiler processes the “bar()” function, it attempts to locate the variable “b.” Since “b” has been declared as extern, it hasn’t been assigned memory by the compiler; it essentially doesn’t exist yet at this stage. The compiler relies on the linker to locate the definition of “b” within the translation unit and then assign it the value specified in that definition. Only after this process does “b” come into existence with memory allocated.

But, because there’s no declaration for “b” within the scope of “bar()”—neither within the function nor in the global scope—the compiler encounters an error. It’s the compiler’s responsibility to ensure that all variables are used within their respective scopes, and when it encounters “b” in “bar()” without a matching declaration, it raises an error and halts the compilation process.

To resolve this issue, you can make “b” a global variable by moving line 1 (the extern declaration) to a location before the definition of the “foo()” function. This makes “b” accessible in both “foo()” and “bar()” functions.

FAQ- Internal Linkage And External Linkage In C

Q1. What is an internal linkage in C language?

Ans. An identifier with internal linkage is only accessible within the translation unit where it’s declared. Any identifier within the same unit can access an identifier with internal linkage. This linkage is established using the “static” keyword in C or C++.

Q2. What is external linkage in C programming?

Ans. In C, all global identifiers inherently have external linkage by default. This means that every declaration of a particular identifier with external linkage refers to the same object or function throughout the entire program. The “extern” keyword is used to explicitly establish external linkage for variables and functions in C.

Q3. What are the different types of linking in C?

Ans. Linking in software development comes in two flavors: Static Linking and Dynamic Linking.
Static Linking: The linker incorporates library code directly into the executable, making the program self-contained. It ensures the program runs independently but can result in larger files.
Dynamic Linking: Programs use external libraries at runtime instead of including them in the executable. It reduces disk space but requires libraries on the target system. The choice depends on factors like portability and resource usage.

Hridhya Manoj

Hello, I’m Hridhya Manoj. I’m passionate about technology and its ever-evolving landscape. With a deep love for writing and a curious mind, I enjoy translating complex concepts into understandable, engaging content. Let’s explore the world of tech together

Leave a Comment