1
void m() {
    char a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    char(*c)[3][3] = (char (*)[3][3])a;
    printf("%d\n", *c[0][0]);
}

For instance, in this function the variable a points to a location in memory with 9 integers in a row.

But what about c? Does c point to a location in memory which points to a location in memory that holds 9 integers in a row?

So, technically, is c a single layer pointer or a double layer pointer?

Shouldn't what I said above be true? How come when I execute the below function:

void m() {
    char a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    char(*c)[3][3] = (char (*)[3][3])a;
    printf("%d\n", *c[0][0]);
    printf("a...%p\nc...%p\n", a, c);
}

a and c both point to the same locations? Shouldn't c be a double layer pointer, and a be a pointer to a location in memory?

Jason
  • 1,297
  • 12
  • 24
  • Oh, so then I shouldn't use it? – Jason Aug 27 '14 at 02:49
  • 2
    We're not saying you shouldn't use it. We're saying it's undefined behavior. If you're ok with it doing anything then you can use it. Just be prepared for it to crash, or order pizza, or give your credit card data to Russian hackers, or seemingly work correctly except it leaves a vulnerability silently sitting in your code for several years until someone discovers it and uses it to remove a few million dollars from your business, etc etc. You decide if it's worth it. We think it's probably not, and you should probably avoid it. – OmnipotentEntity Aug 27 '14 at 02:53
  • `printf("%d\n", *c[0][0]);` should be `printf("%d\n", (*c)[0][0]);` – BLUEPIXY Aug 27 '14 at 03:16
  • Actually, UB understates things: it's actually wrong too. Dereferencing `*c` => `1`, and evaluating `1[0][0]` will most likely segfault. – david.pfx Aug 27 '14 at 05:43
  • @david.pfx You do not understand correctly. never `*c => 1` see http://ideone.com/QJJQ1R – BLUEPIXY Aug 27 '14 at 10:14
  • 2
    @BLUEPIXY: You're right of course, but my problem is that I'm finding both the comments here and the accepted answer very unsatisfactory. The standard says little about conversions between array and pointer to array, and I can find nothing to say this is undefined behaviour. Care to comment (or write a better answer)? – david.pfx Aug 27 '14 at 11:25
  • @david.pfx Can you show the part that standard is writing? – BLUEPIXY Aug 27 '14 at 11:35
  • @david.pfx The standard allows converting object pointers (an array decays when operand of a cast expression) to arbitrary object pointers iff they are correctly aligned (otherwise UB) (C11 6.3.2.3 p7). I can hardly imagine how `a` and `c` can have different alignment requirements, but unfortunately I can't really find anything in the standard guaranteeing it. `malloc`ing the storage for `a` would make the code above defined (`malloc` returns memory correctly aligned for all objects). – mafso Aug 27 '14 at 11:36
  • @mafso: A valid pointer can _always_ be converted to a pointer to character, based on the last sentence in that same section. – david.pfx Aug 27 '14 at 13:46
  • @david.pfx: `(char (*)[3][3])` isn't a pointer to character, I think. – mafso Aug 27 '14 at 14:10
  • @mafso: It can be dereferenced to an array, which decays to a pointer to its first element. The type changes, but the value does not. – david.pfx Aug 28 '14 at 00:33
  • I've asked my own question to try to clarify this: http://stackoverflow.com/questions/25539269/is-converting-between-pointer-to-t-array-of-t-and-pointer-to-array-of-t-ever-un – david.pfx Aug 28 '14 at 01:14
  • @0x499602D2: I just about certain it's not UB. – david.pfx Aug 28 '14 at 01:45
  • @0x499602D2 explain why you think that cast is UB? – M.M Aug 28 '14 at 02:17
  • This would be a good question if it focused on the validity of `*c[0][0]` rather than waffling about arrays and pointers – M.M Aug 28 '14 at 02:21
  • @MattMcNabb I saw the new question too. I was under the impression by looking at the code that a cast like that just wasn't right. I thought I had read a post some years back that said it was UB. Guess I was wrong lol – David G Aug 28 '14 at 02:21

2 Answers2

2

the variable a points to a location in memory with 9 integers in a row.

No. The variable a is a location in memory with 9 integers in a row. a is just a name for that location.

Does c point to a location in memory which points to a location in memory that holds 9 integers in a row?

No. c is a location in memory which points to a location in memory that holds 9 integers in a row. c is a name for the location containing the pointer.

So, technically, is c a single layer pointer or a double layer pointer?

Single.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    The type of `c` is `pointer to array size 3 of array size 3 of char`. Its value is the same as the `pointer to array size 9 of char` that array `a` decays into. Casting from one to the other is safe, but is said to be UB. No ints in sight. Care to extend your answer? – david.pfx Aug 27 '14 at 11:10
  • @david.pfx by "its value is the same" you mean that they store the same memory address, however they have different types – M.M Aug 28 '14 at 02:18
0

Take a look of these type definitions:

typedef char9[9];
typedef char3x3[3][3];

If we check the sizes:

cout<<sizeof(char9); 

result will be always 9, there is no alignments in char array.

cout<<sizeof(char3x3);

if it is equal to 9, it is safe to say the bytes ordered the same as the one dimension array. if it is larger than 9, I would say there is alignment between rows, so there are holes between the lines, and then you can't map a pointer of one type upon the other.

SHR
  • 7,940
  • 9
  • 38
  • 57
  • _An array type describes a contiguously allocated nonempty set of objects with a particular member object type._ – BLUEPIXY Aug 27 '14 at 03:50