Hello World & Running
Hello, World
#include <stdio.h>
int main(void) {
printf("Hello, World!\n");
return 0;
} puts "Hello, World!" Ruby programs need no
#include directives, no main function, and no return 0. Code at the top level executes immediately, line by line. puts prints a value followed by a newline — the direct equivalent of printf("...\n").Running a program
// Compile then run:
// gcc -o hello hello.c && ./hello
// With math:
// gcc hello.c -lm -o hello
// Check with:
// ./hello; echo "exit: $?" # Run directly (no compile step):
# ruby hello.rb
#
# Run a one-liner:
# ruby -e 'puts "Hello!"'
#
# Interactive REPL:
# irb Ruby is interpreted — there is no compile step, no object file, no linker.
ruby hello.rb parses, compiles to bytecode, and executes in one command. For quick experiments, irb (Interactive Ruby) provides a REPL. The -e flag executes a one-liner without creating a file.Comments
#include <stdio.h>
// Single-line comment
/* Multi-line
comment */
int main(void) {
int count = 0; /* inline comment */
printf("%d\n", count);
return 0;
} # Single-line comment
=begin
Multi-line
comment
=end
count = 0 # inline comment
puts count Ruby uses
# for single-line comments — one character shorter than //. The =begin / =end block comment exists but is almost never used in practice; consecutive # lines are the idiomatic Ruby style for multi-line comments. Both markers must be at the very beginning of the line.Output — puts, print, p
#include <stdio.h>
int main(void) {
printf("Hello\n"); // with newline
printf("no newline"); // without newline
printf("x = %d\n", 42); // formatted
fprintf(stderr, "error\n"); // to stderr
return 0;
} puts "Hello" # with newline
print "no newline" # without newline
puts # blank line
puts "x = #{42}" # interpolation
p "hello" # inspect: shows "hello" with quotes
p [1, 2, 3] # inspect: shows [1, 2, 3] Ruby has three main output methods:
puts adds a newline (like printf("...\n")); print does not; p calls .inspect on its argument, which shows the type and structure — invaluable for debugging. Unlike printf, Ruby uses string interpolation (#{expression}) instead of format specifiers for most output.Variables & Types
No type declarations
#include <stdio.h>
int main(void) {
int count = 42;
double price = 9.99;
char name[] = "Alice";
printf("%d %.2f %s\n", count, price, name);
return 0;
} count = 42
price = 9.99
name = "Alice"
puts "#{count} #{price} #{name}" Ruby variables are created on first assignment — no type declaration, no
int, no double, no char[]. The runtime tracks types automatically. Variable names use snake_case by convention. There is no distinction between stack-allocated primitives and heap-allocated objects — everything in Ruby is an object on the heap.Dynamic typing — variables can change type
#include <stdio.h>
int main(void) {
/* C: type is fixed at declaration */
int value = 42;
/* value = "hello"; // compile error */
printf("%d\n", value);
return 0;
} # Ruby: a variable can hold any type at any time
value = 42
puts value.class # Integer
value = "hello"
puts value.class # String
value = [1, 2, 3]
puts value.class # Array In Ruby, variables are not bound to a type — only objects are. Reassigning a variable to a different type is perfectly valid. The
.class method returns the actual runtime class of any object. This is fundamentally different from C, where a variable's type is fixed at declaration and enforced by the compiler.Constants
#include <stdio.h>
#define MAX_RETRIES 3
#define API_URL "https://example.com"
int main(void) {
printf("%d\n", MAX_RETRIES);
printf("%s\n", API_URL);
return 0;
} MAX_RETRIES = 3
API_URL = "https://example.com"
puts MAX_RETRIES
puts API_URL Ruby constants start with an uppercase letter;
SCREAMING_SNAKE_CASE is the convention for simple values. Unlike C's #define macros (which are textual substitution with no scope), Ruby constants are real values stored in the runtime and respect module/class scope. Reassigning a constant produces a warning but is not a fatal error.nil — not NULL
#include <stdio.h>
#include <stddef.h>
int main(void) {
char *pointer = NULL;
if (pointer == NULL) {
printf("pointer is null\n");
}
/* Dereferencing NULL → segfault */
return 0;
} pointer = nil
puts pointer.nil? # true
puts pointer.class # NilClass
puts pointer.to_s # "" (empty string — no segfault)
puts pointer.to_a.inspect # [] (empty array)
puts pointer.to_i # 0 Ruby's
nil is a real object of class NilClass — it is not an invalid memory address. Unlike C's NULL, dereferencing nil does not segfault; calling a method that nil does not understand raises NoMethodError. Conversion methods like nil.to_s, nil.to_a, and nil.to_i all return sensible empty values.Truthiness — only nil and false are falsy
#include <stdio.h>
int main(void) {
/* C: 0, NULL, '