On Tuesday 2008-12-16 17:05, Michel Van den Bergh wrote: > Hi, > > The following program segfaults when compiled with gcc > but runs fine when compiled with g++ or icc (the intel C compiler) > > #include <stdio.h> > struct Hello { > char world[20]; > }; > struct Hello s(){ > struct Hello r; > r.world[0]='H'; > r.world[1]='\0'; > return r; > } > > int main(){ > printf("%s\n",s().world); > } > > Assigning s() to a variable and then using the variable avoids the segfault.
Had you compiled with -Wall would you have noticed: e.c:13: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char[20]’ And when there is a type mismatch, a crash is pretty likely. Not that I can say why gcc does not convert it to char* but g++ does. Now what happens? The following augmented snippet shows it: ---<8--- #include <stdarg.h> #include <stdio.h> #include <string.h> struct Hello { char world[20]; }; struct Hello s(void) { struct Hello r; strcpy(r.world, "Hello"); return r; } static void dump(const char *fmt, ...) { va_list argp; va_start(argp, fmt); char *p = va_arg(argp, char *); printf("%p\n", p); va_end(argp); } int main(void) { dump("", s().world); return 0; } --->8--- I get 0x6c6c6548, which is obviously part of the string Hello. So passing a char[20] into a varargs function seems not to convert it to char* when done through a non-visibile temporary (the result of s() is hidden on the stack of main).