Languages in the Key of C: C, Go

a side-by-side reference sheet

grammar and invocation | variables and expressions | arithmetic and logic | strings | regexes | dates and time | arrays | dictionaries | functions | execution control | concurrency | file handles | files | file formats | directories | processes and environment | libraries and namespaces | user-defined types | macros | net and web | unit tests | debugging and profiling

multidimensional arrays | vectors | matrices

c go
version used
 
gcc 4.6 in POSIX environment 6g version release.r56
show version
 
$ gcc --version $ 6g -V
implicit prologue #include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
grammar and invocation
c go
hello word $ cat hello.c
#include <stdio.h>

int main(int argc, char **argv) {
  printf("Hello, World!\n");
}

$ gcc hello.c

$ ./a.out
Hello, World!
$ cat hello.go
package main
import "fmt"

func main() {
  fmt.Printf("Hello, World!\n")
}

$ go build hello.go

$ ./hello
Hello, World!
file suffixes
source, header, object file
.c .h .o
block delimiters { } { }
statement terminator ; ; or sometimes newline

a new line terminates a statement when the last token on the line is
  (1) an identifier,
  (2) a numeric, character, or string literal,
  (3) one of the keywords
break, continue,
      fallthrough, or return,
  (4) one of
++, --, ), ], or }
end-of-line comment // comment // comment
multiple line comment /* comment line
another line */
/* comment line
another line */
variables and expressions
c go
variable types
variable declaration
are identifiers case sensitive
declare primitive type on stack int i;
int j = 3;
var i int
j := 3
allocate primitive type on heap int *ip = malloc(sizeof(int));
*ip = 7;
ip := new(int)
*ip = 7
free primitive type on heap free(ip); none; language provides garbage collection
global primitive type
value of uninitialized primitive types stack variables and heap variables allocated with malloc have indeterminate values. Global and static variables and heap variables allocated with calloc are zero-initialized. every type has a zero value. For numeric types it is zero and for strings it is the empty string.
constant /* usually preprocessor is used: */
#define PI 3.14
const Pi = 3.14
assignment i = 3; // defines variable of appropriate type:
i := 3

//variable must already be declared:
i = 3
parallel assignment none //define variables of appropriate type:
m, n := 3, 7

// x and y must already be declared:
x, y = 2, 8
swap int x = 1, y = 2, tmp;

tmp = x;
x = y;
y = tmp;
x, y = y, x
compound assignment operators arithmetic:
+= -= *= /= %=

bit:
<<= >>= &= |= ^=
arithmetic:
+= -= *= /= %=

bit:
<<= >>= &= |= ^=
increment and decrement operators premodifiers:
++i --i

postmodifiers:
i++ i--
cannot be used as expressions:
i++ i--
null
 
NULL nil
coalesce
 
char *s1 = s2 || "was null";
undefined variable access
arithmetic and logic
c go
boolean type
 
int bool
true and false
 
1 0 true false
falsehoods
 
0 0.0 NULL false
logical operators && || ! && || !
relational operators == != < > <= >= == != < > <= >=
integer type signed char 1+ byte
short int 2+ bytes
int 2+ bytes
long int 4+ bytes
long long int 4+ bytes
int
int8
int16
int32
int64
unsigned type unsigned char: 8+
unsigned short int 2 bytes+
unsigned int 2 bytes+
unsigned long int 4+ bytes
unsigned long long int 4+ bytes
uint
uint8 (byte)
uint16
uint32
uint64
float type float
double
long double
float32
float64
arithmetic operators
 
+ - * / % + - * / %
integer division 3 / 7 3 / 7
integer division by zero system dependent; process often sent a SIGFPE signal
float division
 
3 / (float)7 3 / float32(7)
float division by zero inf
power #include <math.h>

pow(2.0, 3.0)
import "math"

math.Pow(2.0, 3.0)
sqrt #include <math.h>

sqrt(2);
include "math"

math.Sqrt(2)
sqrt -1 #include <math.h>

/* nan */
double x = sqrt(-2.0);
import "math"

// NaN
x := math.Sqrt(-2.0)

import "math/cmplx"

// (0+1.41421356i)
z := cmplx.Sqrt(-2.0)
transcendental functions #include <math.h>

exp log log2 log10
sin cos tan
asin acos atan
atan2
include "math"

math.Exp math.Log math.Log2 math.Log10
math.Sin math.Cos math.Tan
math.Asin math.Acos math.Atan
math.Atan2
float truncation #include <math.h>
 
double d = 3.77;
 
long trunc = (long)d;
long rnd = round(d);
long flr = floorl(d);
long cl = ceill(d);
include "math"

x = 3.77

trunc := int(x)
none
flr := int(math.Floor(x))
cl := int(math.Ceil(x))
absolute value #include <math.h>  /* fabs() */

int i = abs(-7);
float x = fabs(-7.77);
include "math"

none
math.Abs(-7.77)
complex type complex64
complex128
complex construction #include <complex.h>

double complex z;
z = 1 * I;
z = 2 * I;
z = 3 * I;
complex decomposition #include <complex.h>

double x;
x = creal(z);
x = cimag(z);
x = carg(z);
random number
uniform integer, uniform float
/* returns value between 0 and RAND_MAX inclusive */
int i = rand();
??
import "math/rand"

i := rand.Int()
??
random seed srand(17); import "math/rand"

rand.Seed(17)
bit operators << >> & | ^ ~ << >> & | none ^
strings
c go
string type
 
char * string
char type char rune
string literal
 
"hello" "hello"
newline in string literal
string escapes \a \b \f \n \r \t \v \xhh \uhhhh \Uhhhhhhhh
\" \' \? \\ \o \oo \ooo
allocate string char *s = strdup("hello");
comparison strcmp("hello", "world") "hello" == "world"
semantics of == object identity comparison string comparison
convert string to numeric strtoimax strtol strtoll
strtoumax strtoul strtoull
strtof strtod strtold
import "strconv"

