1

What's a good explanation for the error on Line 1?

/* Line 0 */    int foo[10][10];
/* Line 1 */    int foo_alias_compile_error[] = foo[0];
/* Line 2 */    int foo_alias_also_errors[10] = foo[0];
/* Line 3 */    int * foo_alias_works = foo[0];

The error on Line 2 doesn't really bother me, because I don't need to be able to repeat myself and re-declare the size of the array. However, the error on Line 1 (initialization with "{...}" expected for aggregate object) kind of confuses me. I get that the int foo_alias_compile_error[] is probably the "aggregate object". I just don't get why the language is setup for that not to work. I understand why Line 3 works, but it kind of feels unrepresentative -- it's an array, so I'd rather self-document it as an array.

interestedparty333
  • 2,386
  • 1
  • 21
  • 35
  • You may prefer to use `std::array, 10>` instead. It's self documenting like you want, and behaves as you expect, like other value types. – François Andrieux May 29 '19 at 20:15
  • Ah this is a good point. Unfortunately, this is on a GPU, so none of the STL is available to me. – interestedparty333 May 29 '19 at 20:15
  • Note that Line 3 provides a pointer to `foo[0]` which is not what you seem to want from Line 1. It looks like you intend to make a copy of that array. If that's the case, Line 3 would behave very differently. – François Andrieux May 29 '19 at 20:15
  • You should tag the question with whatever shader language you are using. It's not a C++ question, even if many shader languages look a lot like C++. – François Andrieux May 29 '19 at 20:17
  • Possible duplicate of [Assigning one array to another array c++](https://stackoverflow.com/questions/23850656/assigning-one-array-to-another-array-c) – Fabio says Reinstate Monica May 29 '19 at 20:22
  • thx @fabioturati Here's the longer version of that one https://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c?rq=1 – interestedparty333 May 29 '19 at 20:23
  • @ François Andrieux I think your point is that I'm accidentally invoking a copy operator for the array, which wasn't my intention. I see how the semantics of "copy the object/array" could make sense. Will have to read more. – interestedparty333 May 29 '19 at 20:25
  • Simplified example: `int arr[5]; int arr2[5] = arr;` <- error. You can't copy arrays in C or C++. – SergeyA May 29 '19 at 20:27
  • @FrançoisAndrieux looks like valid C++ code (compilation error notwithstanding) to me? – SergeyA May 29 '19 at 20:28
  • 1
    @ragerdl If you just want a reference to an array, you want `int (&bar)[10] = foo[0];`. Here `bar` is a reference to a `int[10]`, initialized to the array `foo[0]`. – François Andrieux May 29 '19 at 20:28
  • @formerlyknownas_463035818 no, your example is different. – SergeyA May 29 '19 at 20:29
  • @SergeyA Yeah but OP is saying they can't use all the language features because they will run the code on a GPU. That usually means it's a shader, whose code looks a lot like C and C++. If that's the case, the C++ tag is misleading and it would be important to tag the actual language used. – François Andrieux May 29 '19 at 20:29
  • @SergeyA I got confused which error the question actually is about. my example was for line 2 – 463035818_is_not_an_ai May 29 '19 at 20:30
  • @FrançoisAndrieux oh, it is in the comments, I missed it. – SergeyA May 29 '19 at 20:31
  • @formerlyknownas_463035818 still no, because `foo[0]` is an array, while `0` in your case is not. – SergeyA May 29 '19 at 20:32
  • @SergeyA meh my confusion was worse, sorry, I'll have a beer, cheers :P – 463035818_is_not_an_ai May 29 '19 at 20:32
  • Thanks all! I incorporated the feedback into an answer. I also included an explanation about the source of my confusion in that answer. Thanks again! – interestedparty333 May 29 '19 at 20:53

3 Answers3

0

One might hope to think of Line 1 as creating a reference for the 0th entry of foo. However, that's not how C++ works. Rather, the assignment operator (=) is invoking a copy operation. So, C++ is interpreting Line 1 as a directive to copy the elements of foo[0] into a new array inappropriately named foo_alias_compile_error.

This isn't what was meant -- one wanted a reference, not a copy. So, it's good that C++ happens to have caused an error for an unrelated reason and saved one from oneself.

A viable solution is suggested by @FrançoisAndrieux. Here's a fuller example showing that a reference (not a copy) can be made with int (&foo_reference)[10] = foo[0];.

int foo[10][10];
for (int i = 0; i < 10; ++i) {
    for (int j = 0; j < 10; ++j) {
        foo[i][j] = i + j * 10;
    }
}
int (&foo_reference)[10] = foo[0];

for (int j = 0; j < 10; ++j) {
    foo_reference[j] = 100 + j;
}

for (int i = 0; i < 10; ++i) {
    printf("foo   [0][%i] is %i\n", i, foo[0][i]);
    printf("foo_refer[%i] is %i\n", i, foo_reference[i]);
}

Output Snippet

foo   [0][0] is 100
foo_alias[0] is 100
foo   [0][1] is 101
foo_alias[1] is 101
foo   [0][2] is 102
foo_alias[2] is 102
foo   [0][3] is 103
foo_alias[3] is 103

Side-note

It's worth mentioning that functions that take arrays as arguments implicitly convert their array arguments into pointers (as is shown in Line 3). So, that's one reason why one might incorrectly think something like Line 1 should work.

In other words, the following code

void barz(int arg[]) {
    arg[2] = 99999;
}

int another_array[] = {0, 1, 2, 3, 4};
barz(another_array);
printf("another_array[2] is %i\n", another_array[2]);

"Correctly" prints 99999, not 2.

interestedparty333
  • 2,386
  • 1
  • 21
  • 35
  • 2
    This explains the problem but doesn't really propose a solution. So I guess I'll repeat my comment here : If you just want a reference to an array, you want `int (&bar)[10] = foo[0];`. Here `bar` is a reference to a `int[10]`, initialized to the array `foo[0]`. – François Andrieux May 29 '19 at 20:32
  • I think, you need to read a good C++ book instead of learning the language by try and error. A curated list can be found here: https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – SergeyA May 29 '19 at 20:34
  • @FrançoisAndrieux or even `auto& ref = foo[0];` – SergeyA May 29 '19 at 20:36
  • an `int` is never appropriately named "alias", maybe you should take a look at references – 463035818_is_not_an_ai May 29 '19 at 20:36
  • 1
    Ahhhh, so you wanted an alias! Yes, it's even part of the variables' names, but I hadn't really understood it until I read this. Then I second @FrançoisAndrieux: what you want is called a reference, which uses the `&`, and you have to use his syntax. I'm afraid the duplicate I've proposed indicates why you get an error, but it doesn't explain how to do what you want. Well, you could update your question making it clear that you are trying to get an alias! – Fabio says Reinstate Monica May 29 '19 at 20:37
0

The initializer in an array definition (C-style array, that is) must be a braced list.

This rule covers both of your Line 1 and Line 2, where you provide something that isn't a braced list and therefore the code is incorrect.

Further information: when you do provide a braced list, then each element of the list is taken as the initializer for an element of the array. As a corollary, it's not possible to supply a single initializer which causes multiple array elements to be set by it.

This rule nearly applies recursively; if you have an array of arrays, then the initializer should be a braced list of braced lists. However there is a rule that nested braces can be omitted in some cases (and the code will behave as if full bracing had been provided). For example int x[2][2] = { 1, 2, 3, 4 }; is allowed and behaves like int x[2][2] = { {1, 2}, {3, 4} };.

M.M
  • 138,810
  • 21
  • 208
  • 365
-1

when you don't specify the array size (in line 1). the compiler specifies it for you. and for this you have to do this:

/* Line 0 */    int foo[10][10];
/* Line 1 */    int foo_alias_compile_error[] = {foo[0]};

but it still has a problem. when compile that code:

 $ g++ error.cpp
 $ error.cpp:4:28: error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
 $    4 |     int fooError[] = {foo[0]};
 $      |                       ~~~~~^
 $      |                            |
 $      |                            int*

because of foo[0] is a pointer, and point to first row of your matrix (in line 1). you can do this:

/* Line 0 */    int foo[10][10];
/* Line 1 */    int foo_alias_compile_error[] = {foo[0][0]};
Ghasem Ramezani
  • 2,683
  • 1
  • 13
  • 32