0

The code:

int (*2d_array)[width] = calloc(height, width * sizeof(int));

Below is the distribution code from an online class, where RGBTRIPLE is a struct. Someone said image is a pointer to an array of length width of RGBTRIPLE. And so 2d_array here is also a pointer to another array of integers who has width number of elements?

RGBTRIPLE(*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));

I am just really confused about this syntax. How does the parenthesis change the meaning of image? How should I interpret RGBTRIPLE(*image)[width]? From left to right? Any help is greatly appreciated!!!

Shubham
  • 1,153
  • 8
  • 20
  • 1
    Please show us actual code, copy-and-pasted from something that compiled successfully. `2d_array` is not a valid identifier. Please read this: [mre] – Keith Thompson Jul 27 '20 at 04:49
  • You read variable declarations *starting at the variable name*, going right when you can, left when you must, and respecting parentheses. Just read it out: "`image` is pointer to array of `width` `RGBTRIPLE`s". If you got rid of the parentheses it'd be "`image` is array of `width` pointers to `RGBTRIPLE`". – HTNW Jul 27 '20 at 05:08
  • You have two declaration you need to be able to distinguish (using `int` for example), `int *arr[n]` and `int (*arr)[n]`. The first is *an array of pointers* (`n` of `int*` pointers). The second is *a pointer to array* of `int[n]` -- that is a pointer to an array. Your declaration for `image` is *a pointer to array* of `RGBTRIPLE[width]`. Your allocation `calloc(height, width * sizeof(RGBTRIPLE))` allocates storage for `height` number of those arrays, effectively allocating what you reference as `image[x][y]` where `x < height` and `y < width`. – David C. Rankin Jul 27 '20 at 05:18
  • See ["The Clockwise/Spiral Rule"](http://c-faq.com/decl/spiral.anderson.html) – David C. Rankin Jul 27 '20 at 05:20

2 Answers2

1

Or you can interpret RGBTRIPLE(*image)[width] as RGBTRIPLE (*image)[width]. Where RGBTRIPLE is probably a typedefed struct.

For e.g.

typedef struct {
  // data members
}RGBTRIPLE;

So, in RGBTRIPLE (*image)[width], image is a pointer to array of user-defined data type RGBTRIPLE, similar to int (*ptr)[width] which is a pointer to array of int type.

Note: In C, you can only declare a variable name which starts with a underscore or a letter. This int (*2d_array)[width] is wrong as far as I know.


I assume 2d_array is _2dArray.

And so _2dArray here is also a pointer to another array of integers who has width number of elements?

Yes

How does the parenthesis change the meaning of the image? How should I interpret RGBTRIPLE(*image)[width]?

These are called Complex Pointers. E.g. pointer to array == int (*ptr)[LEN]; or pointer to function == int (*ptr)(//function arguments);

If you don't put parenthesis around image i.e. RGBTRIPLE *image[width] it will be array of pointers. So you must put parenthesis around image if you want it to be a pointer to array.

Just interpret it as image is a pointer to an array of width elements of type RGBTRIPLE.

Shubham
  • 1,153
  • 8
  • 20
  • You have the undercore rule a bit off, see [What are the rules about using an underscore in a C++ identifier?](https://stackoverflow.com/q/228783/3422102). The parenthesis effect [C++ Operator Precedence](https://en.cppreference.com/w/cpp/language/operator_precedence) which is the reason for the difference. – David C. Rankin Jul 27 '20 at 05:24
  • Well, I don't know about `C++`. But in `C`, you can do `_Name/_name/__name/__Name`. – Shubham Jul 27 '20 at 05:52
  • The same applies in C++ so long as the name is not declared in global namespace. So that part is right, it just didn't convey the rest of the story. For example `_X` would not be correct. – David C. Rankin Jul 27 '20 at 05:58
  • As I already mentioned I don't know much about C++. But to test `_X`, I declared `int _X = 2;` in a program in C using GCC and it worked. – Shubham Jul 27 '20 at 06:23
  • 1
    Variable name **may** start with underscores in C, that is true. Simply an implementation is allowed to declare a number of global symbals for internal use. The rule is that those internal symbols must start with an underscore. As that list is unspecified, when you use a variable with a name starting with an underscore, it may collide with one of those internal symbols. What is even worse IMHO is that it can work fine with a compiler an break with a different one (implementation dependance)... – Serge Ballesta Jul 27 '20 at 07:04
  • ... That is the reason why *best practices* recomment to not use user level symbols starting with an underscore. – Serge Ballesta Jul 27 '20 at 07:05
  • 1
    "All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use." For example `` could declare `_X` as a typedef... so your program could work for as long as you didn't include ``... – Antti Haapala -- Слава Україні Jul 27 '20 at 07:47
  • **David C. Rankin, Serge Ballesta and Antti Haapala** I understood your point and in future I'll try not to declare a variable starting with an underscore as far as possible. Thanks for this new information that _underscored variables are generally used as internal symbols_. I really didn't know about this. – Shubham Jul 27 '20 at 10:23
0

And so 2d_array here is also a pointer to another array of integers who has width number of elements?

Yes.

Note that identifiers aren't allowed to begin with a number. So, 2d_array is an invalid identifier.

Below is the distribution code from an online class, where RGBTRIPLE is a struct.

To be nitpicky, a pure structure needs to be classified by the struct keyword. This isn't the case here, but I guess RGBTRIPLE is high-probably a typedef alias for a pure structure.

Just that as side note.

I am just really confused about this syntax. How does the parenthesis change the meaning of image?

RGBTRIPLE (*image)[width] - image is a pointer to an array of width elements of type RGBTRIPLE.

RGBTRIPLE *image[width] - image is an array of width pointer to RGBTRIPLE.

It's a big difference. Either you got only one pointer to an array of width RGBTRIPLE or you got an array of pointers to RGBTRIPLE.

The parenthesis changes the whole context.

How should I interpret RGBTRIPLE(*image)[width]? From left to right?

Think in the Clockwise Spiral Rule and read it clockwise from the identifier (middle).

This has been subject of: