C/C++

Указатель превращается в двумерный массив. (Си)

Я правильно делаю когда трансформирую указатель в двумерный массив? Чтоб достать нужное значение.
Из этого *ukazatel[] делаю это ukazatel[0][1]
То что это работает, я вижу, но не будет ли это являться какой либо ошибкой?
Нигде такого примера не видел, всё что видел это как стороной данный вопрос обходили и поэлементно копировали массив.
int main()
{
int arr[]={1,2,3};
int *ukazatel[] ={arr};
printf("%d\n", ukazatel[0][1]);
return 0;
}
Очень удобная конструкция. Можно адреса каждого элемента доставать, можно их значения.
Да, твой пример правилен: ты создаёшь одномерный массив указателей на одномерные массивы и работаешь с ним как с двумерным массивом. Это совершенно корректный способ создания в С/C++ и двумерных массивов, и массивов большей размерности.

При выполнении
ukazatel[0][1]
сначала к указателю ukazatel (значением массива является указатель на начало массива) применяется операция [0], которая возвращает arr (указатель). Потом к полученному указателю применяется операция [1] и возвращает значение 2.
Т. е. выполняется: *(*(ukazatel + 0) + 1)

Но если ты создаёшь переменную:
int arr2[3][7];
то в памяти создаётся одномерный массив из 21 элемента и при обращении arr2[i][j] компилятор преобразует [i][j] в индекс этого одномерного массива по формуле i * 7 + j.
Т. е. выполняется *((int*)arr2 + i * 7 + j)

Хотя внешне оба случая выглядят одинаково, внутри они работают по-разному.
Сергей Крыжанков
Сергей Крыжанков
59 823
Лучший ответ
не путайте создание массивов и обращение к памяти по указателям.
Обращение к ukazatel[5] по определению то же самое, что и *ukazatel+5
А многомерность - это просто указатель на указатель и т. д.
Вот с созданием многомерных массивов будет облом: они создаются как одномерные, без всяких внутренних указателей на указатели.
Если создать int arr[3][4]; то взять из него arr[1][1] можно будет только зная размерность этого двумерного массива, т. е. int* ukaz[3]=&arr[0][0]; при обращении ukaz[1][1] скорее всего не попадет в требуемый элемент, а может и прибить программу обращением к несуществующему адресу.
KY
Kiss You
58 269
Игорь Марков Очень интересно, но непонятно.
Мой пример правильный или в нём ошибка есть?
Игорь Марков В имени массива содержится адрес, поэтому я имею право занести этот адрес в тип int*
Вы это имели в виду?
int *ukazatel[] = { arr } В этой строчке всё правильно.
Сергей Крыжанков Не "размерность" а "размер". Размерность - это кол-во координат (индексов массива). И размерность двумерного массива всегда равна 2.
Игорь Марков Я не пониамю что вы сказать хотели. Хоть с размерностью, хоть с размером.
Мой пример правильный или нет?
Игорь Марков А, понял. Ну конечно я не будуобращаться к ukaz[1][1]
если есть такое объявление int* ukaz[3]=&arr[0][0];
int* ukaz[3] это int* ukaz[3][1]

ukaz[1][1] это обращение ко второму несуществующему элементу массива.
Игорь Марков Понял что вы сказать хотели.
Мне это надо попарктиковать ещё, но я думал уже над этим.
Вот неправильный код например
int main()
{
int arr[]={1,2,3,4,5,6};
int *ukaz[4];
ukaz[3] = &arr[0];
printf("%p\n", ukaz[1][1]);
return 0;
}
Массив arr лежит в третьем столбце массива ukaz, а я обращаюсь к первому столбцу.
Игорь Марков Здесь обращаюсь к первому столбцу, который не заполнен ukaz[1][1]
Игорь Марков В моём примере такой проблемы не было, потому что я объявил массив, не указывая размер массива int *ukazatel[] = { arr } ;
Размер массива автоматически заполнился единицей. int *ukazatel[1] = { arr } ;
крестики-нолики?
0

sudo apt-get update && upgrade
Игорь Марков Это линуксоидная команда ведь. Это на мой вопрос ответ?
Станислав Степанов нет.
это удочка на проф. пригодность))

а си-шарп -- то не про меня