1

Having this code:

#include <stdio.h>
#include <stdlib.h>

struct Test { char c; } foo;

int main (void) {

   struct Test *ar[10];
   struct Test *(*p)[] = &ar; //what type of syntax is this *(*p)[]

   *(*p+1) = &foo; // the same  (*p)[1] = &foo
   //this only works


   p[0][1] = &foo  //the same as *(*p+1) 
   ////1error: invalid use of array with unspecified bounds

   (*(*p+1)+1) = &foo // the same as p[1][1] = &foo 
   ////2error: lvalue required as left operand of assignment

   //HOW TO make assignment of p[1][1] = &foo   and NOT p[0][1] ??

   return 0;
}

I am getting 2 weird errors from trying to assign an address from struct to array of structs. I would like both error explanation and how to make the assignment (viz. code) to p[1][1].

EDIT: the same as statements could be wrong. I just thought, they would be equally, if "normal" pointers (their type)

14
  • 1
    Ouch! Pointers to arrays of pointers — of indeterminate size. It's going to be hard to explain that. It can be done, but it ain't easy. I'm not convinced by your 'same as' comments, especially the first one. Commented May 8, 2020 at 20:52
  • @JonathanLeffler yeah, the first one is completely wrong, isn't it? (*p)[0] is the same as *(*p). No +1 in there. Commented May 8, 2020 at 20:53
  • @JonathanLeffler they may be wrong, if so, just say that Commented May 8, 2020 at 20:54
  • But I mean, why are they wrong, all of them would be right if "normal pointer" or? Commented May 8, 2020 at 20:55
  • 4
    Mostly I'm saying "my brain hurts" and TGIF. The good news for you is that you're unlikely to come across anything so abstruse in the wild — people don't usually write code like that, not least because it is hard to understand and get right. I'm going to sit on the sidelines until many hours later. I'm hoping someone will spare me the effort of working out what's going wrong. Commented May 8, 2020 at 20:56

2 Answers 2

3

Answering your comments line by line:

#include <stdio.h>
#include <stdlib.h>

struct Test { char c; } foo;

int main (void) {

   struct Test *ar[10];
   struct Test *(*p)[] = &ar; //what type of syntax is this *(*p)[]

cdecl.org says struct Test *(*p)[] means declare p as pointer to array of pointer to struct Test. And by the way, the array is an array of unknown/unspecified size, since there's nothing in the square brackets.

   *(*p+1) = &foo; // the same  (*p)[1] = &foo
   //this only works

You're right, and yes, it works.

   p[0][1] = &foo;  //the same as *(*p+1) 
   ////1error: invalid use of array with unspecified bounds

(I added your missing semicolon.) You'd usually be right, but in this case a bit of pedantry means you're not. x[0] isn't equivalent to *x, but rather *(x + 0). Those are usually equivalent, but when x is a pointer to something of unknown size, you're not allowed to do pointer arithmetic on it.

   (*(*p+1)+1) = &foo; // the same as p[1][1] = &foo 
   ////2error: lvalue required as left operand of assignment

(I added your missing semicolon again.) Not quite. p[1][1] would be *(*(p+1)+1). You have your *s and parentheses the wrong way around.

   //HOW TO make assignment of p[1][1] = &foo   and NOT p[0][1] ??

You can't, without knowing how big the array that *p points to is.

   return 0;
}
Sign up to request clarification or add additional context in comments.

15 Comments

So if I have determinated size say struct Test *(*p)[10] = &ar, then it would work?
p[1][1] gives me stack smashing. *(*(p+1)+1) = &foo; but my allocated space comes from statement ` struct Test *(*p)[10] = &ar;`,
@Herdsman Sorry, let me clarify. I meant "work" as in "valid to the compiler". That won't do what you want at runtime because you only have one array, but p[1] will try to access a nonexistent second array.
So how could I allocate new array to add the second needed space to achieve the above, something like realloc(p, sizeof(&p)*2)?
@Herdsman struct Test *ar[2][10]; struct Test *(*p)[10] = ar;
|
0

From the C Standard (6.5.2.1 Array subscripting)

Constraints

1 One of the expressions shall have type ‘‘pointer to complete object type’’, the other expression shall have integer type, and the result has type ‘‘type’’.

In the left side hand of the assignment

p[0][1] = &foo 

o is a pointer to an incomplete object type due to the declaration

struct Test *(*p)[] = &ar;

where the type Test *[] is incomplete type because the size of the array is unknown (unspecified). So the compiler issues an error.

In this statement

*(*p+1) = &foo;

the dereferenced pointer p (*p) used in the expression *p + 1 is converted to pointer to the first element of the array ar and has the type struct Test **. The expression *p + 1 points to the second element of the array and after dereferencing *( *p + 1 ) you get lvalue of the second element of the array that gets the address of the object foo.

In this statement

(*(*p+1)+1) = &foo;

there is used rvalue of the kind pointer + 1. SO you may not assign to this temporary object a value.

It looks the same as in this code snippet

int a[] = { 1, 2 };
int *p = &a[0];

p + 1 = &a[1];

2 Comments

So is this one wrong? (*(*p+1)+1) = &foo;? if so, then how should be correct?
@Herdsman It does not make sense. The expression *( *p + 1 ) yields the second element of the array. Its value was set to &foo. Now you are getting the address of the memory after the object foo and are trying to set it to &foo.

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.