I'm reading Brian W Kernighan and Dennis M Ritchie The C Programming Language, 2nd Edn and practicing using function pointers. I've implemented one of the examples from the book. I kept getting a segfault when addressing some of the functions.
After stepping through it with gdb I realized that when passing a function address to a pointer the pointer remained null, but only for some of the functions. Adding the & operator to the function names causing the error fixed the issue.
I've read everywhere that functions can be addressed by their name with or without the & operator. I cannot figure out why these functions required it. Or could it have something to do with the way I was assigning it?
EDIT: I understand the code is quite buggy. I was just doing a quick exercise from an old book. I will work on minimizing it. I'm just confused why when I step through the program with gdb fp
remains null (without the &
)after the assignment on lines 20 and 25 while on lines 27 and 29 fp
does take get assigned the addresses.
#include <stdio.h>
#include <string.h>
#define MAXLINES 5000
char *lineptr [MAXLINES];
int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);
void my_qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *));
int numcmp(char *, char *);
int reva(char *, char *);
int revn(char *, char *);
int main(int argc, char **argv) {
int nlines;
int numeric = 0;
int (*fp)(void*, void*) = &strcmp;
if(argc > 1) {
for(int i = argc; i > 1; i--) {
if(strcmp(argv[i-1], "-n") == 0)
fp = &numcmp;
else if(strcmp(argv[i-1], "-r") == 0)
fp = reva;
else if(strcmp(argv[i-1], "-rn") == 0 || strcmp(argv[i-1], "-nr") == 0)
fp = revn;
else {
printf("error: invalid modifier [%s]\n", argv[i-1]);
return -1;
}
}
}
if((nlines = readlines(lineptr, MAXLINES)) >= 0) {
my_qsort((void **) lineptr, 0, nlines-1, fp);
writelines(lineptr, nlines);
return 0;
} else {
printf("input too big to sort\n");
return 1;
}
}
void my_qsort(void *v[], int left, int right, int (*comp)(void *, void *)) {
int i, last;
void swap(void *[], int, int);
if (left >= right)
return;
swap(v, left, (left+right)/2);
last = left;
for(i = left+1; i <= right; i++)
if((*comp)(v[i], v[left]) < 0)
swap(v, ++last, i);
swap(v, left, last);
my_qsort(v, left, last-1, comp);
my_qsort(v, last+1, right, comp);
}
#include <stdlib.h>
int numcmp(char *s1, char *s2) {
double v1, v2;
v1 = atof(s1);
v2 = atof(s2);
if(v1 < v2)
return -1;
else if(v1 > v2)
return 1;
else
return 0;
}
int reva(char *s1,char *s2) {
return -strcmp(s1, s2);
}
int revn(char *s1, char *s2) {
return -numcmp(s1, s2);
}
void swap(void *v[], int i, int j) {
void *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
lines.c
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "get_line.h"
#define MAXLEN 1000 // max length of any input line
char *alloc(int);
// readlines: read input lines
int readlines(char *lineptr[], int maxlines) {
int len, nlines;
char line[MAXLEN];
char lines[maxlines*MAXLEN];
char *plines = lines;
nlines = 0;
while((len = get_line(line, MAXLEN)) > 0)
if(nlines >= maxlines)
return -1;
else {
line[len-1] = '\0'; // delete newline
strcpy(plines, line);
lineptr[nlines++] = plines;
plines += len;
}
return nlines;
}
// writelines: write output lines
void writelines(char *lineptr[], int nlines) {
int i;
for(i = 0; i < nlines; i++)
printf("%s\n", lineptr[i]);
}
get_line.c
#include <stdio.h>
#include "get_line.h"
//getline: get line into line[]; return length
int get_line(char line[], int lim) {
int c, i;
i = 0;
while(--lim > 0 && (c = getchar()) != EOF && c != '\n') {
line[i++] = c;
}
if(c == '\n') {
line[i++] = c;
}
line[i] = '\0';
return i;
}