Ben Bacarisse said:
Bill Cunningham said:
I am not quite sure what is going on here but this is my tested
and compiled code. As written below at compile time I get this
warning.
p.c: In function `main':
p.c:9: warning: assignment makes pointer from integer without a cast
I don't see the int in this code.
#include <stdio.h>
#include <string.h>
int main(void)
{
char p[] = "hello to all";
char *a;
printf("%s\n", p);
printf("%s\n", a = strfry(p)); //error on this line.
return 0;
}
strfry() is a GNU extension. It takes a char* as is sole argument
and returns a char*.
An undeclared function is assumed to return int.
In C90. C99, dropped implicit int, so attempting to call an
undeclared function is a constraint violation.
"gcc -std=c99" gives:
c.c: In function 'main':
c.c:9:5: warning: implicit declaration of function 'strfry'
c.c:9:22: warning: assignment makes pointer from integer without a
cast
(Yes, it's still following the C90 implicit int rule, but that's ok as
long as it always warns about constraint violations.)
string.h is not
declaring strfry so the compiler assumes it returns an it and
complains when you assign the result to a char * variable.
Right.
The man page (or some other documentation) should tell you how to get
strfry declared properly. Adding -D_GNU_SOURCE to the compile line
works for me.
In fact, the man page says:
#define _GNU_SOURCE
#include <string.h>
char *strfry(char *string);
where "#define _GNU_SOURCE" in the source is equivalent to
"-D_GNU_SOURCE" on the command line.
*Never* use a function you're not completely familiar with without
first reading the documentation.
Now if I change that char p[] to a char *p I get a
segmentation fault. What's up with that?
p then points to the string rather than being an array initialised by
it. The content of strings can't be modified, so passing p to any
function that tried to alter its contents gives rise to undefined
behaviour. A segmentation fault is a Good Result for undefined
behaviour.
Correction: the contents of string *literals* can't be modified.
More precisely, the contents of the array (which exists at run
time) which is associated with a string literal (which exists
only in your program source file) can't be modified. Even more
precisely, "can't be modified" means that attempting to modify them
is undefined behavior; an implementation could permit modifications,
but it wouldn't be doing you any favors.
This is an odd corner case. It would have made more sense for
string literals to be "const", so the compiler would (usually)
warn you about attempts to modify them, but that would have broken
a lot of pre-ANSI C code. C++, with less concern about backward
compatibility, does make string literals "const".