-1

I have declared and initialized a (dynamic?) array inside a bool function, as seen in this simple example below. I'm using the same function to populate it. I don't want the array to remain preserved in the computer's memory once the function's execution is complete to allow the array to be repopulated with the correct values in future function calls. Will it be automatically erased from the memory once the function call is returned? If not, what's the workaround for it?

bool correct_count(int start, int end)
{
    int numbers[] = {};

    for (int i = 0; i < (end - start + 1); i++)
    {
        numbers[i] = start + i;
    }

    if (numbers[0] == start && numbers[end - start] == end)
    {
        return true;
    }

    return false;
}

In this simple example, we can determine the size of the array, but that is not the case with the program I'm trying to write. Also, I'm not allowed to use memory-related operators like the dereference operator or dynamic memory allocation just yet for my programs, because that's currently out of the scope of what's already been taught to me.

user16217248
  • 3,119
  • 19
  • 19
  • 37
  • 1
    `int numbers[] = {};` actually compiles? What compiler are you using, and what arguments are you passing to it? – Andrew Henle Apr 20 '23 at 14:10
  • The contents of `numbers` after the function returned *may* be erased (but probably won't), and *may* be preserved, or *may* be replaced by something different, but you can't rely on any particular behavior. If you want it to be erased, you have to do it yourself, but (as I just said) can't be assured it will stay that way. – Scott Hunter Apr 20 '23 at 14:10
  • @AndrewHenle: It's valid. It's one of those but whyyy kind of things that turns out to have a niche use that's not immediately apparent. – Joshua Apr 20 '23 at 14:11
  • 1
    @Joshua No it is not valid, it is non-standard GNU goo. – Lundin Apr 20 '23 at 14:20
  • @Joshua *It's valid.* [No, it's **NOT**](https://port70.net/~nsz/c/c11/n1570.html#6.7.6.2p1): "In addition to optional type qualifiers and the keyword static, the [ and ] may delimit an expression or *. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero." [along with](https://port70.net/~nsz/c/c11/n1570.html#6.7.6.2p5): "each time it is evaluated it shall have a value greater than zero" – Andrew Henle Apr 20 '23 at 14:20
  • To avoid problems like this I'd recommend [What compiler options are recommended for beginners learning C?](https://software.codidact.com/posts/282565) – Lundin Apr 20 '23 at 14:21
  • @Lundin: Old '90s compilers took this too. It's almost like the standard wrote one thing and everybody threw it out and made zero length arrays work. I haven't checked a modern compiler other than gcc because my use case evaporated after [] was added to structs. – Joshua Apr 20 '23 at 14:23
  • @Joshua It's not the array that's the problem it's the empty initializer list. The whole reason why gcc supports zero-sized arrays is the old "struct hack" fix which was resolved in C99 with flexible array members. – Lundin Apr 20 '23 at 14:27
  • @AndrewHenle: The passage you cite specifies strictly conforming code. The C standard also permits conforming code. Extensions supported by conforming compilers are conforming code, provided they do not change the behavior of strictly conforming programs. – Eric Postpischil Apr 20 '23 at 14:28
  • @EricPostpischil And how does this not break a strictly conforming code? `memcpy(buf, numbers, sizeof numbers);` `numbers` is what, complete type, incomplete type, who knows? – Lundin Apr 20 '23 at 14:31
  • @EricPostpischil You're expanding the colloquial meaning of "valid" to include code that at best is non-portable. – Andrew Henle Apr 20 '23 at 14:31
  • @AndrewHenle: And do you not include non-portable code as valid? If code has `#include `, do you say that code is invalid? If code uses any GUI library or performs any network communication, do you say it is invalid? The C standard fully specifies only a base language that is useful only for very limited applications, mostly just academic exercises and limited text interactions. It is intended to be extended; that is a deliberate part of the design of C, and conforming extensions are valid. – Eric Postpischil Apr 20 '23 at 14:35
  • @Lundin: `memcpy(buf, numbers, sizeof numbers);` is not a strictly conforming program. The C standard says that extensions that do not change the behavior of strictly conforming programs are conforming, not that extensions that do not change the behavior of isolated snippets of code that could be strictly conforming are conforming. – Eric Postpischil Apr 20 '23 at 14:36
  • @EricPostpischil *And do you not include non-portable code as valid? If code has `#include `,* Again, huh? That's a terrible example that violates no C standard-imposed constraints. The C standard clearly states that arrays must have a size "greater than zero" and calling such code "valid" as you're doing it more than a little confusing. – Andrew Henle Apr 20 '23 at 14:38
  • @AndrewHenle: You asked about including code that is non-portable as valid. `#include ` is non-portable. It is impossible to implement the functions declared in `` using only strictly conforming C. They necessarily access hardware in ways that are not defined by the C standard. Just because it is hidden behind an `#include` does not make it strictly conforming C code. It means you are linking into your program things that do not conform to the C standard’s requirements for strictly conforming code. The program’s behavior is then not defined by the C standard. – Eric Postpischil Apr 20 '23 at 14:41
  • @EricPostpischil Use `gcc -pedantic` and you get `ISO C forbids zero-size array ‘zero’`. Yet you want to call it "valid" through some logic games, while conflating directly violating the C standard saying in multiple places "greater than zero" when referring to the size of an array with including a POSIX-standard header in a way that violates not one single constraint in the C standard? OK. But IMO you're just trying to muddy the waters to avoid having to back off your pushing the limits of "valid" well beyond the vernacular meaning of the word. – Andrew Henle Apr 20 '23 at 16:31
  • @AndrewHenle: It is not a logic game that the C standard permits, and even invites, extensions. C is **intended** to be used with extensions. The C standard is intended to define a base language that implementations extend, not a limited language. How many widely used programs can you identify that use C without any extensions at all, only strictly conforming code? What are you going to use the term “valid” for? If it means only strictly conforming code, are you going to tell people that including `` is not valid? If not, then define “valid”. – Eric Postpischil Apr 20 '23 at 16:45
  • @EricPostpischil So answer this: does an array of constant size but with zero elements violate 6.7.6.2p1's "If the expression is a constant expression, it shall have a value greater than zero."? Either it does or it doesn't - what any extension may or may not do is utterly irrelevant. And you can also add what C syntax or constraint `#include ` violates. Again IMO you're dancing in order to not walk back characterizing arrays that violate "If the expression is a constant expression, it shall have a value greater than zero." as "valid". – Andrew Henle Apr 20 '23 at 19:36
  • @AndrewHenle: Nearly all of the rules, if not all, in clauses 6 and 7 specify how strictly conforming code behaves. They fall inside a framework established by earlier clauses, including clause 4. They cannot be fully interpreted in isolation from that. Paragraph 6 of clause 4 says a conforming implementation may have extensions, and paragraph 7 says a conforming program is one acceptable to a a conforming implementation. So, yes, an expression of value zero for an array size violates 6.7.6.2 1, which means the program it is in is not strictly conforming. It is nonetheless conforming. – Eric Postpischil Apr 20 '23 at 22:40
  • @AndrewHenle: `#include ` by itself might not directly violate any rules, although I expect if you examine the contents of the file, you will find it is not strictly conforming code. My point is about programs that use features from ``, not that merely include it. It is impossible for programs using operating system routines to be strictly conforming, because the features provided by the operating system cannot be implemented using only strictly conforming C code. Please define what you mean by “valid.” – Eric Postpischil Apr 20 '23 at 22:43

2 Answers2

5
  1. int numbers[] = {}; is not valid code. You must specify the array size so the compiler knows how many bytes to allocate. Until C23 you must also either omit the = {} and leave the data uninitialized or initialize at least one of the values (i.e., = {0}).

  2. If the size of the array cannot be determined beforehand you must use a heap array (via int *numbers = malloc(DEFAULT_SIZE);) and call realloc() every time the array needs to be resized. Preferably you double the capacity each allocation so that the number of potentially expensive reallocations will only be related to the log of the final array size. But in this case you must call free(numbers); afterwards to deallocate the memory.

  3. All automatic variables such as your array (i.e., not static and not global and not allocated with malloc) are deallocated once they go out of scope. This includes after the function returns.

user16217248
  • 3,119
  • 19
  • 19
  • 37
  • In the program I'm writing, the length/size cannot be calculated/determined beforehand. – Rishikesh Negi Apr 20 '23 at 14:19
  • 1
    @RishikeshNegi: On your comment I have closed the question as a duplicate with the correct answer for how to get what you want. Note that such an array must be on the heap. – Joshua Apr 20 '23 at 14:20
  • @Rishikesh Negi, Then how is the compiler suppose to know how much to allocate? You will need to malloc a block, then realloc it as needed. This will involve keeping track of how big it is and how much of it is being used. – ikegami Apr 20 '23 at 14:21
  • @Lundin: OP said he can't compute the size at declaration time. – Joshua Apr 20 '23 at 14:24
  • @Joshua Nothing in the code posted supports that opinion, however. – Lundin Apr 20 '23 at 14:25
  • 1
    @Joshua Then OP either has to either find a fixed upper bound for the number of items and use a stack array or use a dynamically growing array. – user16217248 Apr 20 '23 at 14:26
  • 1
    For 1, you could also let the array size be determined automatically by initializing it with a braced, non-empty initializer. – Ian Abbott Apr 20 '23 at 17:09
1

int numbers[] = {}; declares a zero length array. You want int numbers[end - start + 1].

The memory allocated by an array declared in a function is freed when the function returns. Next function call (anywhere) will reuse it.

This answer looks like it should be deleted but isn't because of the first comment (clarifying the question).

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • The thing is, in this example, we can calculate/determine the length. But in the program I'm writing, the length/size cannot be calculated/determined beforehand. – Rishikesh Negi Apr 20 '23 at 14:17
  • Zero-length arrays are not valid C code. – Andrew Henle Apr 20 '23 at 14:20
  • @Rishikesh Negi, Then how is the compiler suppose to know how much to allocate? You will need to malloc a block, then realloc it as needed. This will involve keeping track of how big it is and how much of it is being used. – ikegami Apr 20 '23 at 14:21
  • @AndrewHenle: Zero-length arrays are conforming C code as specified by the C standard. – Eric Postpischil Apr 20 '23 at 14:25
  • @EricPostpischil Huh? Both [fixed-size arrays](https://port70.net/~nsz/c/c11/n1570.html#6.7.6.2p1) and [VLAs](https://port70.net/~nsz/c/c11/n1570.html#6.7.6.2p5) must have a size "greater than zero". – Andrew Henle Apr 20 '23 at 14:30
  • @AndrewHenle: In strictly conforming programs, arrays must be non-empty. That requirement does not apply to conforming programs. – Eric Postpischil Apr 20 '23 at 14:37