Can we Declare Function Inside Structure Of C Programming?

Answer: NO

An example program in C language:

// Example 1

int var_Global;

void main ( )

{

var_Global = 5;

} 

In the above program a global variable var_Global is declared of integer type. This global variable is used in the main ( ) section. When a C language program is executed, the Compiler of C language acquires a calculated amount of memory to execute programming instructions.

C compiler in association with Operating system bifurcate program into three sections and allocate memory accordingly. Program bifurcation is given in Figure 1 below:

Code

Data

Stack

C compilers use stack regions to maintain memory addresses allocated to C programs. Working of the stack can be understood by taking following example:

// Example 2

void uderstanding_fun ( )
{
   int local_variable = 0;
   local_variable++;
} 

Code Analysis

 
Understanding_fun:
                     	stacktop = stacktop-4;
                     	stacktop[0] = 0;
                     	stacktop[0]++;
                     	stacktop = stacktop+4
                  	return

When the execution of the function begins, stacktop points to the top of the stack. Then stacktop is decreased by 4 bytes. These 4 bytes are used by local variables declared in the function. When the function execution ends, stacktop attains the same position which it was before the execution of the function begins.

In this code only one variable is used named as local_variable  stacktop is decreased by 4 bytes. If other variables were also used then stacktop would have decreased accordingly to store them in memory.

Compiler converts the C program into the assembly code. Assembly code for the above C program is given below:

//Assembly Code for Example 2

Understanding_fun:
                              psuh_l   %ebp_register
                              mov_l	%esp_register, %ebp_register
                              Sub_l 	$16, %esp_register
                              mov_l     $0, -4(%ebp_register)
                             	add_l   	$, -4(%ebp_register)
                             	laeve
                             	ret

Assembly Code Analysis of Example -1

# function begins with 

Understanding_fun:

# store ebp_register on stack. This is done by following assembly code statement:

                           push_l %ebp_register

When the function execution ends ebp_register attains the value which it was before the execution of the function Understanding_fun begins. 

# next stack pointer points to ebp_register.

                              mov_l %esp, %ebp

# decrease the stack pointer by 4 bytes as the size of the local variable is of integer type. This is done by following assembly code instructions:

                              sub_l  $16, %esp

By decreasing the stack pointer memory space is created to store declared  variables inside the function. Now integer variables occupy 4 bytes of memory. But in the assembly code 16 bytes are saved because the C compiler may use this memory if required during function execution.

Next, memory is allocated to declared local_variable and set to 0 by executing following assembly code instruction:

                              mov_l $0, -4(%ebp)

local_variable is incremented by executing following assembly code instruction:

                                             add_l $1. -4(%ebp)

At the end of the execution of  the function registered stored to there previous values.

Function Call

An example C language code for function call:

// Example 3

void stk_fun( )
{
   	int x = 0;
   	x++;
}
int main ( )
{
   	stk_fun( );
}

// Example 3 assembly code

.text

.global stk_fun

 

stk_fun:

 

            push_l   %ebp_register

                 mov_l     %esp_register, %ebp_register

                 sub_l       $0, -4(%ebp_register)

            mov_l $1, -4(%êbp_register)

                 laeve

              ret

  

.global main

 

main:

 

              push_l   %ebp_register

                               mov_ %esp_register, %ebp_register

                             call        stk_fun

                              pop_l    %ebp_register

                             

                              ret

 

// Code analysis for Assembly Code of example 3

 

Function of the C language is stored in the text section of the memory occupied by the C compiler. This done by executing following programming instructions:

# .text segment begins                          

                                          .text

Function stk_fun is exported by following assembly code statement

                                          .globl  stk_fun

Function stk_fun begins: 

stk_fun:

         push_l   %ebp_register

             mov_l %esp_register, %ebp_register

         sub_l  $16, %esp_register

          mov_l  $0, -4(%ebp_register)

          add_l   $1, -4(%ebp)

            leave

            ret

Then function stk_fun will be exported by executing following assembly code instructions:

                                       .globl  stk_fun

main function begins by the following assembly code instructions:

main:

     push_l     %ebp_register

          mov_l   %esp_register, %ebp_register

main function execute the following assembly code to function stk_fun                      

                                                         call fun

When execution of the function stk_fun ends all assembly language registers are set to default values.

 

                                                       popt %ebp_register

                                                       ret 

“call” assembly language instruction is used to call functions in C language, when a call is made the next instruction address is pushed into the stack. The function in assembly language is kept in the text section denoted by .text.

When the execution of the code is completed control is returned back to the main function. This is done by executing the ret statement of the assembly language. ret statement gets the return address from the stack. ret statement pops the address from the stack then goes to that address.

Structure and Compiler generated Assembly language Code

Structures in C language are used to store data of heterogeneous type. Structure contains data members and is accessed using the dot operator. Compiler allocates memory to structure when its object is created. Structure also shares contiguous memory allocation.

Amount of memory allocated to the structure is the sum of the memory allocated to each of the structure members. Since data members are of different data types, the compiler separates them using paddings. Compiler does padding to make access of data members faster.

