I'm learning C by reading K&R (ANSI edition), supplemented with 21st Century C. I'd say I'm already pretty confident with most of the fundamentals of pointers. That means I know you have to be very careful passing pointers out of a function that weren't either passed into it in the first place or malloc
ed. So this example has me stumped. It's from §5.6, page 109:
#define MAXLEN 1000 /* max length of any input line */
int getline(char *, int);
char *alloc(int);
/* readlines: readinputlines */
int readlines(char *lineptr[], int maxlines)
{
int len, nlines;
char *p, line[MAXLEN];
nlines = 0;
while ((len = getline(line, MAXLEN)) > 0)
if (nlines >= maxlines || (p = alloc(len)) == NULL)
return -1;
else {
line[len-1]='\0'; /* delete newline */
strcpy(p, line);
lineptr[nlines++] = p;
}
return nlines;
}
strcpy()
was previously defined as:
/* strcpy: copy t to s; pointer version 3 */
void strcpy(char *s, char *t)
{
while (*s++ = *t++)
;
}
I don't understand how the memory pointed to by p
can remain in scope once the function returns. Here's what I do understand. The pointer p
is declared within the function - so it's in automatic memory. As for what it's pointing to, it's not explicitly assigned any memory. Then when strcpy
is called, values are copied from line
to wherever p
points to.
I've also reached the point in 21st Century C which discusses the dangers of pointers, and gives examples that attempting to pass an array declared in automatic memory out of a function is definitely not OK. (p. 109: "A pointer to a block of memory that has already been automatically freed is worse than useless.") So the only way I can understand the above code being valid is that by declaring p
not as an array where a memory block is explicitly allocated in automatic memory, but rather as a pointer, its memory allocation is somehow implicitly handled in some other way. Is that correct? How does the memory allocation work?
Note: By reading 21st Century C I'm attempting to neutralise whatever bad practices K&R might introduce me to. I understand that it's not the best standard to go by, and probably I will never end up writing code in the way demonstrated in this example. But I would still like to understand it.