-1

This is a follow-up question of this: C - Convert array of elements into 2-d matrix

To do the conversion, the Method I got there is:

int (* M)[b] = (int (*) [b])array

where M[a][b] and array[a * b].

The problem is that I found when I do the conversion this way, there is actually an array of size b allocating on the stack, and it is kind of expensive for a large b. So I would like to know if there is any way to do the conversion without such allocating.

Example (update):

/* conversion.c */

int main(void) {
    int flag, array[30], b = 3;

    if (flag)
        goto done;

    int (* M)[b] = (int (*)[b]) array;

done:
    return 0;
}

compiling with gcc-9:

conversion.c: In function 'main':
conversion.c:5:3: error: jump into scope of identifier with variably modified type
    5 |   goto done;
      |   ^~~~
conversion.c:9:1: note: label 'done' defined here
    9 | done:
      | ^~~~
conversion.c:7:9: note: 'M' declared here
    7 |  int (* M)[b] = (int (*)[b]) array;
      |         ^
conversion.c:5:3: error: jump into scope of identifier with variably modified type
    5 |   goto done;
      |   ^~~~
conversion.c:9:1: note: label 'done' defined here
    9 | done:
      | ^~~~
conversion.c:7:9: note: '({anonymous})' declared here
    7 |  int (* M)[b] = (int (*)[b]) array;
      |         ^

update: error: jump into scope of identifier with variably tells that the goto statement is trying to jump across a (compile time)unknown size of memory on stack, which means there is memory allocated on stack due to the conversion above.

Yi Lin Liu
  • 169
  • 1
  • 11
  • `here is actually an array of size b allocating on the stack` How are you sure it is happening because of `int (*M)[b]`. Can you show [mcve]? – kiran Biradar Jun 27 '19 at 10:01
  • @kiranBiradar I guess it is not really necessary to provide an example here. When you try to compile the code with a `goto` statement across the conversion, compiler will throw an error. So there must be allocation at least in some un-optimized case. – Yi Lin Liu Jun 27 '19 at 10:12
  • 1
    Without [mcve] we don't know what `goto` statement and compilation error you are referring. code in the post does not take stack memory that is what we can say. – kiran Biradar Jun 27 '19 at 10:17
  • What happens if you get rid of the `goto` statement? – Andrew Henle Jun 27 '19 at 11:03
  • @AndrewHenle Then the error goes away for sure. The reason I add goto here is because it shows there would be memory allocated on stack. – Yi Lin Liu Jun 27 '19 at 11:05
  • 1
    "there is actually an array of size b allocating on the stack" says who? M is a pointer to an array of size b. Your cast however is non-standard and is likely to result to UB down the road when M is dereferenced. And please don't use goto, it is totally unwarranted here. – n. m. could be an AI Jun 27 '19 at 11:05
  • @n.m. The error from compiler says there is compile time undetermined amount of memory allocated on the stack due to the conversion. – Yi Lin Liu Jun 27 '19 at 11:08
  • 1
    No, the compiler error doesn't say anything about the memory, the stack or any such nonsense. It talks about *identifiers* and *types*. – n. m. could be an AI Jun 27 '19 at 11:10
  • @n.m. I think that's the point of this question - there isn't memory allocated on the stack for a VLA in the posted code, just a pointer. – Andrew Henle Jun 27 '19 at 11:10
  • This question is probably relevant: https://stackoverflow.com/questions/20654191/c-stack-memory-goto-and-jump-into-scope-of-identifier-with-variably-modified – Andrew Henle Jun 27 '19 at 11:11
  • 1
    Voting to close as unclear, since the question is asking something completely different now and posted answers no longer make sense. This is a waste of everyone's time, simply close it. – Lundin Jun 27 '19 at 11:14
  • @Lundin I suspect the question is based on an assumption that a `goto` would break the allocation of a VLA, but that `int (* M)[b] = (int (*)[b]) array;` is a pointer that doesn't allocate memory, thus the compiler should allow the `goto`. If so, it's a duplicate of the question I linked above. – Andrew Henle Jun 27 '19 at 11:19
  • @AndrewHenle Yes, that is what I mean. Thanks – Yi Lin Liu Jun 27 '19 at 11:20
  • @YiLinLiu `I add goto here is because it shows there would be memory allocated on stack` Then you should update so in the question. – Gaurav Singh Jun 27 '19 at 11:28
  • @AndrewHenle "is a pointer that doesn't allocate memory, thus the compiler should allow the goto". The standard says otherwise. A VLA, a pointer to a VLA, a pointer to a pointer to a VLA etc are all forbidden in this context. The compiler follows the standard. You might be thinking that the standard *should* only forbid actual VLAs and not pointers thereto, but the standard says what it says, and in fact a good argument can be made for it. – n. m. could be an AI Jun 27 '19 at 13:07

1 Answers1

1

there is actually an array of size b allocating on the stack

No such thing is happening. You are trying to declare a pointer to an array, not an array.

The very first paragraph of the goto section of the standard forbids what you are trying to do.

6.8.6.1 [The goto statement]/1 A goto statement shall not jump from outside the scope of an identifier having a variably modified type to inside the scope of that identifier.

It doesn't matter if the amount of memory occupied by the object denoted by the identifier in question is variable or constant. It's enough that its type is derived from a VLA type, for example, if it's a pointer to one.

You don't need goto for this, or much anything else.

int main(void) {
    int flag = 0, array[30], b = 3;

    if (!flag) {
        int (*M)[b] = (int (*)[b]) array;
        // note that dereferencing M here is undefined behaviour
        (void)M;
    }
    return 0;
}

Live demo

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243