9

int (*p) [4] ;

Is "p" pointer to array of 4 integers ?? or what ??

and How can I call "new" for this pointer ??

Farah_online
  • 521
  • 1
  • 9
  • 20
  • As you can see from the answer below. This king of type declaration is confusing and non intuitive and as such best avoided (unless you want to add excessive comments). If you use other constructs you can achieve the same results in a more readable way (such as std::vector<> or boost::array) – Martin York Aug 01 '10 at 17:41
  • @Martin: `std::vector<>` is an entirely different animal than `int (*p)[4]`! – Seth Aug 01 '10 at 17:58
  • 2
    @Seth: But `int (*p)[4]` is probably better replaced by a two-dimensional `std::vector >` or a one-dimensional `std::vector` with manual indexing arithmetic or a `boost::multi_array`. – fredoverflow Aug 01 '10 at 18:02
  • @Martin York , @FredOverflow : thanks for your answers but I amn't using this Array to store data in my project . but there is a doctor in our university like this kind of Question very much :( , Althogh its confusing :( – Farah_online Aug 02 '10 at 13:36

3 Answers3

7

Is "p" pointer to array of 4 integers?

Correct!

How can I call "new" for this pointer?

For example, p = new int[7][4].

Billy ONeal
  • 97,781
  • 45
  • 291
  • 525
fredoverflow
  • 237,063
  • 85
  • 359
  • 638
  • 3
    Err.. was +1 until the edit. new int[7][4] gives you a single block 28 ints wide. – Billy ONeal Aug 01 '10 at 17:18
  • humm .. so that I think p is pointer to 4 pointers of integer each of them points to array of 4 integers , it's right ?? – Farah_online Aug 01 '10 at 17:20
  • 3
    @Billy: There is nothing wrong with my example. The type of `new int[7][4]` *is* `int (*)[4]`. Maybe it's more obvious with a typedef? `typedef int row[4]; row *p = new row[7];` This is exactly equivalent to my code, just more readable. Would you argue that this is wrong as well? – fredoverflow Aug 01 '10 at 17:22
  • @Farah: No, it's not a pointer to 4 *pointers* to integer, it's actually a pointer to 4 integers. Remember that a pointer can point to a single element of an array (just as a `char*` can point to a character of a C string). – fredoverflow Aug 01 '10 at 17:26
  • @FredOverflow: I stand corrected. Isn't the typedef version the same as new int[4][7] though? Why does the order get switched around? – Billy ONeal Aug 01 '10 at 17:30
  • 3
    @Billy: Welcome to C declarator syntax hell ;-) The best reference I could find was 5.3.4 (§5 and §6). – fredoverflow Aug 01 '10 at 17:33
  • @FredOverflow : yes ... I mean that p is a pointer to array of 4 pointers to integer , unless how can we reserve array of two-dimensional by 'p' ? if 'p' is pointer to array of 4 integer it should allows to reserve just one-diension array of 4 integer ?? , it is ?? – Farah_online Aug 02 '10 at 13:38
  • @Farah: How can we say `int* p = new int[42]` then? The pointer is always one dimension less then the array. – fredoverflow Aug 02 '10 at 16:11
6

int (*p)[4] is, indeed, a pointer to an array of four ints.

You can dynamically allocat an object of type "pointer to array of four int" as follows.

int (**ptr)[4] = new (int (*)[4]);

Note, no space for any ints is allocated; only the pointer itself.

You can allocated an array of 4 ints as follows:

int *ptr = new int[4];

What you can't do (without explicit casting) is assign a pointer to a dynamically allocated array of 4 int to a pointer of type int (*)[4]. Whenever you allocate an array via new, even if you use a typedef, the type of the new expression is a pointer to the first element of the array; the size of the array is not retained in the type of the new expression.

This is because new[] expressions can allocate arrays where the size of the array is chosen at runtime so would not always be possible (or even desirable) to encode the array size into the type of the new expression.

