]> Pileus Git - ~andy/sfvlug/commitdiff
Add C notes.
authorAndy Spencer <andy753421@gmail.com>
Sun, 22 Dec 2019 01:45:33 +0000 (01:45 +0000)
committerAndy Spencer <andy753421@gmail.com>
Sun, 5 Jan 2020 06:56:46 +0000 (06:56 +0000)
22 files changed:
c/.gitignore [new file with mode: 0644]
c/c.txt [new file with mode: 0644]
c/src/arg.c [new file with mode: 0644]
c/src/args.c [new file with mode: 0644]
c/src/cc.sh [new file with mode: 0755]
c/src/cond.c [new file with mode: 0644]
c/src/cpp.c [new file with mode: 0644]
c/src/data.c [new file with mode: 0644]
c/src/duff.c [new file with mode: 0644]
c/src/fun.c [new file with mode: 0644]
c/src/hello.c [new file with mode: 0644]
c/src/io.c [new file with mode: 0644]
c/src/jump.c [new file with mode: 0644]
c/src/loop.c [new file with mode: 0644]
c/src/main.c [new file with mode: 0644]
c/src/makefile [new file with mode: 0644]
c/src/opts.c [new file with mode: 0644]
c/src/sm.c [new file with mode: 0644]
c/src/struct.c [new file with mode: 0644]
c/src/swap.c [new file with mode: 0644]
c/src/util.c [new file with mode: 0644]
c/src/util.h [new file with mode: 0644]

