Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

C Programming: Core Syntax, Memory Architecture, and Systems-Level Implementation

Tech May 13 1

1. Standard Library Headers and I/O Fundamentals

The C standard library exposes functionality through modular headers. <stdio.h> provides stream-oriented input/output operations, while <stdlib.h> contains utility functions for memory allocation, random number generation, and system command exceution.

Formatted Output with printf

The printf funciton writes formatted text to standard output. Format specifiers control how arguments are interpreted:

#include <stdio.h>

int main(void) {
    int signed_val = -255;
    unsigned int unsigned_val = 4000000000U;
    double pi = 3.14159265359;
    char letter = 'A';
    char phrase[] = "Memory safety";
    void *addr = &signed_val;
    
    printf("Decimal signed: %d\n", signed_val);
    printf("Decimal unsigned: %u\n", unsigned_val);
    printf("Hexadecimal: %X\n", 0xABCD);
    printf("Octal: %o\n", 077);
    printf("Float precision: %.2f\n", pi);
    printf("Scientific: %e\n", 6.022e23);
    printf("Character: %c\n", letter);
    printf("String: %s\n", phrase);
    printf("Memory address: %p\n", addr);
    
    return 0;
}

Width specifiers enable field alignment. A positive width right-justifies; a negative width left-justifies:

printf("[%10d]\n", 42);    /* Right-aligned in 10 chars */
printf("[%-10d]\n", 42);   /* Left-aligned in 10 chars */
printf("[%05d]\n", 42);    /* Zero-padded to 5 digits */

Escape Sequences and Special Characters

Non-printable characters require escape notation:

  • \\ - Literal backslash
  • \' - Single quote within character literals
  • \" - Double quote within string literals
  • \n - Newline (line feed)
  • \t - Horizontal tab (typically 8-column alignment)
  • \xNN - Hexadecimal value (e.g., \x41 for 'A')
  • \NNN - Octal value (e.g., \101 for 'A')

Trigraph sequences (??=, ??(, etc.) map to single characters for legacy character set compatibility, though modern compilers often require explicit flags to recognize them.

Formatted Input with scanf

scanf parses standard input using format specifiers. It requires memory addresses for storage:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void) {
    int age;
    float salary;
    char name[50];
    
    printf("Enter age, salary, and name: ");
    scanf("%d %f %s", &age, &salary, name);
    
    printf("Received: %d years, $%.2f, %s\n", age, salary, name);
    return 0;
}

Note that array names decay to pointers, so name does not require the address-of operator (&), whereas scalar variables do.

Utility Functions in stdlib.h

Random Number Generation:

rand() generates pseudo-random integers in the range [0, RAND_MAX]. To avoid identical sequences across executions, seed the generator with srand():

#include <stdlib.h>
#include <time.h>

int main(void) {
    srand((unsigned int)time(NULL));
    
    for (int idx = 0; idx < 5; idx++) {
        printf("Random %d: %d\n", idx, rand() % 100);
    }
    return 0;
}

System Commands:

#include <stdlib.h>

int main(void) {
    system("title C_Demo_Console");
    system("mode con cols=80 lines=25");
    system("cls");
    system("notepad.exe");
    return 0;
}

2. Fundamental Data Types and Representation

C provides integer, floating-point, and character types with platform-dependent but minimum-guaranteed sizes.

Integer Types

Type Typical Size Range (Visual C++)
short 2 bytes -32,768 to 32,767
int 4 bytes -2,147,483,648 to 2,147,483,647
long 4 bytes (Windows) Same as int
long long 8 bytes -9.22e18 to 9.22e18

The standard guarantees: sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long).

Floating-Point Types

  • float: 4 bytes, single precision (approximately 7 decimal digits)
  • double: 8 bytes, double precision (approximately 15 decimal digits)

Character Types

char stores single byte characters (typically ASCII). The signedness of plain char is implementation-defined; use signed char or unsigned char for portability.

Integer literals accept prefixes: 0 for octal (e.g., 017), 0x for hexadecimal (e.g., 0xFF), and modern compilers support 0b for binary (e.g., 0b1010).

3. Operators and Expressions

Arithmetic Operators

Integer division truncates toward zero. To obtain floating-point results, at least one operand must be floating-point:

int a = 7, b = 2;
printf("%d\n", a / b);      /* Outputs: 3 */
printf("%f\n", 7.0 / 2);    /* Outputs: 3.500000 */

When summing harmonic series, force floating-point conversion:

float harmonic = 0.0f;
for (int term = 1; term <= 100; term++) {
    harmonic += 1.0f / term;  /* 1.0f ensures float division */
}

Bitwise Operations

Operators work on two's complement representations:

  • << : Left shift (fills with zeros)
  • >> : Right shift (arithmetic: sign-bit fill for negatives; logical: zero fill for unsigned)
  • & : Bitwise AND (masking)
  • | : Bitwise OR (setting bits)
  • ^ : Bitwise XOR (toggling)
  • ~ : Bitwise NOT (inversion)

Setting and clearing bits:

unsigned int flags = 0x00;
flags |= (1 << 3);       /* Set bit 3 */
flags &= ~(1 << 3);      /* Clear bit 3 */
flags ^= (1 << 3);       /* Toggle bit 3 */

Counting set bits (population count):

int popcount(unsigned int value) {
    int count = 0;
    while (value) {
        value &= (value - 1);  /* Clear least significant set bit */
        count++;
    }
    return count;
}

Shift Operations and Sign Extension

Left shift always fills with zeros. Right shift behavior depends on type:

signed int negative = -8;    /* Binary: ...11111000 */
signed int shifted = negative >> 2;  /* Arithmetic: ...11111110 (remains -2) */

unsigned int positive = 0xFFFFFFF8;
unsigned int logical_shift = positive >> 2;  /* Logical: 0x3FFFFFFE */

Logical Operators

&& and || exhibit short-circuit evaluation:

int x = 0, y = 5;
if (x++ && y++) {  /* y++ never executes because x++ evaluates to 0 (false) */
    /* unreachable */
}

Ternary Operator

The conditional operator ?: returns values, not references, preventing direct assignment to its results:

int val_a = 10, val_b = 20;
int max_val = (val_a > val_b) ? val_a : val_b;  /* Valid */
/* (val_a > val_b) ? val_a : val_b = 30; */     /* Invalid: not an lvalue */

sizeof Operator

sizeof yields the size in bytes of a type or expression. It does not evaluate its operand at runtime:

int buffer[100];
size_t array_size = sizeof(buffer);           /* Total bytes: 400 */
size_t element_size = sizeof(buffer[0]);      /* Single element: 4 */
size_t element_count = sizeof(buffer) / sizeof(buffer[0]);  /* 100 */

int x = 10;
printf("%zu\n", sizeof(x = x + 100));  /* Prints 4; x remains 10 */

Precedence and Associativity

High precedence: postfix operators ([], (), ->, .), unary operators (!, ~, ++, --, *, &, sizeof), multiplicative (*, /, %).

Low precedence: comma operator (,).

Associativity is left-to-right for most binary operators, right-to-left for assignment and unary operators.

4. Variable Scope and Storage Duration

Scope Categories

Block Scope: Variables declared inside {} are accessible only within that block. They contain indeterminate values unless initialized.

File Scope: Variables declared outside functions are accessible throughout the translation unit. They initialize to zero by default.

#include <stdio.h>

int global_counter;  /* File scope, initialized to 0 */

void increment(void) {
    static int persistent = 0;  /* Static storage duration, retains value */
    int local_temp = 0;         /* Automatic storage, recreated each call */
    
    persistent++;
    local_temp++;
    printf("Static: %d, Local: %d\n", persistent, local_temp);
}

int main(void) {
    for (int i = 0; i < 3; i++) {
        increment();
    }
    return 0;
}

Output:

Static: 1, Local: 1
Static: 2, Local: 1
Static: 3, Local: 1

Storage Class Specifiers

  • auto: Implicit for local variables (rarely written explicitly).
  • static: Extends lifetime to program duration; limits visibility for globals to file scope.
  • register: Suggests storage in CPU registers (compiler hint, modern compilers optimize automatically).
  • extern: Declares external linkage, referencing variables defined in other translation units.

5. Constants and Literals

Literal Constants

Immediate values: 42, 3.14, 'X', "String literal".

const Qualifier

Creates read-only variables that occupy memory (unlike preprocessor constants):

