ch06/alloc_cost.c41 lines
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 1000000
int main(void) {
clock_t t0 = clock();
double **each = malloc(N * sizeof *each); /* N separate blocks */
if (each == NULL) {
return 1;
}
for (size_t i = 0; i < N; i++) {
each[i] = malloc(sizeof **each);
if (each[i] == NULL) {
while (i > 0) {
free(each[--i]);
}
free(each);
return 1;
}
*each[i] = 20.0;
}
for (size_t i = 0; i < N; i++) {
free(each[i]);
}
free(each);
clock_t t1 = clock();
double *one = malloc(N * sizeof *one); /* one block */
if (one == NULL) {
return 1;
}
for (size_t i = 0; i < N; i++) {
one[i] = 20.0;
}
free(one);
clock_t t2 = clock();
printf("N separate blocks: %.1f ms\n", 1000.0 * (t1 - t0) / CLOCKS_PER_SEC);
printf("one block: %.1f ms\n", 1000.0 * (t2 - t1) / CLOCKS_PER_SEC);
return 0;
}
ch06/batch.c40 lines
#include <stdio.h>
#include <stdlib.h>
#define LINE_CAP 64
/* Ownership: on success returns a block of *count doubles that the
* CALLER owns. Returns NULL on bad input or if memory runs out. */
double *load_values(FILE *in, size_t max, size_t *count) {
double *vals = malloc(max * sizeof *vals);
char *line = malloc(LINE_CAP);
if (vals == NULL || line == NULL) {
free(vals);
free(line);
return NULL;
}
size_t n = 0;
while (n < max && fgets(line, LINE_CAP, in) != NULL) {
char *end;
vals[n] = strtod(line, &end);
if (end == line) { /* not a number */
fprintf(stderr, "bad line %zu\n", n + 1);
free(line);
return NULL;
}
n++;
}
free(line);
*count = n;
return vals;
}
int main(void) {
size_t n = 0;
double *vals = load_values(stdin, 1440, &n); /* main owns */
if (vals == NULL) {
return 1;
}
printf("loaded %zu, first %.2f\n", n, n > 0 ? vals[0] : 0.0);
free(vals);
return 0;
}
ch06/batch_failk.c46 lines
#include <stdio.h>
#include <stdlib.h>
#define LINE_CAP 64
static long fail_at = 0, alloc_count = 0;
static void *stn_malloc(size_t size) {
alloc_count++;
return alloc_count == fail_at ? NULL : malloc(size);
}
/* Ownership: on success returns a block of *count doubles that the
* CALLER owns. Returns NULL on bad input or if memory runs out. */
double *load_values(FILE *in, size_t max, size_t *count) {
double *vals = stn_malloc(max * sizeof *vals);
char *line = stn_malloc(LINE_CAP);
if (vals == NULL || line == NULL) {
free(vals);
free(line);
return NULL;
}
size_t n = 0;
while (n < max && fgets(line, LINE_CAP, in) != NULL) {
char *end;
vals[n] = strtod(line, &end);
if (end == line) { /* not a number */
fprintf(stderr, "bad line %zu\n", n + 1);
free(line);
return NULL;
}
n++;
}
free(line);
*count = n;
return vals;
}
int main(int argc, char **argv) {
fail_at = argc > 1 ? strtol(argv[1], NULL, 10) : 0;
size_t n = 0;
double *vals = load_values(stdin, 1440, &n); /* main owns */
if (vals == NULL) {
return 1;
}
printf("loaded %zu, first %.2f\n", n, n > 0 ? vals[0] : 0.0);
free(vals);
return 0;
}
ch06/heap_year.c33 lines
#include <stdio.h>
#include <stdlib.h>
#define YEAR_READINGS 2102400 /* 4 sensors x 525,600 minutes */
/* Ownership: returns a heap block of n doubles that the CALLER
* owns and must free. Returns NULL if memory is not available. */
double *make_series(size_t n) {
double *p = malloc(n * sizeof *p);
if (p == NULL) {
return NULL;
}
for (size_t i = 0; i < n; i++) {
p[i] = 20.0 + (double)(i % 10) / 10.0;
}
return p;
}
int main(void) {
double *year = make_series(YEAR_READINGS); /* main owns */
if (year == NULL) {
fprintf(stderr, "out of memory\n");
return 1;
}
double sum = 0.0;
for (size_t i = 0; i < YEAR_READINGS; i++) {
sum += year[i];
}
printf("mean = %.2f over %d readings\n", sum / YEAR_READINGS,
YEAR_READINGS);
free(year); /* the owner frees, once */
return 0;
}
ch06/opening.c45 lines
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int cmp_double(const void *a, const void *b) {
double x = *(const double *)a, y = *(const double *)b;
return (x > y) - (x < y);
}
/* Writes the median of vals[0..n-1] to *out. Returns 0, or -1
* if a reading is NaN (a faulty sensor). vals is borrowed. */
int stn_median(const double *vals, size_t n, double *out) {
double *copy = malloc(n * sizeof *copy);
if (copy == NULL) {
return -1;
}
memcpy(copy, vals, n * sizeof *copy);
for (size_t i = 0; i < n; i++) {
if (isnan(copy[i])) {
return -1; /* sensor fault */
}
}
qsort(copy, n, sizeof *copy, cmp_double);
*out = copy[n / 2];
free(copy);
return 0;
}
int main(int argc, char **argv) {
double day[1440];
for (size_t i = 0; i < 1440; i++) {
day[i] = 15.0 + (double)(i % 60) / 10.0;
}
if (argc > 1 && strcmp(argv[1], "fault") == 0) {
day[700] = NAN; /* simulate a fault */
}
double m;
if (stn_median(day, 1440, &m) == 0) {
printf("median %.2f\n", m);
} else {
printf("sensor fault\n");
}
return 0;
}