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.

17
  • You may prefer to use std::array<std::array<int, 10>, 10> instead. It's self documenting like you want, and behaves as you expect, like other value types. Commented May 29, 2019 at 20:15
  • Ah this is a good point. Unfortunately, this is on a GPU, so none of the STL is available to me. Commented May 29, 2019 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. Commented May 29, 2019 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++. Commented May 29, 2019 at 20:17
  • 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]. Commented May 29, 2019 at 20:28

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

5 Comments

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].
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: stackoverflow.com/questions/388242/…
@FrançoisAndrieux or even auto& ref = foo[0];
an int is never appropriately named "alias", maybe you should take a look at references
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!
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} };.

Comments

-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]};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.