const int max_iterations = 1000;
/* max_iterations = 500; */  /* Compile error: read-only */

Enumerations

enum defines named integer constants with automatic increment:

enum StatusCode {
    OK = 200,
    CREATED = 201,
    BAD_REQUEST = 400,
    NOT_FOUND = 404,  /* Subsequent values increment by 1 if unspecified */
    ERROR = 500
};

enum StatusCode current = OK;

Enumerations provide type safety and debugging symbols compared to #define macros.

Preprocessor Constants

#define BUFFER_SIZE 1024
#define PI 3.14159
#define SQUARE(x) ((x) * (x))  /* Macro with parentheses for safety */

Macros perform textual substitution before compilation. Parentheses around parameters and the entire expression prevent operator precedence errors.

6. String Manipulation and Memory Layout

String Representation

C strings are null-terminated character arrays. The null byte '\0' (value 0) marks the end.

char str1[] = "Hello";        /* Array size 6: 'H','e','l','l','o','\0' */
char str2[] = {'H','i'};      /* No null terminator: unsafe for string functions */
char str3[5] = "Test";        /* Exactly fits: 'T','e','s','t','\0' */

String Length and Size

strlen() counts characters until (but not including) the null terminator. sizeof() returns the total memory allocation:

char greeting[] = "Hello";
size_t len = strlen(greeting);    /* 5 */
size_t size = sizeof(greeting);   /* 6 */

Standard String Functions

Copying:

char destination[50];
strcpy(destination, "Source text");  /* Unsafe: no bounds checking */
strncpy(destination, "Limited", 10); /* Safer: max 10 chars */

Concatenation:

strcat(destination, " appended");    /* Appends to end */
strncat(destination, " safe", 5);    /* Appends max 5 chars plus null */

Comparison:

strcmp() returns negative, zero, or positive values based on lexicographical ordering:

if (strcmp(str1, str2) == 0) {  /* Equal strings */
    /* ... */
}

Searching:

strstr() locates substrings; strchr() finds characters.

Memory Manipulation Functions

memcpy() copies raw memory (undefined behavior if regions overlap). memmove() handles overlapping regions safely:

int data[] = {1, 2, 3, 4, 5};
memmove(&data[2], &data[0], 3 * sizeof(int));  /* data becomes {1,2,1,2,3} */

memset() initializes memory to a specific byte value:

int arr[100];
memset(arr, 0, sizeof(arr));  /* Zeroes entire array */

7. Control Flow Structures

Conditional Statements

if-else chains:

int score = 85;
if (score >= 90) {
    grade = 'A';
} else if (score >= 80) {
    grade = 'B';
} else if (score >= 70) {
    grade = 'C';
} else {
    grade = 'F';
}

Avoid chained comparisons like 0 <= x <= 10; use 0 <= x && x <= 10.

switch statements:

enum Color { RED, GREEN, BLUE };
enum Color pixel = GREEN;

switch (pixel) {
    case RED:
        printf("Red channel\n");
        break;
    case GREEN:
        printf("Green channel\n");
        break;
    case BLUE:
        printf("Blue channel\n");
        break;
    default:
        printf("Unknown\n");
        break;
}

Without break, execution falls through to subsequent cases.

Loop Constructs

while loops:

int num = 12345;
int sum_digits = 0;
while (num > 0) {
    sum_digits += num % 10;
    num /= 10;
}

for loops:

for (int i = 0, j = 10; i < j; i++, j--) {
    printf("i=%d, j=%d\n", i, j);
}

Omitting the initialization or increment expressions creates a while-equivalent structure.

do-while loops:

Executes body at least once before checking condition:

int input;
do {
    printf("Enter positive number: ");
    scanf("%d", &input);
} while (input <= 0);

Jump Statements

  • break: Exits innermost loop or switch.
  • continue: Skips to next iteration.
  • return: Exits function, optionally returning value.
  • goto: Transfers control to labeled statement (avoid in structured programming).

8. Functions and Program Flow

Function Declaration and Definition

/* Declaration (prototype) */
double calculate_circle_area(double radius);

/* Definition */
double calculate_circle_area(double radius) {
    return 3.14159 * radius * radius;
}

Parameters are passed by value. Modifications to parameters do not affect arguments. To modify caller variables, pass pointers:

