Нет, B
, *B
, B[0]
и &B[0][0]
не совпадают.
Их типы различаются:
B
: массив 3 из массива 3 двойных *B
: массив 3 двойных B[0]
: массив 3 двойных &B[0][0]
: указатель на двойные
Когда вы позволяете им распадаться на указатели (четвертый элемент уже является указателем), типы по-прежнему разные:
B
: указатель на массив 3 из double *B
: указатель на double B[0]
: указатель на double &B[0][0]
: указатель на double
Поскольку указатель на массив эквивалентен указателю на его первый элемент, эти четыре выражения имеют одинаковое значение.
Обратите внимание, что последние 3 имеют один и тот же тип. Они полностью эквивалентны. Тип первого содержит больше информации. Он «знает», что есть группы по 3 двойных.
Это различие типов можно показать, запустив следующую программу:
#include <stdio.h>
double B[3][3] = {
{ 1., 0., 0. },
{ 0., 1., 0. },
{ 0., 0., 1. }
};
int main() {
printf("%p: %zu\n", (void *) B, sizeof(*B));
printf("%p: %zu\n", (void *) (*B), sizeof(*(*B)));
printf("%p: %zu\n", (void *) (B[0]), sizeof(*(B[0])));
printf("%p: %zu\n", (void *) (&B[0][0]), sizeof(*(&B[0][0])));
}
Что для меня выведет:
0x404040: 24
0x404040: 8
0x404040: 8
0x404040: 8
Вы можете видеть, что первый элемент отличается тем, что элементы, на которые он указывает, имеют размер в три раза больше, чем другие элементы.