2nd arg is base, 3rd arg is size of integer in bits:
i, _ := strconv.ParseInt("17", 10, 32)

2nd arg is size of float in bits:
x, _ := strconv.ParseFloat("3.14", 32)
convert numeric to string import "strconv"

3rd arg is precision after decimal point, 4th arg is size of float in bits:
strconv.FormatFloat(3.14, 'f', 4, 32)

2nd arg is base
strconv.FormatInt(7, 10)
split import "strings"

s := "foo bar baz"
parts := strings.Split(s, " ")
join
 
concatenate char *s1 = "hello";
char *s2 = " world";
char *s3 = (char *)calloc(strlen(s1) + strlen(s2) + 1,sizeof(char));
strcpy(s3, s1);
strcat(s3, s2);
"hello" + " world"
replicate
substring char target[3];
char *source = "hello";
strncpy(target, source + 2, 2);
"hello"[2:4]
index const char *s = "hello";
const char *p = strstr("hello", "ll");
p ? p - s : -1;
sprintf char buf[100];
snprintf(buf, 100, "%s: %d", "Spain", 7);
uppercase char *s = strdup("hello");
int i;

for (i=0; i < strlen(s); ++i) {
  s[i] = toupper(s[i]);
}
import "strings"

strings.ToUpper("hello")
lowercase char *s = strdup("HELLO");
int i;

for (i=0; i < strlen(s); i++) {
  s[i] = tolower(s[i]);
}
trim
pad on right char buf[100];
snprintf(buf, 100, "%-10s", "hello");
length
 
strlen("hello") len("hello")
character access
chr and ord
regular expressions
c go
metacharacters /* REG_BASIC: */
. [ ] \ * ^ $

/* REG_EXTENDED: */
. [ ] \ ( ) * + ? { } | ^ $
character class abbrevations /* matches any character; does not match newline if
   REG_NEWLINE is used: */

.

/* more character classes available in pcre library */
anchors /* match beginning and end of string; match beginning and
   end of line if REG_NEWLINE is used: */

^ $
match test #include <regex.h>

regex_t rx;
int retval;
char *pat = "1999";
char *s = "It's 1999";