void swap_values(int *px, int *py) {
    int temp = *px;
    *px = *py;
    *py = temp;
}

Recursion

Functions that call themselves require:

  1. Base case (termination condition)
  2. Progress toward base case

Factorial:

unsigned long long factorial(unsigned int n) {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

Fibonacci (inefficient recursive):

unsigned long long fib(unsigned int n) {
    if (n < 2) return n;
    return fib(n - 1) + fib(n - 2);
}

Fibonacci (efficient iterative):

unsigned long long fib_iterative(unsigned int n) {
    if (n < 2) return n;
    unsigned long long prev = 0, curr = 1;
    for (unsigned int i = 2; i <= n; i++) {
        unsigned long long next = prev + curr;
        prev = curr;
        curr = next;
    }
    return curr;
}

Function Pointers and Callbacks

Function pointers enable polymorphic behavior and callbacks:

#include <stdio.h>
#include <stdlib.h>

int compare_ascending(const void *a, const void *b) {
    int arg1 = *(const int*)a;
    int arg2 = *(const int*)b;
    return (arg1 > arg2) - (arg1 < arg2);
}

int main(void) {
    int dataset[] = {64, 34, 25, 12, 22, 11, 90};
    size_t n = sizeof(dataset) / sizeof(dataset[0]);
    
    qsort(dataset, n, sizeof(int), compare_ascending);
    
    for (size_t i = 0; i < n; i++) {
        printf("%d ", dataset[i]);
    }
    return 0;
}

9. Arrays and Pointer Arithmetic

Array Fundamentals

Arrays store contiguous elements of the same type:

int matrix[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

Initialization omits elements default to zero:

int sparse[10] = {1, 2};  /* Index 0=1, 1=2, rest=0 */

Array-Pointer Relationship

Array names decay to pointers to the first element in most expressions:

int arr[5] = {10, 20, 30, 40, 50};
int *p = arr;        /* Equivalent to &arr[0] */

printf("%d\n", arr[2]);    /* Array indexing */
printf("%d\n", *(arr + 2)); /* Pointer arithmetic */
printf("%d\n", p[2]);       /* Pointer indexing */
printf("%d\n", 2[arr]);    /* Unconventional but valid: *(2+arr) */

Pointer arithmetic scales by the size of the pointed-to type:

int *ip = arr;
ip++;  /* Advances by sizeof(int) bytes */

Array Parameters

When passed to functions, arrays decay to pointers. The called function cannot determine the array size:

void process_array(int *buffer, size_t length) {
    for (size_t idx = 0; idx < length; idx++) {
        buffer[idx] *= 2;
    }
}

/* Call: */
process_array(data, sizeof(data) / sizeof(data[0]));

For 2D arrays, column size must be specified:

void print_matrix(int rows, int cols, int mat[][4]) {
    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < cols; c++) {
            printf("%d ", mat[r][c]);
        }
        printf("\n");
    }
}

10. Advanced Pointer Concepts

Pointer Types and Void Pointers

void* represents a generic pointer type that can point to any data type. It cannot be dereferenced without casting:

void *generic = malloc(sizeof(double));
double *dp = (double*)generic;
*dp = 3.14159;

Pointer to Pointers

Used for dynamic 2D arrays or modifying pointer values:

int value = 42;
int *ptr = &value;
int **pptr = &ptr;

printf("%d\n", **pptr);  /* Dereferences twice to reach value */

Complex Declarations

Reading right-to-left (or using the "Clockwise/Spiral Rule"):

int *arr[10];        /* Array of 10 pointers to int */
int (*arr)[10];      /* Pointer to array of 10 ints */
int (*func)(int);    /* Pointer to function taking int, returning int */
int (*arr_func[5])(int); /* Array of 5 function pointers */

Dynamic Memory Allocation

#include <stdlib.h>

/* Single object */
int *single = malloc(sizeof(int));
*single = 100;
free(single);
single = NULL;

/* Array */
size_t count = 100;
int *dynamic_arr = calloc(count, sizeof(int));  /* Zero-initialized */
if (dynamic_arr == NULL) { /* Handle error */ }

/* Resize */
count *= 2;
int *resized = realloc(dynamic_arr, count * sizeof(int));
if (resized != NULL) {
    dynamic_arr = resized;
}

