Skip to content

my_printf implements a custom version of the printf() function in C without using the stdio.h or stdarg.h libraries. Instead, the code manually manages variable-length arguments (variadic functions) and provides custom implementations of basic input/output functions like putchar and puts, using low-level system calls.

Notifications You must be signed in to change notification settings

shreejaykurhade/my_printf

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 

Repository files navigation

📘 Variadic Arguments in C – Custom Implementation & Logic

📌 Introduction

In C programming, variadic functions are functions that accept a variable number of arguments. The most common example is the printf() function. While the standard implementation uses <stdarg.h>, it is possible to replicate the variadic argument mechanism using pointer arithmetic and custom macros.

This document explains how variadic arguments work in C and demonstrates a complete, low-level implementation of a custom printf() function, including manual memory management and format parsing.


📚 Theory: How Variadic Arguments Work

✅ What Are Variadic Functions?

A variadic function can accept a varying number of arguments. In C, such functions declare their fixed parameters followed by ... to indicate additional arguments.

Example:

int printf(const char *format, ...);

📦 The Role of <stdarg.h>

C provides a standard library header <stdarg.h> with these key macros:

  • va_list – type to hold the variable argument list
  • va_start – initializes the argument list
  • va_arg – retrieves the next argument
  • va_end – cleans up the list

🔧 Manual Implementation (Without <stdarg.h>)

🔁 Custom Macro Definitions

typedef char* va_list;

#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
#define va_start(ap, v) (ap = (va_list)&v + _INTSIZEOF(v))
#define va_arg(ap, type) (*(type *)((ap += _INTSIZEOF(type)) - _INTSIZEOF(type)))
#define va_end(ap) (ap = (va_list)0)

🧠 How It Works

  • va_list is simply a char* pointer used to traverse the argument list.
  • _INTSIZEOF(n) ensures proper alignment by rounding the size up to a multiple of int.
  • va_start(ap, v) sets the va_list to the first variadic argument (after parameter v).
  • va_arg(ap, type) retrieves the next argument and advances the pointer.
  • va_end(ap) resets the pointer to NULL.

This simulates what the compiler and <stdarg.h> do behind the scenes.


🖨️ Custom printf() Logic

🔍 Format Parsing

The printf() function parses a format string containing specifiers like %d, %f, %s, etc. It handles each character:

  • If it's a regular character, it is printed.
  • If it’s %, the next character determines how to interpret the argument.

🔄 Argument Fetching

Each specifier uses va_arg() to fetch the correct type:

int x = va_arg(args, int);       // for %d
char *str = va_arg(args, char*); // for %s

🔤 Conversion Functions

These helper functions convert arguments to printable strings:

  • itoa(int, char*) → Integer to string
  • utoa(unsigned int, char*) → Unsigned integer
  • itoh(unsigned int, char*, int) → Hexadecimal
  • itoo(unsigned int, char*) → Octal
  • ftoa(double, char*, int) → Floating point

🧪 Example Output

printf("Integer: %d\n", 12345);
printf("Hex: %x\n", 255);
printf("Float: %f\n", 3.14);
printf("Char: %c\n", 'A');

Output:

Integer: 12345
Hex: ff
Float: 3.140000
Char: A

All achieved without using stdio.h.


📦 Memory Management

The implementation includes a mini malloc() using a fixed-size heap:

#define HEAP_SIZE 1024
static char heap[HEAP_SIZE];

This enables dynamic string generation and storage during formatting.


🧵 Summary

  • Variadic functions allow flexible interfaces like printf().
  • Behind the scenes, va_list and pointer arithmetic traverse arguments.
  • Manual implementations are valuable for understanding calling conventions and memory layout.
  • This low-level approach is foundational in systems programming and embedded systems.

🔗 Related Concepts

  • Stack memory layout
  • Calling conventions (ABI)
  • Format string vulnerabilities
  • __builtin_va_list in GCC

🛠️ Compile & Run

To compile the full implementation:

gcc -o my_printf custom_printf.c
./my_printf

🧑‍💻 Author

Crafted with ❤️ by a low-level C enthusiast exploring the internals of printf().

About

my_printf implements a custom version of the printf() function in C without using the stdio.h or stdarg.h libraries. Instead, the code manually manages variable-length arguments (variadic functions) and provides custom implementations of basic input/output functions like putchar and puts, using low-level system calls.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages