Do Local Variables and Function Prototypes in a C Program Produce any Assembly Code

In C programming, function prototypes and local variables are fundamental. Function prototypes declare the interface of functions, while local variables store temporary data within functions. Understanding their impact on assembly code helps in writing efficient programs and debugging at the assembly level.

What are Function Prototypes in C?

A function prototype is a declaration that specifies a function’s name, return type, and parameter types—without providing its body. For example:

int add(int a, int b);

This declaration informs the compiler about the function’s interface and enables type checking during compilation.

Do Function Prototypes Generate Assembly Code?

Function prototypes themselves do not generate assembly code. They serve as declarations, allowing the compiler to verify function usage. Only when a function is defined does the compiler generate corresponding assembly instructions.

What are Local Variables in C?

Local variables are declared within functions and are accessible only within their scope. For example:

advertisement
void quiz() {
    int score = 0;
}

In this case, score is a local variable accessible only within the function quiz().

Do Local Variables Generate Assembly Code?

Local variables may generate assembly code depending on their usage:

Free 30-Day C Certification Bootcamp is Live. Join Now!
  • Unused Local Variables: If you declare a variable but don’t use it, modern compilers often remove it during optimization. In that case, the compiler won’t generate any assembly code for it.
  • Used Local Variables: When you use a local variable, the compiler sets aside space—usually on the stack—and creates assembly instructions to manage its value.

Assembly Code Generation

Function Prototypes

As declarations, function prototypes do not produce assembly code. They guide the compiler during the compilation process but have no direct representation in the generated assembly.

Local Variables

When local variables are used, the compiler generates assembly code to allocate space and manage their values.

Example 1: Only Declarations (No Initialization)

void lvar_funpt() {
    long a1, a2, a3, a4, a5, a6,
         a7, a8, a9, a10;
 
    int *pi1, *pi2, *pi3, *pi4, *pi5,
        *pi6, *pi7, *pi8, *pi9, *pi10;
 
    fun_ret_ptr();
    fun_ret_int();
}

Corresponding x86-64 Assembly (GCC or Clang):

lvar_funpt:
    pushq   %rbp
    movq    %rsp, %rbp
    movl    $0, %eax
    call    fun_ret_ptr
    movl    $0, %eax
    call    fun_ret_int
    popq    %rbp
    ret

Observation: No assembly instructions were generated for any of the declared variables or function prototypes. Only the function calls appear in the output.

Example 2: Declarations with Initialization

advertisement
void lvar_funpt() {
    long a1 = 10, a2 = 20, a3 = 30, a4 = 40, a5 = 50;
    int *pi1 = (int *)100;
    int *pi2 = (int *)200;
 
    fun_ret_ptr();
    fun_ret_int();
}

Corresponding x86-64 Assembly:

lvar_funpt:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $64, %rsp
    movq    $10, -8(%rbp)
    movq    $20, -16(%rbp)
    movq    $30, -24(%rbp)
    movq    $40, -32(%rbp)
    movq    $50, -40(%rbp)
    movq    $100, -48(%rbp)
    movq    $200, -56(%rbp)
    movl    $0, %eax
    call    fun_ret_ptr
    movl    $0, %eax
    call    fun_ret_int
    leave
    ret

Observation: Now you see specific instructions that allocate space on the stack and assign values to variables. This proves that only used or initialized local variables impact the generated assembly.

Example 3:

int sum(int a, int b) {
    int result = a + b;
    return result;
}

A possible assembly translation might look like:

sum:
    push    rbp
    mov     rbp, rsp
    mov     DWORD PTR [rbp-4], edi
    mov     DWORD PTR [rbp-8], esi
    mov     eax, DWORD PTR [rbp-4]
    add     eax, DWORD PTR [rbp-8]
    pop     rbp
    ret

In this assembly code:

  • push rbp and mov rbp, rsp set up the stack frame.
  • the mov DWORD PTR [rbp-4], edi stores the first parameter.
  • mov DWORD PTR [rbp-8], esi stores the second parameter.
  • mov eax, DWORD PTR [rbp-4] and add eax, DWORD PTR [rbp-8] compute the sum.
  • pop rbp and ret clean up and return.

This demonstrates how local variables and operations on them are represented in assembly.

How to View Assembly Code

You can inspect assembly output with these commands:

gcc -S -O2 test.c -o test.s      # Using GCC
clang -S -O2 test.c -o test.s    # Using Clang

These commands generate a .s file containing the assembly code.

Sanfoundry Global Education & Learning Series – 1000 C Tutorials.

If you wish to look at all C Tutorials, go to C Tutorials.

advertisement
advertisement
Subscribe to our Newsletters (Subject-wise). Participate in the Sanfoundry Certification contest to get free Certificate of Merit. Join our social networks below and stay updated with latest contests, videos, internships and jobs!

Youtube | Telegram | LinkedIn | Instagram | Facebook | Twitter | Pinterest
Manish Bhojasia - Founder & CTO at Sanfoundry
Manish Bhojasia, a technology veteran with 20+ years @ Cisco & Wipro, is Founder and CTO at Sanfoundry. He lives in Bangalore, and focuses on development of Linux Kernel, SAN Technologies, Advanced C, Data Structures & Alogrithms. Stay connected with him at LinkedIn.

Subscribe to his free Masterclasses at Youtube & discussions at Telegram SanfoundryClasses.