Common errors:

  • Dereferencing NULL
  • Using memory after free (dangling pointer)
  • Double-free
  • Memory leaks (losing pointer to allocated memory)

11. Memory Storage and Endianness

Memory Organization

Program memory segments:

  • Stack: Local variables, function parameters, return addresses. Grows downward.
  • Heap: Dynamically allocated memory. Grows upward.
  • Data: Global and static variables (initialized and uninitialized/BSS).
  • Text: Program code (read-only).

Endianness

Little-endian (x86, ARM): Least significant byte at lowest address. Big-endian (Network protocols, some RISC): Most significant byte at lowest address.

Detection:

int check_endianness(void) {
    union {
        int i;
        char c[sizeof(int)];
    } test;
    test.i = 1;
    return (test.c[0] == 1);  /* True if little-endian */
}

Integer Representation

Signed integers use two's complement:

  • Positive: Standard binary
  • Negative: Invert bits, add 1

Range of signed n-bit integer: [-2^(n-1), 2^(n-1) - 1] Unsigned range: [0, 2^n - 1]

Floating-Point Representation (IEEE 754)

Single-precision (32-bit) format:

  • 1 bit: Sign (S)
  • 8 bits: Exponent (E, biased by 127)
  • 23 bits: Mantissa/Significand (M, implicit leading 1)

Value = (-1)^S × 1.M × 2^(E-127)

Special values: E=0 (denormalized), E=255 (infinity/NaN).

12. Structures, Unions, and Bit-Fields

Structures

Aggregate types combining heterogeneous data:

struct PacketHeader {
    uint16_t source_port;
    uint16_t dest_port;
    uint32_t sequence_num;
    uint32_t ack_num;
    uint8_t data_offset;
    uint8_t flags;
    uint16_t window_size;
};

struct PacketHeader tcp_hdr = {
    .source_port = 8080,
    .dest_port = 443,
    .sequence_num = 1000
};

Memory Alignment

Compilers insert padding to satisfy alignment requirements:

struct Example {
    char c;      /* 1 byte + 3 padding */
    int i;       /* 4 bytes */
    char d;      /* 1 byte + 3 padding */
};  /* Total: 12 bytes, not 6 */

Pack structures to minimize padding (may reduce performance):

#pragma pack(push, 1)
struct PackedExample { /* layout without padding */ };
#pragma pack(pop)

Unions

All members share the same memory location:

union DataValue {
    int i;
    float f;
    char str[20];
};

union DataValue val;
val.i = 123;
val.f = 98.6;  /* Overwrites val.i */

Size equals the largest member.

Bit-Fields

Memory-efficient storage for flags and small values:

struct DeviceStatus {
    unsigned int is_online : 1;
    unsigned int error_code : 4;
    unsigned int priority : 3;
    unsigned int : 24;  /* Padding to fill 32 bits */
};

13. Preprocessor and Compilation

Compilation Phases

  1. Preprocessing: Macro expansion, #include resolution, comment removal.
  2. Compilation: Syntax analysis, optimization, assembly generation.
  3. Assembly: Object code generation.
  4. Linking: Symbol resolution, library binding.

Preprocessor Directives

Conditional compilation:

#ifdef DEBUG
    #define LOG(msg) printf("[DEBUG] %s\n", msg)
#else
    #define LOG(msg) ((void)0)
#endif

Macro operators:

#define STRINGIFY(x) #x          /* Converts x to string */
#define CONCAT(a, b) a##b        /* Concatenates tokens */

Predefined macros:

  • __FILE__: Current filename
  • __LINE__: Current line number
  • __DATE__: Compilation date
  • __TIME__: Compilation time
  • __func__: Current function name (C99)

Header Guards

Prevent multiple inclusion:

#ifndef MODULE_H
#define MODULE_H

/* declarations */

#endif /* MODULE_H */

Or use #pragma once (non-standard but widely supported).

14. File I/O Operations

Opening and Closing

FILE *fp = fopen("data.txt", "r");  /* Modes: r, w, a, r+, w+, a+, rb, wb */
if (fp == NULL) {
    perror("Failed to open file");
    return EXIT_FAILURE;
}
/* operations */
fclose(fp);
fp = NULL;

