3

I have come across this discussion lately, where an array member of a returned struct is passed to another function directly and causes a crash.

Basically, we have a function returning an object of type struct S (which contains an array), and call another function with the array element of that object:

#include <stdio.h>
#include <stdlib.h>

struct S
{
    char array[10];
};

struct S func (void)
{
    struct S s;

    s.array[0] = 'H';
    s.array[1] = 'e';
    s.array[2] = 'l';
    s.array[3] = 'l';
    s.array[4] = 'o';
    s.array[5] = '\0';

    return s;
}

int main (int argc, char ** argv)
{
    printf("%s\n", func().array);

    return EXIT_SUCCESS;
}

While it was pointed out in the mentioned discussion that the problem lies in accessing the result of the call to func() after the next sequence point, it is not clear to me why the following then works without crashing on my machine:

#include <stdio.h>
#include <stdlib.h>

struct S
{
    char array[10];
};

struct S func (void)
{
    struct S s;

    s.array[0] = 'H';
    s.array[1] = 'e';
    s.array[2] = 'l';
    s.array[3] = 'l';
    s.array[4] = 'o';
    s.array[5] = '\0';

    return s;
}

int main (int argc, char ** argv)
{
    printf("%s\n", &func().array[0]);

    return EXIT_SUCCESS;
}

As opposed to the first example (which leads to the warning format '%s' expects argument of type 'char *', but argument 2 has type 'char[10]' [-Wformat=]), the second example compiles without any issues - but anyway, the result of the call to func() is accessed after the next sequence point, and therefore, according to the mentioned discussion, this should be undefined behaviour.

So I am wondering if either the second example running on my machine without crash is just luck, or if there is another point that comes into play here - maybe my understanding of why the first one crashes is just wrong, and what has been described in this answer of another related discussion is of more relevance here.

Edit (to clarify with respect to possible duplicate):

I am aware of this answer (1), and I also have read this answer (2) from a related discussion. However, I think both address different aspects corresponding to the topic I have opened: While (1) talks about undefined behaviour due to accessing the result of a function after the next sequence point, (2) talks about undefined behaviour due to having an array of value type (as opposed to lvalue type).

So, while it is obvious that example one is undefined behaviour, the main focus is on example two: As already mentioned, this runs without crashing on my machine. I am totally aware of this fact not being any evidence for the abscence of undefined behaviour - however, it is at least worth thinking about the abscence of undefined behaviour in that case. Furthermore, I do not see how the accepted answer in (1) would answer my question with respect to incorporation of points mentioned in (2) into this issue: It would be interesting to know if the fact that in my second example a pointer to char is used instead of an array type actually makes any difference with respect to the language rules.

Anyway, I assume that my second example also violates both constraints mentioned in (1) and in (2), but other opinions on this would be appreciated.

Community
  • 1
  • 1
FreakinGeek
  • 51
  • 1
  • 6
  • "The code compiles" does not imply it is correct. I'm voting to close as dup, because the accepted answer it the original question also answers this and they are basically the same. You should have asked for clarification in a comment if something still was unclear. – too honest for this site Jul 03 '16 at 19:39
  • Possible duplicate of [printing a member of a returned struct](http://stackoverflow.com/questions/7963813/printing-a-member-of-a-returned-struct) – too honest for this site Jul 03 '16 at 19:39
  • You have said it is undefined behaviour. But that does not guarantee malfunction until you present the demo for funding. It's like asking for an explanation of why your car did not roll away after leaving it with the parking brake off. It was just lucky. – Weather Vane Jul 03 '16 at 19:51
  • @Olaf Never claimed that passing compilation is an indicator for correct code. But I agree that it might have been an option to put my question as a comment in the original discussion. However, as my post is not only related to [printing a member of a returned struct](http://stackoverflow.com/questions/7963813/printing-a-member-of-a-returned-struct), but also to [Returning struct containing array](http://stackoverflow.com/questions/8774753/returning-struct-containing-array), I decided to better open a new question and somehow fuse the findings from both. – FreakinGeek Jul 03 '16 at 21:01
  • "As opposed ... the second example compiles without any issues ..." can very well be interpreted like that. Anyway, I disagree this is a different question. No offence, but beginners tend to think every slight variation is different. They just don't have the whole picture. That's exactly why they should learn C from a good book first. While the language looks simple at a first glance, it has more traps and pitfalls than an Indiana Jones movie. – too honest for this site Jul 04 '16 at 05:47
  • Well, I really would not consider me as a beginner. Also, I doubt that any C text book (and even more not such for beginners) covers stuff like sequence points or undefined behaviour due to non-lvalue expressions of array type to a reasonable degree - but of course I have nothing against proving me wrong here and pointing out some helpful reference apart from the standard. Anyway, even the answers to the questions I linked to talk about "corner cases" of the language... – FreakinGeek Jul 05 '16 at 08:16

0 Answers0