/* Use REG_NOSUB if 4th arg to regexec() is NULL */
if (retval = regcomp(&rx, pat, REG_EXTENDED | REG_NOSUB)) {

  char buf[200];

  regerror(retval, &rx, buf, 200);
  fprintf(stderr, "regex error: %s\n", buf);
}
else {

  if (regexec(&rx, "s, 0, NULL, 0) == 0) {
    printf("Party!\n");
  }

  regfree(&rx);
}
case insensitive match test #include <regex.h>

regex_t rx;
int retval;
char *pat = "lorem";
char *s = "Lorem";

if (retval = regcomp(&rx, pat, REG_EXTENDED | REG_ICASE)) {

  char buf[200];

  regerror(retval, &rx, buf, 200);
  fprintf(stderr, "Regex error: %s\n", buf);
}
else {

  if (regexec(&rx, s, 0, NULL, 0) == 0) {
    printf("case insensitive match\n");
  }

  regfree(&rx);
}
modifiers /* bit flags used in 3rd arg of regcomp(): */
REG_BASIC
REG_EXTENDED
REG_ICASE
REG_NOSUB
REG_NEWLINE
substitution
group capture #include <regex.h>

regex_t rx;
int retval;

char *pat = "([0-9]{4})-([0-9]{2})-([0-9]{2})";
char *s = "2010-06-03";

if (retval = regcomp(&rx, pat, REG_EXTENDED)) {

  char buf[200];

  regerror(retval, &rx, buf, 200);
  fprintf(stderr, "Regex error: %s\n", buf);
}
else {

  /* first match is entire pattern */
  regmatch_t matches[4];

  if (regexec(&rx, s, 4, matches, 0) == 0) {

    char yr[5];
    regmatch_t rm = matches[1];

    /* rm_so and rm_eo contain index of start and end of
       match; they are set to -1 if unused */

    strncpy(yr, s + rm.rm_so, rm.rm_eo - rm.rm_so);
    yr[5] = '\0';

    printf("year is %s\n", yr);
  }

  regfree(&rx);
}
dates and time
c go
unix epoch type time_t
broken down type struct tm Time
current unix epoch time_t now;

if (time(&now) == -1) {
  perror("time failed");
}
import "time"

t := time.Now()
current broken-down date/time
date and time to string
format date
parse date
convert to string
 
char *s;

/* ctime returns pointer to statically allocated memory */
if ((s = ctime(&now)) == NULL) {
  fputs("ctime failed.");
}
date subtraction
add duration
date parts
time parts
build broken-down date and time
how localtime is determined
time zone info
name and utc offset in hours
daylight savings test
nonlocal time zone
microseconds
sleep #include <unistd.h>

/* seconds */
int retval = sleep(10);
if (retval != 0) {
  printf("interupted with %d s to go", retval);
}

/* microseconds */
if (usleep(10000)) {
  perror("usleep failed");
}
timeout
cpu usage #include <sys/times.h>
#include <unistd.h>  /* sysconf */

struct tms start, end;

double ticks_per_s = (double)sysconf(_SC_CLK_TCK);

clock_t start_wall = times(&start);

if (start_wall < 0) {
  fputs("times failed", stderr);
  return (1);
}

int i;
for (i = 0; i < 1000 * 1000 * 1000; ++i) {
  /* empty loop */
}

clock_t end_wall = times(&end);

if (end_wall < 0) {
  fputs("times failed", stderr);
  return (1);
}

clock_t wall = end_wall - start_wall;
clock_t user = end.tms_utime - start.tms_utime;
clock_t system = end.tms_stime - start.tms_stime;

printf("wall: %f s\n", wall / ticks_per_s);
printf("user: %f s\n", user / ticks_per_s);
printf("system: %f s\n", system / ticks_per_s);
arrays
c go
declare int a[10];
allocate on stack int a[10];
allocate on heap #include <stdlib.h>

int *a = calloc(10, sizeof(int));
free heap free(a);
literal int a[] = {1, 2, 3}; a := []int{1, 2, 3}
size
 
none len(a)
lookup
 
a[0] a[0]
update a[0] = 4;
out-of-bounds behavior undefined, possible SIGSEGV panic: index out of range

if compiler detects a problem the code won't compile
element index char *a[3] = {"foo", "bar", "baz"};
int loc = -1, i;

for (i = 0; i < 3; ++i) {
  if (strcmp("bar", a[i]) == 0) {
    loc = i;
    break;
  }
}
slice int *a2;

a2 = a[2];
slice to end
manipulate back
manipulate front
concatenate
copy
array as function argument
iterate int a[10];

for (i = 0; i < 10; ++i ) {
  a[i] = i * i;
}
sort int
compare(const void *a, const void *b) {

  if (*(int *)a < *(int *)b) {
    return -1;
  }
    else if (*(int *)a == *(int *)b) {
    return 0;
  }
  else {
    return 1;
  }
}

int a[5] = {6, 8, 10, 9, 7};

/* 2nd arg is array length; 3rd arg is element size */
qsort(a, 5, sizeof(int), &compare);
dictionaries
c go
map declaration gold := make(map[string]int)
map literal gold := map[string]int{
  "France": 7,
  "Spain": 3,
}
map access gold["France"] = 7
fmt.Printf("France: %d\n", gold["France"])
is key present if key not present, val will contain zero value for type and ok will contain false:
val, ok = gold["Norway"]
map remove element delete(gold, "France")
map iterate
functions
c go
define function int add(int n, int m) {
  return n + m;
}
func add(n int, m int) int {
  return n + m
}

// parameters can share type declaration:
func add(n, m int) int {
  return n + m
}
invoke function
 
add(3, 7) add(3, 7)
forward declaration of function float add(float x, float y);

/* if a function invocation is encountered before a
  declaration or a definition, the arguments and the
  return value are assumed to have type 'int' */

printf("%f\n", add(2.2, 3.5));

float add(float x, float y) {
  return x + y;
}
// function can be invoked before definition
fmt.Printf("%f\n", add(2.2, 3.5))

func add(n float32, m float32) float32 {
  return n + m
}
overload function not permitted not permitted
nest function not permitted not permitted
missing argument behavior doesn't compile doesn't compile
extra argument behavior doesn't compile doesn't compile
default value for parameter none none
variable number of arguments #include <stdarg.h>

char* concat(int cnt, ...) {

  int i, len;
  va_list ap;
  char *retval, *arg;

  va_start(ap, cnt);
  for (i = 0, len = 0; i < cnt; i++) {
    len += strlen(va_arg(ap, char*));
  }
  va_end(ap);

  retval = calloc(len + 1, sizeof(char));

  va_start(ap, cnt);
  for (i = 0, len = 0; i < cnt; i++) {
    arg = va_arg(ap, char*);
    strcpy(retval + len, arg);
    len += strlen(arg);
  }
  va_end(ap);

  return retval;
}

char *s = concat(4, "Hello", ", ", "World", "!");
named parameters none
pass by value void use_integer(int i) {
  function body
}

int i = 7;

use_integer(i);
pass by address void use_iptr(int *i) {
  function body
}

int i = 7;

use_iptr(&i);
pass by reference not possible
return value return arg return arg. If return values have names and no arguments are provided to return the values assigned to the return variables are used.
no return value /* declare function void: */
void print_err(char *msg) {
  fprintf(stderr, msg);
}
multiple return values not permitted func divmod(m, n int) (int, int) {
  return m / n, m % n
}

q, r := divmod(7, 3)
named return values none func divmod(m, n int) (q, r int) {
  q = m / n
  r = m % n
  return
}

q, r := divmod(7, 3)
anonymous function literal none
function with private state int
counter() {
  static int n = 0;

  return ++n;
}
function as value int
add(int m, int n) {
  return m + n;
}

/* a function cannot be stored in a variable, but
  its address can */

int (* fp)(int, int) = &add;

printf("1 + 2: %d\n", (*fp)(1, 2));
execution control
c go
for int i, n;

for (i = 1, n = 1; i <= 10; ++i) {
  n *= i;
}
n := 1

for i := 1; i <= 10; i++ {
  n *= i;
}
if if (i > 0) {
  signum = 1;
} else if (i == 0) {
  signum = 0;
} else {
  signum = -1;
}
if x > 0 {
  signum = 1
} else if x == 0 {
  signum = 0
} else {
  signum = -1
}
while int i = 0;

while (i < 10) {

  ++i;
}
i := 0

for i < 10 {
  i++
}
switch switch(i) {
case 0:
  0;
  break;
case 1:
  1;
  break;
default:
  -1;
  break;
}
break/continue
 
concurrency
c go
start thread #include <pthread.h>

typedef struct {
  int id;
} payload;

void*
thread(void* arg) {
  payload* pl = (payload*)arg;
  printf("the value is %d\n", pl->id);
}

pthread_t thr;
payload pl = {3};

if (pthread_create(&thr, NULL, &thread, (void*)&pl)) {
  printf("failed to create thead\n");
  exit(1);
}
terminate current thread #include <pthread.h>

payload pl = {7};

pthread_exit((void*)&pl);
terminate other thread #include <pthread>

pthread_t thr;
payload pl = {3};

if (pthread_create(&thr, NULL, &thread, (void*)&pl)) {
  printf("failed to create thead\n");
  exit(1);
}

sleep(5);

if (pthread_cancel(thr)) {
  printf("failed to cancel thread\n");
  exit (1);
}
list threads no portable way
wait on thread
lock
create message queue
send message
receive message
file handles
c go
standard file handles stdin stdout stderr import "os"

os.Stdin os.Stdout os.Stderr
read line from stdin char *line = NULL;
size_t cap = 0;
ssize_t len;

/* if line is not NULL, it should be memory allocated by
   malloc and the size should be in cap. If size is not
   sufficient getline will call realloc on line */

len = getline(&line, &cap, stdin);

if (len == -1) {
  if (ferror(stdin)) {
    perror("getline err");
  }
  else if (feof(stdin)) {
    fprintf(stderr, "end of file\n");
  }
} else {

  /* use line here */

  free(line);
}
import "bufio"
import "os"

var line string
var err error

b := bufio.NewReader(os.Stdin)

line, err = b.ReadString('\n')

if err != nil {
  os.Stderr.WriteString("error!")
} else {
  // use line here
}
write line to stdout /* returns EOF on error */
int retval = puts("Hello, World!");
import "os"

os.Stdout.WriteString("Hello, World!\n")
write formatted string to stdout
 
printf("count: %d\n", 7); fmt.Printf("count: %d\n", 7)
open file for reading /* returns NULL on error */
FILE *f = fopen("/etc/hosts", "r");
open file for writing /* returns NULL on error */
FILE *f = fopen("/tmp/test", "w");
open file for appending /* returns NULL on error */
FILE *f = fopen("/tmp/err.log", "a");
close file /* returns EOF on error */
int retval = fclose(f);
close file implicitly none defer
i/o errors functions return values such as EOF, NULL, or -1 to indicate error. In some cases errors are not distinguished from end-of-file. The functions ferror() and feof() can be used to test a file handle.

The type of error is stored in
errno. strerror(errno) converts the errors code to a string and perror() writes its argument to stderr with sterror(errno).
read line char line[BUFSIZ];

if (fgets(line, BUFSIZ, f) == NULL) {
  if (ferror(stdin)) {
    perror("getline err");
  }
  else if (feof(stdin)) {
    fprintf(stderr, "end of file\n");
  }

} else {
  if ('\n' == line[strlen(line) - 1]) {

    /* use line here */

} else {
    fprintf(stderr, "long line truncated\n");
}
iterate over file by line
read file into array of strings
read file into string
write string /* returns EOF on error */
int retval = fputs("Hello, World!", f);
write line /* returns EOF on error */
int retval = fputs("Hello, World!\n", f);
flush file handle if (fflush(f) == EOF) {
  perror("fflush failed");
}
end-of-file test
 
feof(f)
get and set file handle position long pos;
if ((pos = ftell(f)) == -1) {
  perror("ftell failed");
}

/* 3rd arg can also be SEEK_CUR or SEEK_END */
if (fseek(f, 0, SEEK_SET) == -1) {
  perror("fseek failed");
}
open unused file #include <limits.h>  /* PATH_MAX */
#include <unistd.h>

char buf[PATH_MAX];

strcpy(buf, "/tmp/foo.XXXXXX");

/* terminal Xs will be replaced: */
int fd = mkstemp(buf);

if (fd != -1) {
  FILE *f = fdopen(fd, "w");

  if (NULL == f) {
    perror("fdopen failed");
  } else {
    /* use f */
  }

} else {
  perror("mkstemp failed");
}
files
c go
file test, regular file test
 
#include <sys/stat.h>
#include <unistd.h>  /* access() */

struct stat buf;

if (access("/tmp/foo", F_OK) >= 0) {
  /* file exists */
}

if (stat("/tmp/foo", &buf) != 0) {
  perror("stat failed");
} else if (S_ISREG(buf.st_mode)) {
  /* file is regular */
}
file size
 
#include <sys/stat.h>

struct stat buf;

if (stat("/tmp/foo", &buf) != 0) {
  perror("stat failed");
} else {
  printf("size: %llu\n", buf.st_size);
}
is file readable, writable, executable #include <unistd.h>

if (access("/etc/hosts", R_OK) != 0) {
  printf("not readable\n");
}
if (access("/etc/hosts", W_OK) != 0) {
  printf("not writable\n");
}
if (access("/etc/hosts", X_OK) != 0) {
  printf("not executable\n");
}
set file permissions #include <sys/stat.h>

if (chmod("/tmp/foo", 0755) == -1) {
  perror("chmod failed");
}
copy file, remove file, rename file /* no copy function in standard library */

if (remove("/tmp/foo")) {
  perror("remove failed");
}

if (rename("/tmp/bar", "/tmp/foo")) {
  perror("rename failed");
}
create symlink, symlink test, readlink #include <limits.h>  /* PATH_MAX */
#include <sys/stat.h>
#include <unistd.h>

if (symlink("/etc/hosts", "/tmp/hosts") == -1) {
  perror("symlink failed");
}

struct stat sbuf;

if (stat("/tmp/hosts", &buf) != 0) {
  perror("stat failed");
} else if (S_ISLNK(buf.st_mode)) {
  /* file is symlink */
}

char pbuf[PATH_MAX + 1];

ssize_t size = readlink("/tmp/hosts", pbuf, PATH_MAX);

if (size >= 0 ) {
  pbuf[size] = 0;
  /* pbuf now contains null-terminated string
     with target path */

}
generate unused file name /* if first argument is NULL, path is in system temp
   directory. Caller should free() return value. */

char *path = tempnam("/tmp", "foo");
file formats
c go
directories
c go
build pathname
dirname and basename #include <libgen.h>

/* return pointers to statically allocated memory
   which is overwritten by subsequent calls */

char *s1 = dirname("/etc/hosts");
char *s2 = basename("/etc/hosts");
import "path"

path.Dir("/etc/hosts")
path.Base("/etc/hosts")
absolute pathname #include <limits.h>

char buf[PATH_MAX];

if (realpath("..", buf) == NULL) {
  perror("realpath failed");
}
else {
  /* use buf */
}
iterate over directory by file #include <dirent.h>

DIR *dir = opendir("/etc");
struct dirent *de;

while (de = readdir(dir)) {
  printf("%s\n", de->d_name);
}

closedir(dir);
glob paths #include <glob.h>

glob_t pglob;
int i;

glob("/etc/*", 0, NULL, &pglob);

for (i = 0; i < pglob.gl_pathc; ++i) {
  printf("%s\n", pglob.gl_pathv[i]);
}

globfree(&pglob);
make directory #include <sys/stat.h>

if (mkdir("/tmp/foo")) {
  fprintf(stderr, "mkdir err: %s\n", strerror(errno));
}
recursive copy
remove empty directory #include <unistd.h>

if (rmdir("/tmp/foo") == -1) {
  perror("rmdir failed");
}
remove directory and contents
directory test
 
#include <sys/stat.h>

struct stat buf;

if (stat("/tmp/foo", &buf) != 0) {
  perror("stat failed");
} else if (S_ISDIR(buf.st_mode)) {
  /* file is directory */
}
generate unused directory #include <limits.h>

char buf[PATH_MAX];

strcpy(buf, "/tmp/fooXXXXXX");

/* terminal Xs will be replaced: */
if (mkdtemp(buf) == NULL) {
  perror("mkdtemp failed");
} else {
  /* use buf */
}
system temporary file directory /* defined in <stdio.h> */
P_tmpdir
processes and environment
c go
signature of main int main(int argc, char **argv) {
first argument
 
pathname of executable
getopt #include <getopt.h>

/* 2nd value indicates whether option takes an argument */
static struct option long_opts[] = {
  {"debug", 0, NULL, 'd'},
  {"threshold", 1, NULL, 't'},
  {0, 0, 0, 0}
};

int debug = 0;
double threshold = 0.0;
char *file = NULL;

int ch;
int opti;
char *endptr;

while (1) {
  ch = getopt_long(argc, argv, "dt:", long_opts, &opti);
  if (-1 == ch) {
    break;
  }

  switch (ch) {
  case 'd':
    debug = 1;
    break;
  case 't':
    threshold = strtod(optarg, &endptr);
    if (*endptr != 0) {
      fprintf(stderr, "expected float: %s\n", optarg);
      exit(1);
    }
    break;
  default:
    fprintf(stderr, "unexpected arg: %d\n", ch);
    exit(1);
  }
}

/* optind is index of 1st arg not consumed by getopt */
if (optind != argc - 1) {
  fputs("USAGE: foo [--multi] [--threshold=NUM] FILE\n",
        stderr);
  exit(1);
}
else {
  file = argv[optind];
}
environment variable #include <stdlib.h>

char *home = getenv("HOME");
setenv("EDITOR", "emacs", 1);
unsetenv("EDITOR");
iterate thru environment variables
get user id and name #include <unistd.h>  /* getlogin */

printf("uid: %d\n", getuid());
printf("username: %s\n", getlogin());
exit /* use 0 for success; 1 through 127 for failure */
exit(1);
executable test #include <unistd.h>

if (access("/bin/ls", X_OK) != 0) {
  printf("not executable\n");
}
external command /* retval of -1 indicates fork or wait failed.
   127 indicates shell failed */

int retval = system("ls -l *");
fork
exec
pipe
wait
get pid, parent pid #include <unistd.h>

/* getpid() and getppid() have return type pid_t */
printf("%d\n", getpid());
printf("%d\n", getppid())
set signal handler #include <signal.h>

void
handle_signal(int signo) {
  switch(signo) {
  case SIGUSR1:
    puts("caught SIGUSR1");
    break;
  default:
    printf("unexpected signal: %s", strsignal(signo));
    break;
  }
}

/*2nd arg can also be SIG_IGN or SIG_DFL */
sig_t prev_handler = signal(SIGUSR1, &handle_signal);

if (prev_handler == SIG_ERR) {
  perror("signal failed");
  exit(1);
}
send signal #include <signal.h>
#include <unistd.h>  /* getppid */

if (kill(getppid(), SIGUSR1) == -1) {
  perror("kill failed");
}
libraries and namespaces
c go
user-defined types
c go
typedef typedef int customer_id;
customer_id cid = 3;
enum enum day_of_week {
  mon, tue, wed, thu, fri, sat, sun
};

enum day_of_week dow = tue;
struct definition struct medal_count {
  const char* country;
  int gold;
  int silver;
  int bronze;
};
type MedalCount struct {
  country string
  gold int
  silver int
  bronze int
}
struct declaration struct medal_count spain;
struct initialization struct medal_count spain = { "Spain", 3, 7, 4};

struct medal_count france = {
  .gold = 8,
  .silver = 7,
  .bronze = 9,
  .country = "France"
};
spain := MedalCount{"Spain", 3, 2, 1}

france := MedalCount{
  bronze: 9,
  silver: 7,
  gold: 8,
  country: "France"}
struct member assignment spain.country = "Spain";
spain.gold = 3;
spain.silver = 7;
spain.bronze = 4;
france := MedalCount{}
france.country = "France"
france.gold = 7
france.silver = 6
france.bronze = 5
struct member access int spain_total = spain.gold + spain.silver + spain.bronze; france_total = france.gold +
  france.silver +
  france.bronze
union definition union perl_scalar {
  char *string;
  long integer;
  double number;
  void *reference;
}
none
union declaration union perl_scalar x; none
union access
 
x.integer = 7; none
macros
c go
net and web
c go
unit tests
c go
unit test example $ sudo apt-get install check

$ cat > check_foo.c
#include <check.h>

START_TEST(test_foo) {
  fail_unless(0, "not true");
}
END_TEST

Suite *
suite_foo(void) {
  Suite *ste = suite_create("suite: foo");
  TCase *tc = tcase_create("case: foo");

  tcase_add_test(tc, test_foo);
  suite_add_tcase(ste, tc);

  return ste;
}

int
main(void) {
  int number_failed;
  Suite *ste = suite_foo();
  SRunner *sr = srunner_create(ste);

  srunner_run_all(sr, CK_NORMAL);
  number_failed = srunner_ntests_failed(sr);
  srunner_free(sr);

  return (number_failed);
}

$ gcc -o check_foo check_foo.c -lcheck

$ ./check_foo
Running suite(s): foo
0%: Checks: 1, Failures: 1, Errors: 0
check_foo.c:4:F:foo:test_foo:0: not equal
equality assertion fail_unless(1 == 2, "integers not equal");

char *s = "lorem";
fail_unless(strcmp(s, "ipsum"), "strings not equal");
setup and teardown
unit test coverage
debugging and profiling
c go
check syntax $ gcc -fsyntax-only foo.c
flag for stronger warnings $ gcc -Wall foo.c
suppress warnings $ gcc -w foo.c
treat warnings as errors $ gcc -Werror foo.c
lint $ sudo apt-get install splint
$ splint foo.c
source cleanup
run debugger $ gcc -g -o foo foo.c
$ gdb foo
debugger commands
help, list source, (re)load executable, next, step, set breakpoint, show breakpoints, delete breakpoint, continue, backtrace, up stack, down stack, print, run, quit
> h
> l [FIRST_LINENO, LAST_LINENO]
> file PATH
> n
> s
> b [FILE:]LINENO
> i
> d NUM
> c
> bt
> up
> do
> p EXPR
> r [ARG1[, [ARG2 ...]]
> q
profile code does not work on Mac OS X
$ gcc -pg -o foo foo.c
$ ./foo
$ gprof foo
memory tool $ sudo apt-get install valgrind
$ gcc -o foo foo.c
$ valgrind foo
multidimensional arrays
c go
2d array literal
vectors
c go
vector literal
element-wise arithmetic operators
result of vector length mismatch
scalar multiplication
dot product
matrices
c go
matrix literal or constructor
multiplication
_________________________________________________________ ________________________________________________________

General

version used

The compiler version used for this cheatsheat.

show version

How to get the compiler version.

implicit prologue

Code which the examples in this sheet assume to have been executed.

c:

A selection of commonly used symbols and macros from the standard C library and the headers in which they are defined according to POSIX:

errno.h stdlib.h stdio.h string.h time.h
errno

ENOENT
ENOMEM
EACCES
EINVAL
EPIPE
abs
drand48
exit
free
getenv
malloc
mkdtemp
putenv
qsort
rand
realpath
srand
strtod
strtol
system
unsetenv
fclose
feof
fflush
fgets
fopen
fprintf
fputs
getc
getline
printf
putc
remove
rename
scanf

BUFSIZ
EOF
NULL
strcat
strchr
strcmp
strcpy
strdup
strerror
strncat
strncmp
strncpy
strndup
strrchr
strstr
strtok
time
time_t

Grammar and Invocation

hello world

How to write, compile, and run a "Hello, World!" program.

file suffixes

The suffixes used for source files, header files, and compiled object files.

block delimiters

statement terminator

end-of-line comment

The syntax for a comment which is terminated by the end of the line.

c:

The // style comment first appeared in the C99 standard.

multiple line comment

The syntax for a comment which can span multiple lines.

Variables and Expressions

null

c:

A typical definition:

#define NULL (void *)0

coalesce

The equivalent of the COALESCE function from SQL.

c:

The short circuit or operator || can be used as a coalesce operator. However, in C, C++, and Objective C, NULL is identical to zero, whereas in databases they are two distinct values.

declare primitive type on stack

How to declare a primitive type on the stack.

allocate primitive type on heap

How to allocate memory for a primitive type on the heap.

free primitive type on heap

How to free the memory for a primitive type that was allocated on the heap.

value of uninitialized types

The value assigned to primitive types that are not explicitly initialized.

constant

How to define a constant.

go:

Multiple constants can be declared in this manner:

const (
  Pi = 3.14
  E = 2.718
)

assignment

The syntax for assigning a value to a variable.

assignment

The syntax for parallel assignment.

swap

How to swap the values in two variables.

compound assignment operators

Arithmetic and Logic

boolean type

c:

The following definitions are common:

typedef int BOOL;
#define TRUE 1
#define FALSE 0

true and false

Literals for the boolean values true and false.

c:

The following definitions are common:

typedef int BOOL;
#define TRUE 1
#define FALSE 0

falsehoods

Values which evaluate as false in the conditional expression of an if statement.

logical operators

The logical operators.

In all languages on this sheet the && and || operators short circuit: i.e. && will not evaluate the 2nd argument if the 1st argument is false, and || will not evaluate the 2nd argument if the 1st argument is true. If the 2nd argument is not evaluated, side-effects that it contains are not executed.

relational operators

Binary operators which return boolean values.

integer type

Signed integer types.

c:

Whether char is a signed or unsigned type depends on the implementation.

unsigned type

Unsigned integer types.

c:

Whether char is a signed or unsigned type depends on the implmentation.

float type

Floating point types.

arithmetic operators

The arithmetic binary operators.

integer division

How to find the quotient of two integers.

integer division by zero

The result of attempting to divide an integer by zero.

c:

The behavior for division by zero is system dependent; the behavior described is common on Unix.

float division

How to perform float division on integers.

float division by zero

The result of attempting to divide a float by zero.

power

How to perform exponentiation.

sqrt

The square root function.

sqrt -1

The result of attempting to find the square root of a negative nubmer.

transcendental functions

The square root function and the transcendental functions.

float truncation

Functions for converting a float to a nearby integer value.

c:

The math.h library also provides floor and ceil which return double values.

absolute value

The absolute value of a numeric.

complex type

Complex floating point types.

complex construction

How to create a complex number.

complex decomposition

How to decompose a complex number into its real and imaginary parts; how to get the argument of a complex number.

random number

How to generate a random integer from a uniform distribution; how to generate a random float from a uniform distribution.

random seed

How to set the random seed.

bit operators

The bit operations: right shift, left shift, and, or, exclusive or, and not.

go:

Note that ^ is bit-not and not exclusive-or like in C.

Strings

string type

The type for a string

char type

The type for a character.

string literal

The syntax for a string literal.

newline in string literal

Can newlines be included in string literals?

string escapes

Escape sequences in string literals.

allocate string

string length

string comparison

c:

Returns 1, 0, or -1 depending upon whether the first string is lexicographically greater, equal, or less than the second. The variants strncmp, strcasecmp, and strncasecmp can perform comparisons on the first n characters of the strings or case insensitive comparisons.

to C string

numeric conversion

c:

strtoimax, strtol, strtoll, strtoumax, strtoul, and strtoull take three arguments:

intmax_t
strtoimax(const char *str, char **endp, int base);

The 2nd argument, if not NULL, will be set to first character in the string that is not part of the number. The 3rd argument can specify a base between 2 and 36.

strtof, strtod, and strtold take three arguments:

double
strtod(const char *str, char **endp);

split

join

concatenate

substring

index

sprintf

uppercase

lowercase

trim

pad

Regular Expressions

metacharacters

The list of regular expression metacharacters.

A regular expression that does not contain any metacharacters matches itself as a string.

character class abbrevations

Abbreviations for character classes.

c:

regex.h (POSIX 2008)

We describe the regex library which is mandated by POSIX.

The PCRE library is available or easily installed on most systems and provides Perl style regular expressions. In particular PCRE has these character class abbreviations: \d \D \h \H \s \S \v \V \w \W.

To install PCRE on Ubuntu and read the documentation:

$ sudo apt-get install pcre

$ man pcre

To include the PCRE definitions in a C file:

#include <pcre.h>

anchors

Metacharacters for matching locations in the string which aren't single characters or substrings.

match test

How to test whether a string matches a regular expression.

case insensitive match test

How to test whether a string matches a regular expression in a case insensitive manner.

modifers

Modifers which can be used to customize the behvaior of a regular expression.

substitution

How to replace the part of a string matching a regular expression.

group capture

How to use a regular expression to parse a string.

Dates and Time

date/time type

date/time difference type

current date/time

unix epoch

convert to string

strftime

date parts

time parts

build date/time from parts

Arrays

declare

How to declare an array variable.

allocate on stack

How to allocate an array on the stack.

allocate on heap

How to allocate an array on the heap.

free heap

How to free an array that was allocated on the heap.

literal

Syntax for an array literal.

size

How many elements are stored in an array.

lookup

How to get an element by index.

c:

Arrays can be manipulated with pointer syntax. The following sets x and y to the same value:

int a[] = {3,7,4,8,5,9,6,10};
int x = a[4];
int y = *(a+4);

update

How to set or change the element stored at an index.

out-of-bounds behavior

What happens when an attempt is made to access an element at an invalid index.

element index

slice

slice to end

manipulate back

manipulate front

concatenate

copy

array as function argument

iterate

How to iterate over the elements of an array.

c:

C arrays do not store their size; if needed the information can be stored in a separate variable. Another option is to use a special value to mark the end of the array:

char *a[] = { "Bob", "Ned", "Amy", NULL };
int i;
for (i=0; a[i]; i++) {
  printf("%s\n", a[i]);
}

sort

How to sort the elements of an array.

Dictionaries

map declaration

c:

For those interested in an industrial strength hashtable implementation for C, here is the header file and the source file for the hashtable used by Ruby.
For those interested in a "Computer Science 101" implementation of a hashtable, here is a simpler source file and header file.

map access

map size

map remove

map element not found result

map iterator

Functions

define function

How to define a function.

invoke function

How to invoke a function.

forward declaration of function

How to declare a function without defining it.

overload function

How to define multiple functions with the same name. The functions differ in either the number or type of arguments.

nest function

How to define a function inside another function.

missing argument behavior

What happens when a function is invoked with too few arguments.

extra argument behavior

What happens when a function is invoked with too many arguments.

default value for parameter

variable number of arguments

c:

The stdarg.h library supports variable length functions, but provides no means for the callee to determine how many arguments were provided. Two techniques for communicating the number of arguments to the caller are (1) devote one of the non-variable arguments for the purpose as illustrated in the table above, or (2) set the last argument to a sentinel value as illustrated below. Both techniques permit the caller to make a mistake that can cause the program to segfault. printf uses the first technique, because it infers the number of arguments from the number of format specifiers in the format string.

char* concat(char* first,  ...) {

  int len;
  va_list ap;
  char *retval, *arg;

  va_start(ap, first);
  len = strlen(first);

  while (1) {
    arg = va_arg(ap, char*);
    if (!arg) {
      break;
    }
    len += strlen(arg);
  }

  va_end(ap);

  retval = calloc(len+1,sizeof(char));

  va_start(ap, first);

  strcpy(retval, first);
  len = strlen(first);

  while (1) {
    arg = va_arg(ap, char*);
    if (!arg) {
      break;
    }
    printf("copying %s\n", arg);
    strcpy(retval+len, arg);
    len += strlen(arg);
  }

  va_end(ap);

  return retval;
}

An example of use:

string *s = concat("Hello", ", ", "World", "!", NULL);

named parameters

pass by value

pass by address

pass by reference

return value

How the return value for a function is determined.

no return value

How to define a function with no return value.

multiple return values

How to return multiple values.

named return values

How to return values by assigning values to variables.

anonymous function literal

function with private state

function as value

Execution Control

for

if

c:

The curly braces surrounding an if or else clause are optional if the clause contains a single statement. The resulting dangling else ambiguity is resolved by setting the value of c to 2 in the following code:

int a = 1;
int b = -1;
int c = 0;
if (a > 0)
if (b > 0)
  c=1;
else
  c= 2;

while

c:

If the body of a while loop consists of a single statement the curly braces are optional:

int i = 0;
while (i<10)
  printf("%d\n", ++i);

switch

A switch statement branches based on the value of an integer or an integer expression. Each clause must be terminated by a break statement or execution will continue into the following clause.

break/continue

Concurrency

File Handles

standard file handles

The file handles for standard input, standard output, and standard error.

c:

POSIX systems provide processes with the ability to open multiple files and manipulate them with via integers called file descriptors. Normally the integers 0, 1, and 2 refer to standard input, standard output, and standard error. The header <unistd.h> defines the macros STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO for these file descriptors.

System calls take file descriptors as arguments, but the C standard library provides an alternate set functions for buffered I/O. The standard library functions use FILE structs to identify streams and open files.

read line from stdin

How to read a line from standard input.

write line to stdout

How to write a line to standard output.

write formatted string to stdout

How to print a formatted string to standard out.

c:

The printf man page describes the notation used in C style format strings.

open file for reading

How to open a file for reading.

open file for writing

How to open a file for reading.

open file for appending

How to open a file for appending.

close file

How to close a file handle.

close file implicitly

i/o errors

read line

iterate over file by line

read file into array of strings

read file into string

write string

write line

flush file handle

end-of-file test

get and set file handle position

open unused file

How to open a file with a previously unused file name.

c:

The function mkstemps can be used to create a new file with a fixed suffix: "/tmp/fooXXXXXXsuffix".

Files

file test, regular file test

Does the file exist; is the file a regular file.

file size

The size of the file in bytes.

is file readable, writable, executable

Can the process read, write, or executable the file?

c:

access returns 0 if the process has the permission, and -1 if it doesn't or some other error occurred.

access uses the real user id to determine permission even though the kernel uses the effective user id.

set file permissions

copy file, remove file, rename file

create symlink, symlink test, readlink

generate unused file name

File Formats

Directories

build pathname

dirname and basename

absolute pathname

iterate over directory by file

glob paths

make directory

recursive copy

remove empty directory

remove directory and contents

directory test

generate unused directory

system temporary file directory

Processes and Environment

signature of main

first argument

c:

The first argument is the pathname to the executable. Whether the pathname is absolute or relative depends on how the executable was invoked. If the executable was invoked via a symlink, then the first argument is the pathname of the symlink, not the executable the symlink points to.

environment variable

iterate thru environment variables

exit

How to set the exit status and cause the process to exit.

c:

On POSIX systems zero indicates success and other values indicate failure.

On Linux and Mac OS X the value returned to the parent is exit_arg & 0377. If the process exited because of a signal, the kernel sets the exit status to 128 plus the signal number. The signals are numbered starting from 1, leaving exit status values from 1 to 127 and perhaps 128 available for other failure conditions.

The C standard library defines the values EXIT_SUCCESS and EXIT_FAILURE as an aid for writing code which is portable to systems which do not use 0 to indicate success.

Libraries and Namespaces

User-Defined Types

typedef

c:

Because C integer types don't have well defined sizes, typedef is sometimes employed to as an aid to writing portable code. One might include the following in a header file:

typedef int int32_t;

The rest of the code would declare integers that need to be 32 bits in size using int32_t and if the code needed to be ported to a platform with a 16 bit int, only a single place in the code requires change. In practice the typedef abstraction is leaky because functions in the standard library such as atoi, strtol, or the format strings used by printf depend on the underlying type used.

enum

c:

Enums were added to the C standard when the language was standardized by ANSI in 1989.

An enum defines a family of integer constants. If an integer value is not explicitly provided for a constant, it is given a value one greater than the previous constant in the list. If the first constant in the list is not given an explicit value, it is assigned a value of zero. it is possible for constants in a list to share values. For example, in the following enum, a and c are both zero and b and d are both one.

enum { a=0, b, c=0, d };

A typedef can be used to make the enum keyword unnecessary in variable declarations:

typedef enum { mon, tue, wed, thu, fri, sat, sun } day_of_week;
day_of_week d = tue;

From the point of view of the C compiler, an enum is an int. The C compiler does not prevent assigning values to an enum type that are not in the enumerated list. Thus, the following code compiles:

enum day_of_week { mon, tue, wed, thu, fri, sat, sun };
day_of_week d = 10;

typedef enum { mon, tue, wed, thu, fri, sat, sun } day_of_week2;
day_of_week2 d2 = 10;

struct definition

A struct provides names for elements in a predefined set of data and permits the data to be accessed directly without the intermediation of getters and setters. C++, Java, and C# classes can be used to define structs by making the data members public. However, public data members violates the uniform access principle.

struct declaration

struct initialization

c:

The literal format for a struct can only be used during initialization. If the member names are not provided, the values must occur in the order used in the definition.

struct member assignment

struct member access

c:

The period operator used for member access has higher precedence than the pointer operator. Thus parens must be used
to get at the member of a struct referenced by a pointer:

struct medal_count {
char* country;
int gold;
int silver;
int bronze;
}

struct medal_count spain = { "Spain", 3, 7 4 };
struct medal_count *winner = &spain;
printf("The winner is %s with %d gold medals", (*winner).country, (*winner).gold);

ptr->mem is a shortcut for (*ptr).mem:

printf("The winner (%s) earned %d silver medals", winner->country, winner->silver);

union definition

union access

Macros

Net and Web

Unit Tests

Debugging and Profiling

Multidimensional Arrays

Vectors

Matrices

C

ANSI C Standard 1990
ANSI C Standard (pdf) 1999
C Standard Library
POSIX Library C Headers
Linux System Call Man Pages
Linux Subroutine Man Pages
C Standard Library
GNU C Library

Go

Language Specification
Package Reference

content of this page licensed under creative commons attribution-sharealike 3.0