From bc60878f14313f857dedc9954f189f37528386b7 Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Sun, 22 Dec 2019 01:45:33 +0000 Subject: [PATCH] Add C notes. --- c/.gitignore | 16 ++++++ c/c.txt | 43 ++++++++++++++++ c/src/arg.c | 7 +++ c/src/args.c | 8 +++ c/src/cc.sh | 18 +++++++ c/src/cond.c | 34 +++++++++++++ c/src/cpp.c | 35 +++++++++++++ c/src/data.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++ c/src/duff.c | 28 +++++++++++ c/src/fun.c | 31 ++++++++++++ c/src/hello.c | 7 +++ c/src/io.c | 29 +++++++++++ c/src/jump.c | 44 +++++++++++++++++ c/src/loop.c | 67 +++++++++++++++++++++++++ c/src/main.c | 7 +++ c/src/makefile | 20 ++++++++ c/src/opts.c | 67 +++++++++++++++++++++++++ c/src/sm.c | 42 ++++++++++++++++ c/src/struct.c | 79 +++++++++++++++++++++++++++++ c/src/swap.c | 19 +++++++ c/src/util.c | 7 +++ c/src/util.h | 6 +++ 22 files changed, 746 insertions(+) create mode 100644 c/.gitignore create mode 100644 c/c.txt create mode 100644 c/src/arg.c create mode 100644 c/src/args.c create mode 100755 c/src/cc.sh create mode 100644 c/src/cond.c create mode 100644 c/src/cpp.c create mode 100644 c/src/data.c create mode 100644 c/src/duff.c create mode 100644 c/src/fun.c create mode 100644 c/src/hello.c create mode 100644 c/src/io.c create mode 100644 c/src/jump.c create mode 100644 c/src/loop.c create mode 100644 c/src/main.c create mode 100644 c/src/makefile create mode 100644 c/src/opts.c create mode 100644 c/src/sm.c create mode 100644 c/src/struct.c create mode 100644 c/src/swap.c create mode 100644 c/src/util.c create mode 100644 c/src/util.h diff --git a/c/.gitignore b/c/.gitignore new file mode 100644 index 0000000..45215cc --- /dev/null +++ b/c/.gitignore @@ -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 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 index 0000000..c55b7c5 --- /dev/null +++ b/c/src/arg.c @@ -0,0 +1,7 @@ +#include + +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 index 0000000..8d7d0c6 --- /dev/null +++ b/c/src/args.c @@ -0,0 +1,8 @@ +#include + +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 index 0000000..eaf9a05 --- /dev/null +++ b/c/src/cc.sh @@ -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 index 0000000..724ae2a --- /dev/null +++ b/c/src/cond.c @@ -0,0 +1,34 @@ +#include + +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 index 0000000..3518371 --- /dev/null +++ b/c/src/cpp.c @@ -0,0 +1,35 @@ +#include + +#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 index 0000000..331bbb1 --- /dev/null +++ b/c/src/data.c @@ -0,0 +1,132 @@ +#include +#include + +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 index 0000000..9e7074e --- /dev/null +++ b/c/src/duff.c @@ -0,0 +1,28 @@ +#include +#include + +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 index 0000000..25086a4 --- /dev/null +++ b/c/src/fun.c @@ -0,0 +1,31 @@ +#include + +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 index 0000000..503e170 --- /dev/null +++ b/c/src/hello.c @@ -0,0 +1,7 @@ +#include + +int main() +{ + printf("Hello, World\n"); + return 0; +} diff --git a/c/src/io.c b/c/src/io.c new file mode 100644 index 0000000..89666ab --- /dev/null +++ b/c/src/io.c @@ -0,0 +1,29 @@ +#include +#include +#include + +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 index 0000000..7fab02c --- /dev/null +++ b/c/src/jump.c @@ -0,0 +1,44 @@ +#include + +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 index 0000000..814f653 --- /dev/null +++ b/c/src/loop.c @@ -0,0 +1,67 @@ +#include + +#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 index 0000000..63b77a1 --- /dev/null +++ b/c/src/main.c @@ -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 index 0000000..73e0024 --- /dev/null +++ b/c/src/makefile @@ -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 index 0000000..9fc0ae1 --- /dev/null +++ b/c/src/opts.c @@ -0,0 +1,67 @@ +#include +#include +#include + +/* 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 index 0000000..c17ea1d --- /dev/null +++ b/c/src/sm.c @@ -0,0 +1,42 @@ +#include + +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 index 0000000..1c67422 --- /dev/null +++ b/c/src/struct.c @@ -0,0 +1,79 @@ +#include +#include + +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 index 0000000..5219c32 --- /dev/null +++ b/c/src/swap.c @@ -0,0 +1,19 @@ +#include + +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 index 0000000..1be6714 --- /dev/null +++ b/c/src/util.c @@ -0,0 +1,7 @@ +#include +#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 index 0000000..5bd07de --- /dev/null +++ b/c/src/util.h @@ -0,0 +1,6 @@ +#ifndef UTIL_H +#define UTIL_H + +void hello(char *name); + +#endif /* UTIL_H */ -- 2.43.2