As has been suggested, you can dynamically allocate an array of one array of 4 int. The size of the first array is lost from the type information and what you get is a pointer to the first element of the array (of size 1) of the arrays of four int.

int (*p)[4] = new int[1][4];

Even though it is an array of just 1 (arrays of 4 int), you still need to use delete[] to deallocate p.

delete[] p;
CB Bailey
  • 648,528
  • 94
  • 608
  • 638
  • 2
    Of course one should never actually be a position to need to call `delete` manually. – GManNickG Aug 01 '10 at 21:16
  • well , what about int (*p)[4] = new int[4][4] ... dow can I call delet on it ?? I try : for (int i=0;i<4;i++) delete[] p[i] ; delete[] p ; but it doesn't work :( – Farah_online Aug 02 '10 at 13:39
  • 2
    @Farah_online: It doesn't matter what size the array is, you always delete arrays with `delete[] p;` So `p = new int[1][4];` ... `delete[] p` and `p = new int [4][4];` ... `delete[] p`. Calling delete on an array member (`delete[] p[i]` or `delete p[i]`) is not valid. – CB Bailey Aug 02 '10 at 15:30
  • +1 for _the size of the array is chosen at runtime so would not always be possible (or even desirable) to encode the array size into the type of the new expression._. – legends2k Sep 29 '14 at 15:33
  • well.. I agree that the new[] can allocate an array of a size dictated by the runtime state, but then, now, 9 years later, we **do have** compilers that trace `constexpr`s very well, and there's an obvious compile time vs run time difference between `new int[6]` and `new int[x]` where x is `int` and `new int[x]` where x is constexpr.. IMHO, the first one could easily return `(int(*)[6])` type and the last: `(int(*)[x])`... I only hope this gets included in the standard at some point of time – quetzalcoatl Aug 01 '19 at 13:11
3

The online CDECL evaluator is a helpful resource for questions like this:


cdecl

C gibberish ↔ English

int (*p)[4];

    declare p as pointer to array 4 of int
Seth
  • 40,196
  • 9
  • 82
  • 118
  • ...except that `int (*p)[4];` doesn't _declare_ `p`, but __defines__ it. (At least it is in C++, which this question is about. As Johannes once pointed out, in some areas C and C++ differ in what's a definition and what's a declaration.) – sbi Aug 01 '10 at 18:27
  • @sbi: Okay, but every definition is also a declaration ;) "C declarator syntax" is a well-accepted term. – fredoverflow Aug 01 '10 at 18:29
  • @FredOverflow; In C and C++, every definition is also a statement. Still, people rarely ever confuse "definition" and "statement", but confuse "definition" and "declaration" all the time. – sbi Aug 01 '10 at 18:34
  • @sbi: I'm pretty sure the definition `int foo() { return 42; }` is *not* a statement ;) – fredoverflow Aug 01 '10 at 18:45
  • @FredOverflow: `` Scratch that. Then what was it? Isn't the definition of a local, automatic variable considered a statement? Anyway, my point is: People keep messing up declarations and definitions. (For example, more than half of the answers to http://stackoverflow.com/questions/1410563/ were either misleading or plain wrong, in comments people kept suggesting silly counter-examples (`int i;` not a definition), and I had to add a quote from the standard to settle the ever repeating discussions about what's a class definition vs. class declaration.) So I'd like to be precise with it. – sbi Aug 01 '10 at 20:17
  • @sbi: Yes a local automatic variable is a _statement_: a _declaration-statement_. A _function-body_ consists of a _compound-statement_ which is `{` _statement-seq[OPT]_ `}` . A local automatic variable declaration (and definition) is a _declaration-statement_ consisting of a _block-declaration_ consisting of a _simple-declaration_. Outside of a function body a _simple-declaration_ may appear in a context where it is not a _statement_. – CB Bailey Aug 01 '10 at 20:38