chapter 1 — variables, data types & IO

← back to C index · V:\KNOWLEDGE\NOTES\C

Final log

How C stores a value, names it, measures it, and moves it in and out of a program. The big idea of the whole chapter: a format specifier is a window onto a byte — change the window, not the byte. The memory never moves; only the interpretation does.


core concepts

variables

Containers that store a value. Declaration reserves memory; initialization writes a value into it. They are two separate events — a declared-but-uninitialized variable holds whatever garbage was already in that memory.

int age;        // declaration — memory reserved, value undefined
age = 25;       // initialization — value written
int year = 2026; // both at once

constants

Entities whose value does not change once set.

data types

A classification that tells the compiler what kind of value a variable holds and how much memory to allocate for it.

typestoresnote
intwhole numbersno decimals
floatnumbers with decimalsfloating point
chara single characterwrap the value in 'single quotes', never "

comments

Notes for humans, ignored by the compiler: // single line or /* block */.

format specifiers

Placeholders inside printf/scanf that say how to read or display a value.

specifiertype
%dwhole number (int)
%ffloating point (float)
%csingle character (char)
%zusize (size_t, from sizeof)

escape sequences

Special characters inside a string: \n newline, \t tab, \" / \' literal quote. They are valid char values — storable and injectable like any other.

sizeof

A unary operator that returns the exact memory size in bytes of a type, variable, or expression. Resolved at compile time, never at runtime.

  • Around a type, parentheses are required: sizeof(int).
  • Around a variable, they are optional but recommended.
  • Returns a size_t — print it with %zu.
One byte, two windows

The same variable can be printed two ways in one printf: %c shows the character, %d shows its ASCII integer. Both read the same byte — only the display instruction changes. Every % consumes one argument, left to right, so two specifiers need two arguments even when it's the same variable.

user input — scanf() and &

scanf pauses, waits for input, and writes it into a variable's memory address. The & (address-of) operator hands scanf the destination address.

Without &, scanf has nowhere to write

&age does not pass the value of age — it passes its address, telling scanf where in memory to store the data. Omit it and you get undefined behavior or a crash. This is the foundation of pointers.


code logs

code 03 — format specifiers & data types

Objective: the format specifier controls how a value is displayed, not the value itself. Same byte in memory, different display.

#include <stdio.h>
int main() {
  int a = 1;
  float b = 1.40;
  char c = 'b';
  char x = 'a';
  printf("valor de a es %d \n", a);
  printf("valor de b es %f \n", b);
  printf("valor de c es %c \n", c);
  printf("valor de x es %d \n", x);
  return 0;
}

Output:

valor de a es 1
valor de b es 1.400000
valor de c es b
valor de x es 97

Walkthrough:

  • int a = 1%d displays 1.
  • float b = 1.40%f displays 1.400000 (six decimals by default).
  • char c = 'b'%c displays b.
  • char x = 'a'%d displays 97, the ASCII value of a.
Key insight

char is an integer internally. %c and %d are two instructions for displaying the same byte. The memory never changes; only the interpretation does.

code 04 — sizeof(), memory size & multiple representations

Objective: variables have a value and a memory size. Both can be printed in one statement. The same variable can appear multiple times to show different representations.

#include <stdio.h>
int main() {
  int a = 10;
  float b = 3.14;
  char c = 'z';
  printf("Variable a has value %d and takes %zu bytes\n", a, sizeof(int));
  printf("Variable b has value %f and takes %zu bytes\n", b, sizeof(float));
  printf("Variable c has value %c as character but %d as number and takes %zu bytes\n",
         c, c, sizeof(char));
  return 0;
}

Output:

Variable a has value 10 and takes 4 bytes
Variable b has value 3.140000 and takes 4 bytes
Variable c has value z as character but 122 as number and takes 1 bytes

Walkthrough:

  • int a = 10 → 4 bytes. int is 32-bit; the compiler reserves 4 bytes on the stack for whole numbers.
  • float b = 3.14 → 4 bytes. Floating-point precision: 3.14 has no exact binary form, so the machine stores the closest representable value. GDB reveals 3.140001; printf rounds it to 3.140000 for display.
  • char c = 'z' → 1 byte. ASCII fits in 256 combinations; 8 bits suffice. GDB shows 122 'z' — the integer value of z.