diff --git a/c/.gitignore b/c/.gitignore
new file mode 100644 (file)
index 0000000..45215cc
--- /dev/null
@@ -0,0 +1,16 @@
+src/arg
+src/args
+src/cond
+src/cpp
+src/data
+src/duff
+src/fun
+src/hello
+src/io
+src/jump
+src/loop
+src/main
+src/opts
+src/struct
+src/swap
+src/sm
diff --git a/c/c.txt b/c/c.txt
new file mode 100644 (file)
index 0000000..3d56912
--- /dev/null
+++ b/c/c.txt
@@ -0,0 +1,43 @@
+Intro:
+
+  1. Hello, World         -- src/hello.c
+  2. Compiling            -- src/cc.sh
+  3. Functions            -- src/fun.c
+  4. Arguments            -- src/arg.c
+  5. Pre-processor        -- src/cpp.c
+
+Control flow:
+
+  - do, while, for        -- src/loop.c
+  - if, switch            -- src/cond.c
+  - goto, labels, return  -- src/jump.c
+  - duff's device         -- src/duff.c
+
+Data types:
+
+  - Basic types           -- src/data.c
+  - Structs and unions    -- src/struct.c
+  - Unions                -- src/union.c
+
+Argument parsing:
+
+  - src/args.c
+  - src/opts.c
+
+Multiple files:
+
+  - src/util.c
+  - src/util.h
+  - src/main.c
+
+Why C?:
+
+  - You *can* do anything in C.
+  - C programs never break.
+  - Embedded software.
+  - High performance.
+  - C programs just work better.
+  - C and Unix (and Linux)
+
+
+# vim: ft=txt
diff --git a/c/src/arg.c b/c/src/arg.c
new file mode 100644 (file)
index 0000000..c55b7c5
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+       printf("Hello, %s!\n", argv[1]);
+       return 0;
+}
diff --git a/c/src/args.c b/c/src/args.c
new file mode 100644 (file)
index 0000000..8d7d0c6
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+       for (int i = 1; i < argc; i++)
+               printf("Hello, %s!\n", argv[i]);
+       return 0;
+}
diff --git a/c/src/cc.sh b/c/src/cc.sh
new file mode 100755 (executable)
index 0000000..eaf9a05
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+# Simplest complie 
+cc hello.c
+./a.out
+
+# Standard CC compile
+gcc --std=c99 -Wall -o hello hello.c
+./hello
+
+# Bulding object files
+gcc -c -o hello.o hello.c
+gcc -o hello hello.o -lm
+./hello
+
+# Building with make
+make hello
+./hello
diff --git a/c/src/cond.c b/c/src/cond.c
new file mode 100644 (file)
index 0000000..724ae2a
--- /dev/null
@@ -0,0 +1,34 @@
+#include <stdio.h>
+
+int main()
+{
+       int answer = 42;
+
+       /*
+        * If / else.
+        */
+       if (answer == 42)
+               printf("Right!\n");
+       else if (answer == 41)
+               printf("Close!\n");
+       else
+               printf("Wrong!\n");
+
+       /*
+        * Switch.
+        */
+       switch (answer) {
+               case 42:
+                       printf("Right!\n");
+                       break;
+               case 41:
+               case 43:
+                       printf("Close!\n");
+                       break;
+               default:
+                       printf("Wrong!\n");
+                       break;
+       }
+
+       return 0;
+}
diff --git a/c/src/cpp.c b/c/src/cpp.c
new file mode 100644 (file)
index 0000000..3518371
--- /dev/null
@@ -0,0 +1,35 @@
+#include <stdio.h>
+
+#define ANSWER        42
+
+#define COUNTER       counter++
+
+#define DONT          printf("Don't"
+#define DO            " do "
+#define THIS          "this!\n");
+
+#define HELLO1(name)  printf("Hello, %s\n", name)
+
+#define HELLO2(name)  printf("Hello, " #name "\n")
+
+int main()
+{
+       int counter = 0;
+
+       printf("The answer is %d.\n", ANSWER);
+       printf("\n");
+
+       printf("The counter is %d.\n", COUNTER);
+       printf("The counter is %d.\n", COUNTER);
+       printf("The counter is %d.\n", COUNTER);
+       printf("\n");
+
+       DONT DO THIS
+       printf("\n");
+
+       HELLO1("Andy");
+       HELLO2(Andy);
+       HELLO2("Andy");
+
+       return 0;
+}
diff --git a/c/src/data.c b/c/src/data.c
new file mode 100644 (file)
index 0000000..331bbb1
--- /dev/null
@@ -0,0 +1,132 @@
+#include <stdio.h>
+#include <stdint.h>
+
+int main()
+{
+       /*
+        * Numeric types.
+        */
+       int the_answer = 42;
+
+       signed negative = -100;
+
+       unsigned positive = 100;
+
+       long long trillion = 1000000000000;
+
+       unsigned long long int neg_trillion = -1000000000000;
+
+       short two_bytes = 65000;
+
+       char one_byte = 123;
+
+       printf("Numbers\n");
+       printf("  the_answer   = %d\n",   the_answer);
+       printf("  positive     = %d\n",   positive);
+       printf("  negative     = %u\n",   negative);
+       printf("  trillion     = %lld\n", trillion);
+       printf("  neg_trillion = %lld\n", neg_trillion);
+       printf("  two_bytes    = %hd\n",  two_bytes);
+       printf("  one_byte     = %hhd\n", one_byte);
+       printf("\n");
+
+       /*
+        * Standard integers.
+        */
+       int8_t signed_8bit = 1;
+
+       uint8_t unsigned_8bit = 2;
+
+       int64_t signed_64bit = 3;
+
+       uint64_t unsigned_64bit = 4;
+
+       printf("Standard Ints\n");
+       printf("  signed_8bit    = %hhd\n", signed_8bit);
+       printf("  unsigned_8bit  = %hhu\n", unsigned_8bit);
+       printf("  signed_6bit_   = %ld\n",  signed_64bit);
+       printf("  unsigned_64bit = %lu\n",  unsigned_64bit);
+       printf("\n");
+
+       /*
+        * Characeters.
+        */
+       char a_char = 'a';
+
+       char a_int = 97;
+
+       char a_hex = 0x61;
+
+       printf("Standard Ints\n");
+       printf("  as integers = %2d %2d %2d\n", a_char, a_int, a_hex);
+       printf("  as chars    = %2c %2c %2c\n", a_char, a_int, a_hex);
+       printf("  as hex      = %2x %2x %2x\n", a_char, a_int, a_hex);
+       printf("\n");
+
+       /*
+        * Arrays.
+        */
+       int fixed_size[100] = {1, 2, 3};
+
+       int auto_sized[] = {1, 2, 3};
+
+       int tables[][32] = {
+               {1, 2, 3},
+               {4, 5, 6},
+       };
+
+       printf("Array sizes\n");
+       printf("  fixed_size  = %zd\n", sizeof(fixed_size));
+       printf("  auto_sized  = %zd\n", sizeof(auto_sized));
+       printf("  table size  = %zd\n", sizeof(tables));
+       printf("  first       = %d\n",  fixed_size[0]);
+       printf("  third       = %d\n",  fixed_size[2]);
+       printf("  last        = %d\n",  fixed_size[99]);
+       printf("  tables      = %d\n",  tables[0][0]);
+       printf("\n");
+
+       /*
+        * Strings.
+        */
+       char hello_char[] = {'h', 'e', 'l', 'l', 'o', '\0'};
+
+       char hello_str[] = "hello";
+
+       char *hello_ptr = "hello";
+
+       printf("Strings\n");
+       printf("  as strings  = %s %s %s\n",
+                       hello_char,
+                       hello_str,
+                       hello_ptr);
+       printf("  as arrays   = %c %c %c\n",
+                       hello_char[0],
+                       hello_str[0],
+                       hello_ptr[0]);
+       printf("  sizes       = %zd %zd %zd\n",
+                       sizeof(hello_char),
+                       sizeof(hello_str),
+                       sizeof(hello_ptr));
+       printf("\n");
+
+       /*
+        * Pointers.
+        */
+       int one = 1;
+
+       int two = 2;
+
+       int *pointer = &one;
+
+       *pointer = 100;
+
+       printf("Strings\n");
+       printf("  one      = %d\n",   one);
+       printf("  two      = %d\n",   two);
+       printf("  pointer  = %llx\n", (long long)pointer);
+       printf("  pointer  = %p\n",   pointer);
+       printf("  value    = %d\n",   *pointer);
+
+
+       return 0;
+}
diff --git a/c/src/duff.c b/c/src/duff.c
new file mode 100644 (file)
index 0000000..9e7074e
--- /dev/null
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <string.h>
+
+void duff(const char *str)
+{
+       int len = strlen(str);
+       int div = len / 8;
+       int rem = len % 8;
+
+       switch (rem) {
+               case 0: while (div--) {
+                               putchar(*str++);
+               case 7:         putchar(*str++);
+               case 6:         putchar(*str++);
+               case 5:         putchar(*str++);
+               case 4:         putchar(*str++);
+               case 3:         putchar(*str++);
+               case 2:         putchar(*str++);
+               case 1:         putchar(*str++);
+                       }
+       }
+}
+
+int main(int argc, char **argv)
+{
+       duff("Hello, World\n");
+       return 0;
+}
diff --git a/c/src/fun.c b/c/src/fun.c
new file mode 100644 (file)
index 0000000..25086a4
--- /dev/null
@@ -0,0 +1,31 @@
+#include <stdio.h>
+
+void hello_world(void)
+{
+       printf("Hello, World!\n");
+}
+
+void hello_name(char *name)
+{
+       printf("Hello, %s!\n", name);
+}
+
+void hello_hello(int n)
+{
+       printf("Hello, World!\n");
+       if (n > 1)
+               hello_hello(n - 1);
+}
+
+int main()
+{
+       hello_world();
+       printf("\n");
+
+       hello_name("World");
+       hello_name("Andy");
+       printf("\n");
+
+       hello_hello(10);
+       return 0;
+}
diff --git a/c/src/hello.c b/c/src/hello.c
new file mode 100644 (file)
index 0000000..503e170
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main()
+{
+       printf("Hello, World\n");
+       return 0;
+}
diff --git a/c/src/io.c b/c/src/io.c
new file mode 100644 (file)
index 0000000..89666ab
--- /dev/null
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+void cat(char *name)
+{
+       FILE *fd = fopen(name, "r");
+       if (!fd) {
+               printf("Error opening '%s': %s\n",
+                       name, strerror(errno));
+               return;
+       }
+
+       int  len = 0;
+       char buf[32] = {};
+       while (!feof(fd)) {
+               len = fread(buf, 1, sizeof(buf), fd);
+               printf("{{ Read %d bytes }}", len);
+               fwrite(buf, 1, len, stdout);
+       }
+
+}
+
+int main()
+{
+       cat("io.c");
+       cat("junk.c");
+       return 0;
+}
diff --git a/c/src/jump.c b/c/src/jump.c
new file mode 100644 (file)
index 0000000..7fab02c
--- /dev/null
@@ -0,0 +1,44 @@
+#include <stdio.h>
+
+void bad_hello(int count)
+{
+       int i = 0;
+hello:
+       printf("Hello, %d!\n", i);
+       i++;
+       if (i < count)
+               goto hello;
+}
+
+int ok_hello(int count)
+{
+       if (count == 0)
+               goto error_zero;
+       if (count < 0)
+               goto error_neg;
+
+       for (int i = 0; i < count; i++)
+               printf("Hello, %d!\n", i);
+
+       return 0;
+
+error_zero:
+       printf("Count is zero!\n");
+       return 1;
+
+error_neg:
+       printf("Count is negative!\n");
+       return 1;
+}
+
+int main()
+{
+       bad_hello(3);
+       printf("\n");
+
+       ok_hello(1);
+       ok_hello(0);
+       ok_hello(-1);
+
+       return 0;
+}
diff --git a/c/src/loop.c b/c/src/loop.c
new file mode 100644 (file)
index 0000000..814f653
--- /dev/null
@@ -0,0 +1,67 @@
+#include <stdio.h>
+
+#define N_ELEM(x) (sizeof(x)/sizeof((x)[0]))
+
+struct list {
+       const char *name;
+       struct list *next;
+};
+
+int main()
+{
+       int i = 0;
+
+       /*
+        * While loops.
+        */
+       i = 0;
+       while (i < 3) {
+               printf("Hello, %d!\n", i);
+               i = i + 1;
+       }
+       printf("\n");
+
+       /*
+        * Do loops.
+        */
+       i = 0;
+       do {
+               printf("Hello, %d!\n", i);
+               i = i + 1;
+       } while (i < 3);
+       printf("\n");
+
+       /*
+        * For loops.
+        */
+       for (i = 0; i < 3; i++)
+               printf("Hello, %d!\n", i);
+       printf("\n");
+
+       /*
+        * C99 only.
+        */
+       for (int j = 0; j < 3; j++)
+               printf("Hello, %d!\n", j);
+       printf("\n");
+
+       /*
+        * Arrays
+        */
+       char *names[] = {"one", "two", "three"};
+       for (int i = 0; i < N_ELEM(names); i++)
+               printf("Hello, %s!\n", names[i]);
+       printf("\n");
+
+       /*
+        * Linked lists.
+        */
+       struct list three = {"three"};
+       struct list two   = {"two", &three};
+       struct list one   = {"one", &two};
+       for (struct list *cur = &one; cur; cur = cur->next)
+               printf("Hello, %s!\n", cur->name);
+       printf("\n");
+
+       return 0;
+}
diff --git a/c/src/main.c b/c/src/main.c
new file mode 100644 (file)
index 0000000..63b77a1
--- /dev/null
@@ -0,0 +1,7 @@
+#include "util.h"
+
+int main()
+{
+       hello("Andy");
+       return 0;
+}
diff --git a/c/src/makefile b/c/src/makefile
new file mode 100644 (file)
index 0000000..73e0024
--- /dev/null
@@ -0,0 +1,20 @@
+GCC    := gcc
+CFLAGS := -g -Wall -Wno-unused-variable --std=c99
+
+SRCS   := $(wildcard *.c)
+OBJS   := ${SRCS:%.c=%.o}
+BINS   := $(filter-out main util,${SRCS:%.c=%})
+
+all: $(BINS) main
+
+%-test: %
+       ./$<
+
+main: main.o util.o
+       $(GCC) $(CFLAGS) -o $@ $+
+
+$(BINS): %: %.o
+       $(GCC) $(CFLAGS) -o $@ $+
+
+%.o: %.c
+       $(GCC) $(CFLAGS) -c -o $@ $+
diff --git a/c/src/opts.c b/c/src/opts.c
new file mode 100644 (file)
index 0000000..9fc0ae1
--- /dev/null
@@ -0,0 +1,67 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+/* Options */
+static int   opt_verbose  = 0;
+static char *opt_greeting = "Hello";
+static char *opt_name     = "World";
+
+/* Parsing */
+static char *short_options = "hvg:n:";
+
+static struct option long_options[] = {
+       {"help",     0, NULL, 'h'},
+       {"verbose",  0, NULL, 'v'},
+       {"greeting", 1, NULL, 'g'},
+       {"name",     1, NULL, 'n'},
+};
+
+/* Show usage information */
+static void usage(int status)
+{
+       printf("opts -[OPTIONS]\n");
+       printf("\n");
+       printf("Options:\n");
+       printf("  -h,--help          Show usage information\n");
+       printf("  -v,--verbose       Print debug output messages\n");
+       printf("  -n,--greeting=STR  Use the given greeting\n");
+       printf("  -n,--name=NAME     Greet the given person\n");
+       exit(status);
+}
+
+/* Parse command line arguments */
+static void parse(int argc, char **argv)
+{
+       while (1) {
+               int c = getopt_long(argc, argv,
+                               short_options, long_options, 0);
+               if (c == -1)
+                       break;
+               switch (c) {
+                       case 'h': usage(0);               break;
+                       case 'v': opt_verbose   = 1;      break;
+                       case 'g': opt_greeting  = optarg; break;
+                       case 'n': opt_name      = optarg; break;
+                       default:  usage(1);               break;
+               }
+       }
+       if (argc != optind)
+               usage(1);
+
+       if (opt_verbose) {
+               printf("Options:\n");
+               printf("  verbose  = %d\n", opt_verbose);
+               printf("  greeting = %s\n", opt_greeting);
+               printf("  name     = %s\n", opt_name);
+               printf("\n");
+       }
+}
+
+/* Main entry point */
+int main(int argc, char **argv)
+{
+       parse(argc, argv);
+       printf("%s, %s\n", opt_greeting, opt_name);
+       return 0;
+}
diff --git a/c/src/sm.c b/c/src/sm.c
new file mode 100644 (file)
index 0000000..c17ea1d
--- /dev/null
@@ -0,0 +1,42 @@
+#include <stdio.h>
+
+int (*state)(typeof(state));
+
+int sm_first(state_t *state);
+int sm_second(state_t *state);
+int sm_third(state_t *state);
+int sm_done(state_t *state);
+
+int sm_first(state_t *state)
+{
+       printf("first\n");
+       *state = &sm_second;
+       return 1;
+}
+
+int sm_second(state_t *state)
+{
+       *state = &sm_third;
+       printf("second\n");
+       return 1;
+}
+
+int sm_third(state_t *state)
+{
+       *state = &sm_done;
+       printf("third\n");
+       return 1;
+}
+
+int sm_done(state_t *state)
+{
+       printf("done\n");
+       return 0;
+}
+
+int main()
+{
+       state_t state = sm_first;
+       while (state(&state));
+       return 0;
+}
diff --git a/c/src/struct.c b/c/src/struct.c
new file mode 100644 (file)
index 0000000..1c67422
--- /dev/null
@@ -0,0 +1,79 @@
+#include <stdio.h>
+#include <stdint.h>
+
+int main()
+{
+       /*
+        * Structs
+        */
+       struct person {
+               char *name;
+               int   age;
+       };
+
+       struct person andy = { "Andy", 33 };
+
+       printf("%s is %d years old!\n",
+                       andy.name, andy.age);
+       printf("\n");
+
+       /*
+        * Typedefs
+        */
+       typedef struct {
+               char *name;
+               int   age;
+       } person_t;
+
+       person_t andys = { "Andy Spencer", 33 };
+
+       printf("%s is %d years old!\n",
+                       andys.name, andys.age);
+       printf("\n");
+
+       /*
+        * Pointers.
+        */
+       person_t *who = &andys;
+
+       printf("%s is %d years old!\n",
+                       (*who).name, (*who).age);
+
+       printf("%s is %d years old!\n",
+                       who->name, who->age);
+       printf("\n");
+
+       /*
+        * Unions.
+        */
+       union cake {
+               char *have;
+               char *eat;
+       };
+
+       union cake chocolate = {};
+
+       chocolate.have = "Yes please";
+       printf("Chocolate? %s!\n", chocolate.have);
+       chocolate.eat = "Yum";
+       printf("Chocolate? %s!\n", chocolate.eat);
+       printf("Chocolate? %s!\n", chocolate.have);
+       printf("\n");
+
+       /*
+        * Unions.
+        */
+       union types {
+               uint32_t number;
+               char     string[4];
+       };
+
+       union types abc = {
+               .string = "abc"
+       };
+
+       printf("Number: %08x\n", abc.number);
+       printf("String: %s\n",   abc.string);
+
+       return 0;
+}
diff --git a/c/src/swap.c b/c/src/swap.c
new file mode 100644 (file)
index 0000000..5219c32
--- /dev/null
@@ -0,0 +1,19 @@
+#include <stdio.h>
+
+void swap(int *a, int *b)
+{
+       *a ^= *b;
+       *b ^= *a;
+       *a ^= *b;
+}
+
+int main(int argc, char **argv)
+{
+       int a = 5678;
+       int b = 1234;
+
+       swap(&a, &b);
+       printf("%d %d\n", a, b);
+
+       return 0;
+}
diff --git a/c/src/util.c b/c/src/util.c
new file mode 100644 (file)
index 0000000..1be6714
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include "util.h"
+
+void hello(char *name)
+{
+       printf("Hello, %s\n", name);
+}
diff --git a/c/src/util.h b/c/src/util.h
new file mode 100644 (file)
index 0000000..5bd07de
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+void hello(char *name);
+
+#endif /* UTIL_H */