0

I saw this assignment:

u = &Binary[0][0][0][0]

in a for loop:

for (i = 0, u = &Binary[0][0][0][0]; i < MAX_ADDRESSES; i++, u++)

from this section:

#define ILLEGAL_VALUE 0xFFFF
#define MAX_MODULES 8
#define MAX_SECTORS 16
#define MAX_SYLLABLES 3
#define MAX_WORDS 256
#define MAX_ADDRESSES (MAX_MODULES * MAX_SECTORS * MAX_SYLLABLES * MAX_WORDS)

...

int i;
uint16_t *u;

// Initialize the binary as completely unused.
for (i = 0, u = &Binary[0][0][0][0]; i < MAX_ADDRESSES; i++, u++)
  *u = ILLEGAL_VALUE;

for an assembler.

I am not very familiar with c (or other compiled languages), awk is somewhat similar to c.

In awk var[x] is an array, but this seems not to be an array, or any other variable.

What is this piece of code '&Binary[0][0][0][0]' ?

Edit:

Indeed I found this:

typedef uint16_t
    BinaryImage_t[MAX_MODULES][MAX_SECTORS][MAX_SYLLABLES][MAX_WORDS];
#define ILLEGAL_VALUE 0xFFFF

So it is an array after all !

However I am surprised by the ampersand as the first character of the array name ?

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
azbc
  • 399
  • 1
  • 5
  • 12
  • https://stackoverflow.com/questions/6290956/one-dimensional-access-to-a-multidimensional-array-is-it-well-defined-behaviour – Ry- Dec 08 '19 at 23:08
  • This might be UB; going off the end of one inner-most array into the next by incrementing `u` might technically violate something. I'm pretty sure accessing the whole 4D array via `Binary[0][0][0][large_i]` would, but it might be guaranteed that the array objects are contiguous in a multidimensional array, in which case taking a pointer to the start of the first one might be language-lawyer safe as well as safe in practice. – Peter Cordes Dec 08 '19 at 23:17
  • @PeterCordes - fairly certain items are contiguous in multi-dim arrays. I had an expert point this out to me last week on a previous question. – selbie Dec 08 '19 at 23:19
  • @selbie: My only concern is that the pointer is derived from the first inner-most `uint16_t` array, and you're eventually going outside that to the other arrays. Yes the data is guaranteed to be contiguous and I think without padding between array objects in the outer arrays, but the question is whether C lets you address it with a pointer derived from the first array. (For example, whether C allows an implementation with a segmented memory model to keep different inner-arrays in different segments, making them too large to iterate over with a "large" not "huge" memory model. Flat = trivial) – Peter Cordes Dec 08 '19 at 23:37
  • @selbie: [C/C++: Is this undefined behavior? (2D arrays)](//stackoverflow.com/q/6015080) confirms it's technically UB to "access elements of a multidimensional array from a pointer to the first element, for the elements that are not part of the first array." It happens to work on most implementations, though. – Peter Cordes Dec 08 '19 at 23:43
  • @selbie: Hrm, that's only for the obviously bad case of `Binary[0][0][0][x]` for large x. But given the way C pointer math rules are defined, repeated increments of a pointer to the first element is exactly equivalent. Also other answers on the question cast some doubt on it. – Peter Cordes Dec 08 '19 at 23:45
  • @PeterCordes - I am not a language lawyer. However, this sort of code has existed for decades and all compilers would align the elements logically as a single array and address any element `x[row][col]` as `&x[0][0] + (width*row + col)` – selbie Dec 08 '19 at 23:47
  • @selbie: yes, of course, and why I said "technically". But the C standard has UB for accessing outside objects because not all systems have a flat memory model. This allows indexing *within* one object to just use the offset part of a seg:off address on a segmented machine, if max object size is much less than the size of the address space / pointer width. That's why you can't just subtract 2 pointers to different objects and then use `b[ a_minus_b ]` to address `a` relative to `b`. See also [Does C have an equivalent of std::less from C++?](//stackoverflow.com/q/58322107) – Peter Cordes Dec 08 '19 at 23:52
  • @selbie: also found another language-lawyer question: [May I treat a 2D array as a contiguous 1D array?](//stackoverflow.com/q/7269099). Includes an example that refuses to compile with constexpr, essentially proving that compiler devs think it's UB. I'm aware that it happens to work reliably enough to be widely used, I'm not disputing that. – Peter Cordes Dec 09 '19 at 00:05
  • Since `ILLEGAL_VALUE` is 0xFFFF, this whole icky code could be replaced with `memset(Binary, 0xFF, sizeof Binary);` – Lundin Dec 09 '19 at 08:48

2 Answers2

4

Somewhere in your code is likely a declaration for a multi-dimensional array named Binary Most likely a 4-d array of type uint16_t (16-bit unsigned int)

uint16_t Binary[MAX_MODULES][MAX_SECTORS][MAX_SYLLABLES][MAX_WORDS];

This expression: &Binary[0][0][0][0]

is the address of the first element in this multi-dimensional array. While the array is declared as a 4-d array, it appears the for-loop is simply enumerating over all elements in the array via pointer to initialize each with the ILLEGAL_VALUE constant.

For what it's worth, the for-loop could likely be replaced with:

memset(Binary, 0xff, sizeof(Binary));

selbie
  • 100,020
  • 15
  • 103
  • 173
  • Good compilers will already recognize this loop as being memset-equivalent and optimizing it to a call to memset, or whatever inline expansion they prefer. But yes, calling memset might be more readable, OTOH it's a uint16_t array so you need to comment that it's actually `ILLEGAL_VALUE` which has two identical halves. At least `uint16_t` guarantees there's no padding, so this can't compile on machines where `unsigned` might have some padding bits and memset with `0xFF` bytes might not be equivalent. It would break on machines like DSPs with CHAR_BIT=16 where sizeof(uint16_t) = 1, though. – Peter Cordes Dec 08 '19 at 23:20
  • I found the array declaration. But I wonder how it is possible to use an ampersand as a character in a variable ? Is this a special case ? – azbc Dec 08 '19 at 23:47
  • 3
    `&` means "address of" – selbie Dec 08 '19 at 23:48
1

regarding:

u = &Binary[0][0][0][0]

this means set the contents of u with the address of the very first entry in a 4 dimensional array

user3629249
  • 16,402
  • 1
  • 16
  • 17