Multiple representations in one call:

printf("...%c as character but %d as number...", c, c, sizeof(char));

Each specifier consumes one argument left to right. Two specifiers, two arguments — even when the variable repeats.

sizeof()

Resolved at compile time, never at runtime — the compiler knows every type's size before execution. Returns a size_t; format with %zu.

code 06 — user input with scanf()

Objective: read three datatypes from the user, store each via the address-of operator, and print each value with its size.

#include <stdio.h>
int main() {
  char ini;
  int age;
  float height;
  scanf("%c", &ini);
  scanf("%d", &age);
  scanf("%f", &height);
  printf("Name Initial: %c and value %d and %zu bytes\n", ini, ini, sizeof(char));
  printf("Age: %d and %zu bytes\n", age, sizeof(int));
  printf("Height: %f %zu bytes \n", height, sizeof(float));
  printf("Me llaman el mas piola \n");
  return 0;
}

Input:

J
25
1.75

Output:

Name Initial: J and value 74 and 1 bytes
Age: 25 and 4 bytes
Height: 1.750000 4 bytes
Me llaman el mas piola

Walkthrough:

  • Variables declared without initialization. GDB shows garbage: memory is reserved, but nothing has been written yet.
  • Each scanf pauses execution, waits for input, and writes the value to the variable's memory address.

The & operator: &ini, &age, &height give scanf the destination address. Without &, scanf has nowhere to write — undefined behavior or a crash. This is the address-of operator: the foundation of pointers.

GDB confirms type sizes through address differences:

  • &age at 0x7fffffffe2a4, &height at 0x7fffffffe2a0 → 4 bytes apart.
  • &ini at 0x7fffffffe2ab → 1 byte from the next variable.
Hex not covered yet

The 0x... notation is hexadecimal — skip it for now. What matters: addresses are real, and their differences expose type sizes directly.

code 07 — \n as a stored value, char as an injectable variable

Objective: \n lives in a char variable and gets injected into printf like any other argument — no hardcoding required. A user-input char then prints as character, ASCII integer, and memory size in a single statement.

#include <stdio.h>
int main() {
  char separator = '\n';
  char init = 'J';
  char apu;
  scanf("%c", &apu);
  printf("Hello, my name starts with %c %c Nice to meet you %c %c "
         "But people also call me %c OR %d OR %zu byte  %c THANKS YOU",
         init, separator, init, separator, apu, apu, sizeof(char), separator);
  return 0;
}

Input:

Z

Output:

Hello, my name starts with J
Nice to meet you J
But people also call me Z OR 90 OR 1 byte
THANKS YOU

Walkthrough:

  • char separator = '\n' → stores ASCII 10 (newline).
  • char init = 'J' → stores J.
  • char apu → declared, uninitialized. Garbage in GDB until scanf writes.
  • scanf("%c", &apu) → user supplies a character; scanf writes it to apu's address.

printf, applied:

  • One datatype, one variable, one format specifier per occurrence.
  • separator injects the newline without hardcoding \n in the string — operationally identical, just controlled through a variable.
  • apu appears three times: %c shows Z, %d shows 90, %zu shows 1. Three views of the same byte.
The rule

Every % consumes one argument, left to right. Two specifiers, two arguments. No exceptions.


concepts covered

conceptkey point
declaration vs initDeclaration reserves memory. Initialization writes a value.
int, float, charDifferent sizes, different valid operations.
format specifiersControl display, not the value. Same byte, different window.
sizeof()Compile-time operator. Returns size_t. Format with %zu.
floating pointBinary can't represent all decimals. Closest value is stored.
ASCIIchar is an integer internally. %c and %d show the same byte.
scanf() and && passes a memory address. Without it, scanf has no target.
memory addressesVariables live at addresses. Diffs reveal type sizes.
\n as a valueEscape sequences are valid char values. Storable and injectable.

→ next: chapter 2 — operators & arithmetic

Built with LogoFlowershow