C Programming: Data Types, Memory & Strings

🔗 C and C++ Data Type Hierarchy

Data Type
Scalar
Function
void
Aggregate
Pointer
Arithmetic
Enumeration
Array
Structure
Variant
Floating-point
bool
Integer
enum
struct
union
float
double
char
short
int
long
signed
unsigned

Key Concepts:

  • Scalar Types: Single values (int, float, char, pointers)
  • Aggregate Types: Collections of data (arrays, structures, unions)
  • Function Types: Represent functions and their signatures
  • void Type: Represents absence of type or value
  • Type Qualifiers: const, volatile, restrict modify behavior

🏨 Memory Organization

Memory is byte-addressable - each byte has a unique address

Memory Layout Example:

0x1000 65 ('A') char 1 byte
0x1001 66 ('B') char 1 byte
0x1002 0x00 char null terminator
0x1004 1234 int 4 bytes (typically)
0x1008 3.14159 float 4 bytes
0x100C 0x1000 char* pointer to char (8 bytes on 64-bit)

Memory Organization Test Points:

  • Each byte has a unique memory address
  • Addresses increase sequentially (0x1000, 0x1001, 0x1002...)
  • Different data types occupy different amounts of memory
  • Memory alignment affects where data is stored
  • Pointers store memory addresses as their values

📍 Byte Addressable Memory - Code Examples

// Basic pointer and address demonstration
#include <stdio.h>

int main() {
    int n1 = 4, n2 = 8;
    int *pt1 = &n1, *pt2 = &n2;
    char c1 = 'A', c2 = 'B', c6;
    char *pc1 = &c1, *pc2 = &c2, *pc3 = &c6;
    
    // Print addresses and values
    printf("c1 address = %p, c1 value = %c\n", pc1, *pc1);
    printf("c2 address = %p, c2 value = %c\n", pc2, *pc2);
    printf("n1 address = %p, n1 value = %d\n", pt1, *pt1);
    printf("n2 address = %p, n2 value = %d\n", pt2, *pt2);
    
    return 0;
}
// Pointer arithmetic and memory addresses
#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40};
    int *ptr = arr;
    
    // Show how array elements are stored in consecutive memory
    for(int i = 0; i < 4; i++) {
        printf("arr[%d] = %d, address = %p\n", 
               i, *(ptr + i), (ptr + i));
    }
    
    // Show byte-level addressing
    char *byte_ptr = (char*)ptr;
    printf("\nByte-by-byte view of first integer:\n");
    for(int i = 0; i < sizeof(int); i++) {
        printf("Byte %d: %02X (address %p)\n", 
               i, *(byte_ptr + i), (byte_ptr + i));
    }
    
    return 0;
}

📝 C-Style Strings

String "Hello" in Memory:

H
e
l
l
o
\0

Address: 0x2000 0x2001 0x2002 0x2003 0x2004 0x2005

// C-Style String Examples
#include <stdio.h>
#include <string.h>

int main() {
    // Different ways to declare strings
    char str1[] = "Hello";           // Array on stack
    char *str2 = "World";           // Pointer to string literal
    char str3[20];                   // Uninitialized array
    char str4[10] = {'T', 'e', 's', 't', '\0'}; // Character array
    
    // Show string properties
    printf("str1 = \"%s\", length = %zu\n", str1, strlen(str1));
    printf("str2 = \"%s\", length = %zu\n", str2, strlen(str2));
    printf("str4 = \"%s\", length = %zu\n", str4, strlen(str4));
    
    // String operations
    strcpy(str3, "Copied");
    printf("After strcpy: str3 = \"%s\"\n", str3);
    
    strcat(str3, " String");
    printf("After strcat: str3 = \"%s\"\n", str3);
    
    // Character-by-character access
    printf("\nCharacter-by-character access of str1:\n");
    for(int i = 0; str1[i] != '\0'; i++) {
        printf("str1[%d] = '%c' (ASCII %d) at address %p\n", 
               i, str1[i], str1[i], &str1[i]);
    }
    
    return 0;
}
// Advanced String Operations
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// Custom string length function
int my_strlen(const char *str) {
    int count = 0;
    while(*str != '\0') {
        count++;
        str++;
    }
    return count;
}

// Custom string copy function
char* my_strcpy(char *dest, const char *src) {
    char *original_dest = dest;
    while(*src != '\0') {
        *dest = *src;
        dest++;
        src++;
    }
    *dest = '\0'; // Don't forget null terminator!
    return original_dest;
}

int main() {
    char source[] = "Programming";
    char destination[20];
    
    printf("Source length (custom): %d\n", my_strlen(source));
    printf("Source length (library): %zu\n", strlen(source));
    
    my_strcpy(destination, source);
    printf("Copied string: %s\n", destination);
    
    // Dynamic string allocation
    char *dynamic_str = malloc(50 * sizeof(char));
    strcpy(dynamic_str, "Dynamic Memory");
    printf("Dynamic string: %s\n", dynamic_str);
    free(dynamic_str); // Don't forget to free!
    
    return 0;
}

🎯 Key Test Points & Concepts

Data Types & Hierarchy

  • Know the difference between scalar and aggregate types
  • Understand type qualifiers: const, volatile, restrict
  • Memory sizes: char (1), short (2), int (4), long (8), pointer (8 on 64-bit)
  • Signed vs unsigned integer ranges
  • Float vs double precision and storage

Memory Organization

  • Each byte has a unique memory address
  • Addresses are typically displayed in hexadecimal
  • Memory alignment affects performance and layout
  • Stack vs heap memory allocation
  • Pointer arithmetic: ptr + 1 moves by sizeof(type) bytes

C Strings

  • C strings are null-terminated character arrays
  • String literals are stored in read-only memory
  • strlen() returns length WITHOUT the null terminator
  • Buffer overflows can occur without bounds checking
  • String functions: strcpy, strcat, strcmp, strlen, strstr
  • Always allocate space for the null terminator (\0)

Pointers & Addresses

  • &variable gives address of variable
  • *pointer dereferences pointer to get value
  • Pointer arithmetic follows data type size
  • Array name is pointer to first element
  • Pointer to pointer concepts (char **)
  • NULL pointer (0x0) represents invalid address