Compilers use base address of structure to access structure data members. 

C language program to declare structure

//Example 4

#include <stdio.h>
 
struct data_struct
{
	int a;
    int b;
};
void display();
struct data_struct global_data;
int main()
{
	struct data_struct local_data;
	global_data.a = 10;
	global_data.b = 15;
	local_data.a = 25;
	local_data.b = 20;
	
	printf("\n");
	printf("The value of local variable 'a' in main is: %d", local_data.a);
	printf("\n");
	printf("The value of local variable 'b' in mian is: %d", local_data.b);
	printf("\n");
	
	display();
	
	return 0;
}
 
void display()
{
	
	printf("\n");
	printf("The value of global variable 'a' in display function is: %d", global_data.a);
	printf("\n");
	printf("The value of global variable 'b' in display function is : %d", global_data.b);
	printf("\n");
	
}

Output:

The value of local variable 'a' in main is: 25
 
The value of local variable 'b' in mian is: 20
 
The value of global variable 'a' in display function is: 10
 
The value of global variable 'b' in display function is : 15

Assembly code for Example 4

 

  .comm global_data 8,4
   .text
  
.global main
 
main:
    	push_l  %ebp_register
   	mov_l   %esp_register, %ebp_register
   	sub_l    $16, %esp_register
   	mov_l   $10, global_data
   	mov_l   $15, global_data+4
  	mov_l   $25, -8(%ebp_register)
  	mov_l   $20, -4(%ebp)
  	mov_l   $0, %eax_register
  
  	Leave
  	
  	ret

Offset of data member “a” and data member “b” of the data_struct structure
a ⇒ 0
b ⇒ 4
global _data will access structure members as:
global_data.a ⇒ global_data+0 or only global_data
global_data.b ⇒ global_data+4
In the same way local data members will be accessed as:
local_data.a ⇒ -8(%ebp_register)
local_data.b ⇒ -4(%ebp)

Code Analysis of Example 4

In assembly code of example 4 structure data_struct is declared with tag .comm and this is used to specify that data members of structure data_struct will hold memory space in the data section of the total memory space held by the compiler to execute example 4.
But assembly code of example 3 begins with .text that specify that example 3 contains a function.
Compiler has a definition that variables or data members should be declared in the data section and function should be declared in the code section identified by .text.
It is because of this reason that structure can not have function within them.

If a function is defined in the structure what will happen

What will happen if function is declared in structure this can be understood by following program:

Function within structure

//Example 5

#include <stdio.h>
 
struct Student_Data
{
	char *student_name;
	int student_id;
	int student_age;
	void add();
};
 
void add( )
{
	int a,b;
	int sum = 0;
	printf("Input value of a ");
	scanf("%d", &a);
	printf("Input value of b");
	scanf("%d", &b);	
	sum = a+b;
	
	printf("Total Sum is =%d", sum);
}
 
int main( )
{
 	
 	struct Student_Data stu;
 	
 	stu.student_name = "Involve";
 	stu.student_id = 12346;
 	stu.student_age = 300;
 
 	
 	printf("Name of Student is: %s", stu.student_name);
 	printf("\n Id of Student is: %d", stu.student_id);
 	printf("\n Age of Student is: %d", stu.student_age);
 	return 0;
 }

Output:

main.c:8:10: error: field ‘add’ declared as a function
 	void add();
    	^~~

Code Analysis

As it can be seen from the code output that the error is field ‘add’ declared as function.
Anything declared within a structure is treated as a field that is data members and data members are allocated memory in the data section and in the code section functions are allocated memory out of the total memory allocated to the compiler for the execution of the program.

What will happen if the function is defined in the structure

 //Example 6

#include <stdio.h>
 
struct Student_Data
{
	char *student_name;
	int student_id;
	int student_age;
	void add()
	{
    	int a,b;
	int sum = 0;
	
	printf("Input value of a ");
	scanf("%d", &a);
	
	printf("Input value of b");
	scanf("%d", &b);
	
	sum = a+b;
	
	printf("Total Sum is =%d", sum);
	}
};
 
int main()
{
 	
 	struct Student_Data stu; 	
 	stu.student_name = "Involve";
 	stu.student_id = 12346;
 	stu.student_age = 300;
 	printf("Name of Student is: %s", stu.student_name);
 	printf("\n Id of Student is: %d", stu.student_id);
 	printf("\n Age of Student is: %d", stu.student_age);
 	return 0;
 	
}

Output:

error: expected ';' at end of declaration list
	void add()
 
error: expected ';' at end of declaration list
	void add()

Code Analysis

Above code ends with 2 errors. In the first error the compiler considers the add function as a list.
 
In the second error the compiler considers as a field is expecting semicolon (;).

Conclusion

From the discussion it is evident that structure cannot have function within it because of two reasons, first, it is allocated memory space in the data section and not in the code section, second, data members declared in structure are considered as a field and field is the term associate with class and C compiler does not have grammar for class so structure does support function either declared or defined in structure.