Formatted I/O

fprintf(fp, "ID: %d, Score: %.2f\n", 42, 95.5);
fscanf(fp, "%d %f", &id, &score);

Binary I/O

struct Record rec;
fwrite(&rec, sizeof(struct Record), 1, fp);

struct Record buffer[100];
size_t count = fread(buffer, sizeof(struct Record), 100, fp);

Positioning

fseek(fp, 0L, SEEK_SET);  /* Beginning */
fseek(fp, 0L, SEEK_END);  /* End */
long pos = ftell(fp);     /* Current position */
rewind(fp);               /* Reset to beginning */

Standard Streams

  • stdin: Standard input (keyboard)
  • stdout: Standard output (console)
  • stderr: Standard error (unbuffered output)

15. Practical Algorithms and Problem Solving

Prime Number Detection

#include <stdbool.h>
#include <math.h>

bool is_prime(unsigned int n) {
    if (n < 2) return false;
    if (n == 2) return true;
    if (n % 2 == 0) return false;
    
    for (unsigned int i = 3; i <= sqrt(n); i += 2) {
        if (n % i == 0) return false;
    }
    return true;
}

Greatest Common Divisor (Euclidean Algorithm)

unsigned int gcd(unsigned int a, unsigned int b) {
    while (b != 0) {
        unsigned int remainder = a % b;
        a = b;
        b = remainder;
    }
    return a;
}

Tower of Hanoi

void move_disk(int disk, char source, char dest) {
    printf("Move disk %d from %c to %c\n", disk, source, dest);
}

void hanoi(int n, char source, char auxiliary, char dest) {
    if (n == 1) {
        move_disk(n, source, dest);
        return;
    }
    hanoi(n - 1, source, dest, auxiliary);
    move_disk(n, source, dest);
    hanoi(n - 1, auxiliary, source, dest);
}

String Rotation Check

#include <string.h>

bool is_rotation(const char *s1, const char *s2) {
    if (strlen(s1) != strlen(s2)) return false;
    
    size_t len = strlen(s1);
    char *concat = malloc(2 * len + 1);
    if (!concat) return false;
    
    strcpy(concat, s1);
    strcat(concat, s1);
    
    bool result = (strstr(concat, s2) != NULL);
    free(concat);
    return result;
}

Finding Single Numbers (XOR Method)

void find_two_singles(int arr[], size_t n, int *first, int *second) {
    int combined_xor = 0;
    for (size_t i = 0; i < n; i++) {
        combined_xor ^= arr[i];
    }
    
    /* Find rightmost set bit */
    int diff_bit = combined_xor & (-combined_xor);
    
    *first = 0;
    *second = 0;
    for (size_t i = 0; i < n; i++) {
        if (arr[i] & diff_bit) {
            *first ^= arr[i];
        } else {
            *second ^= arr[i];
        }
    }
}

Diamond Pattern Generation

void print_diamond(int rows) {
    /* Upper half */
    for (int i = 1; i <= rows; i++) {
        for (int space = 0; space < rows - i; space++) printf(" ");
        for (int star = 0; star < 2 * i - 1; star++) printf("*");
        printf("\n");
    }
    /* Lower half */
    for (int i = rows - 1; i >= 1; i--) {
        for (int space = 0; space < rows - i; space++) printf(" ");
        for (int star = 0; star < 2 * i - 1; star++) printf("*");
        printf("\n");
    }
}

Young's Matrix Search

bool search_young_matrix(int **matrix, int rows, int cols, int target) {
    int row = 0;
    int col = cols - 1;
    
    while (row < rows && col >= 0) {
        if (matrix[row][col] == target) return true;
        if (matrix[row][col] > target) {
            col--;
        } else {
            row++;
        }
    }
    return false;
}

Narcissistic Numbers (Armstrong Numbers)

#include <math.h>

void find_armstrong_numbers(int limit) {
    for (int num = 1; num <= limit; num++) {
        int original = num;
        int sum = 0;
        int digits = (int)log10(num) + 1;
        
        int temp = num;
        while (temp > 0) {
            int digit = temp % 10;
            sum += (int)pow(digit, digits);
            temp /= 10;
        }
        
        if (sum == original) {
            printf("%d is an Armstrong number\n", original);
        }
    }
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.