1
votes

I have something along the lines of:

#include <stdio.h>
typedef struct {
char s[100];
} literal;

literal foo()
{
return (literal) {"foo"};
}

int main(int argc, char **argv) {
    printf("%s", foo().s);
    return 0;
}

And I get this error when compiling it (with gcc):

warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char[100]’ [-Wformat=]

any1 has any ideas on how I can fix it? And what is wrong with that function return type?

EDIT The problem (if not clear in the discussion) was the c standard gcc was using to compile the file. if you use -std=c99 or -std=c11 it works.

2
there seems to be tons of error in your code. please explain what you are trying to do with your codeHaris
It's a compilers project where I need to generate some c code. Everything works except using that literal return type there. If you could point out where you see these tons of errors it'd be something.PHMitrious
What's the meaning of this line ? 'return (literal) {"foo"};'ThisaruG
(literal){"foo";} just encapsulates the string "foo" in a literal struct, not much more that that. I just return the struct.PHMitrious
I was able to build it with other compilers as well, but it's for a school project and my professor will use gcc, so I need to make it work there :(PHMitrious

2 Answers

5
votes

It is not an error but a warning, not all warnings that -Wall produces are sensible.

Here the compiler is "kind-of" right: before evaluation your argument is an array and not a pointer, and taking the address of a temporary object is a bit dangerous. I managed to get rid of the warning by using the pointer explicitly

printf("%s\n", &foo().s[0]);

Also you should notice that you are using a rare animal, namely an object of temporary lifetime, the return value or your function. Only since C99, there is a special rule that allows to take the address of such a beast, but this is a corner case of the C language, and you would probably be better off by using some simpler construct. The lifetime of the pointer ends with the end of the expression. So if you would try to assign the pointer to a variable, say, and use it later on in another expression, you would have undefined behavior.

Edit(s): As remarked by mafso in a comment, with C versions from before C99, it was not allowed to take the address of the return value of the function. As Pascal Cuoq notes, the behavior of your code is undefined even for C99, because between the evaluation of the arguments and the actual call of the function there is a sequence point. C11 rectified this by indroducing the object of temporary lifetime that I mentioned above.

-1
votes

I don't exactly why maybe someone with more knowledge in C than me can explain it but writing main() on this way:

int main(int argc, char **argv) {
    literal b = foo();
    printf("%s", b.s);
    return 0;
}

The code prints "foo" correctly on GCC 4.5.4