Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.65/40: Рейтинг темы: голосов - 40, средняя оценка - 4.65
 Аватар для yutsura
-11 / 0 / 0
Регистрация: 14.07.2015
Сообщений: 30

Как передать двухмерный массив в функцию по ссылке?

21.05.2018, 09:46. Показов 8829. Ответов 21

Студворк — интернет-сервис помощи студентам
Преподаватель в универе просит написать функцию вида
C++
1
void st3(&array, &n, &m)
. Бьюсь головой об стол уже второй день и никак не могу найти решение. Друзья, помогите, пожалуйста!
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
21.05.2018, 09:46
Ответы с готовыми решениями:

Как передать в функцию двухмерный динамический массив по ссылке?
как передать в функцию двухмерный динамический массив по ссылке?

Как передать двухмерный массив в функцию?
Подскажите пожалуйста, как в функцию передать двухмерный массив? Пробовал так: void FuncArr(int** arr){ arr = 111111; } void...

Как в функцию передать параметр - двухмерный массив
void max_el() { int i,j,max; for ( i=1 ; i<=n; i++) for ( j=1; j<=m; j++) //nahodim maksimalnii element...

21
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
21.05.2018, 10:27
Функции, передача массива в качестве параметра
Функции, передача массива в качестве параметра
0
12 / 12 / 13
Регистрация: 18.05.2018
Сообщений: 67
21.05.2018, 11:59
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
 
using std::cout;
using std::endl;
 
bool xxx(int (&a)[2][3])
{
    for(int i = 0; i < 2; i++)
        for(int j = 0; j < 3; j++)
            cout << a[i][j] << endl;
 
    return true;
}
 
int main()
{
    int a[2][3] = {
        {0, 1, 2},
        {3, 4, 5}
    };
 
    xxx(a);
 
    return 0;
}
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
21.05.2018, 18:47
В первом коде UB.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
21.05.2018, 20:38
Цитата Сообщение от rat0r Посмотреть сообщение
В первом коде UB
Где именно?
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
21.05.2018, 20:52
Цитата Сообщение от Evg Посмотреть сообщение
Где именно?
Ну, во-первых, подозрение вызывает каст двумерного массива к указателю. Но, допустим, указатель получили корректно (&a[0][0]), дальше в функции получается выход за границы массива. Обсуждалось тут Из одномерного массива сформировать двумерный массив

Добавлено через 7 минут
Кстати, тему от 2009-го года я даже находил, кажется. Но не стал её поднимать, т.к. слишком старая.
Но раз уж она всплыла сейчас, то почему бы не написать про то, что там UB.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
21.05.2018, 21:05
В теме "Распространённые ошибки" удалили, так что лучше здесь. Чтобы не скакать по разным местам

Цитата Сообщение от rat0r Посмотреть сообщение
1. Это раздел про C++
Возможно, в Си и Си++ действительно разное поведение. В Си++ я не силён

Цитата Сообщение от rat0r Посмотреть сообщение
Впрочем, в стандарте C написано то же самое по смыслу
Можешь привести ссылку? Я не для того, чтобы срач развести, а для выяснения истины. Вероятно, ты уже с ходу знаешь, где искать, а потому просто время сэкономим

Добавлено через 5 минут
В ссылке (если имелась в виду она) http://eel.is/c++draft/expr.add#4 я не вижу подтверждения тому, что в коде UB
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
21.05.2018, 21:08
Цитата Сообщение от Evg Посмотреть сообщение
В ссылке (если имелась в виду она) http://eel.is/c++draft/expr.add#4 я не вижу подтверждения тому, что в коде UB
Да, имелась в виду она.
В теме Из одномерного массива сформировать двумерный массив я писал про то, почему в подобном коде UB.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
21.05.2018, 21:30
Если ты имеешь в виду этот пост Из одномерного массива сформировать двумерный массив, то ты его неправильно интерпретируешь

Продублирую, чтобы перед глазами было:

C++
int mm[50][2];
...
int *m=&mm[0][0];
for(int i=0;i<100;i++)
    std::cout<<m[i]<<' ';
Выдержка из http://eel.is/c++draft/expr.add#4:

When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand.
If the expression P points to element x[i] of an array object x with n elements, the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i+j] if 0≤i+j≤n; otherwise, the behavior is undefined.
В качестве "expression P" здесь имеется в виду &mm[0], &mm[1], &mm[2] и т.п. Т.е. имеется в виду указатель на одномерный массив. В нашем случае указатель должен быть на сущность, которая представляет собой массив из двух элементов. Т.е. имеет тип int(*)[2]. Это утверждение справедливо именно для таких типов указателей

В противном случае мы бы имели следующее. Есть указатель "int *ppp = &mm[0][1]". Формально такой указатель НЕ удовлетворяет условию "If the expression P points to element x[i] of an array object x with n elements", поскольку адрес этого выражения не совпадает ни с одним из адресов &mm[0], &mm[1] и т.п. (ведь в выдержке речь идёт про одномерный массив). При этом указатель "ppp + 1" совпадает с адресом элемента &mm[1]. Т.е. первая часть утверждения как бы ложна, а вторая как бы истина, а потому формально попадаем в "otherwise, the behavior is undefined", что выглядит заведомо абсурдным

Поэтому данное правило не корректно применять к коду, который через обычный указатель обходит все элементы массива, потому что в стандарте описывается один тип указателя, а ты применяешь этот пункт к другому типу

Вообще стандарт это вещь такая, где зачастую одного пункта недостаточно для того, чтобы понять точный смысл. Тут как в юридическом документе надо прочитать миллион разных пунктов, по совокупности которых как бы можно составить какое-то формально корректное утвеждение

Добавлено через 4 минуты
Та тема очень старая, в те времена ещё на форуме не было TheCalligrapher. Он умеет доступно и человеческим языком объяснить многие тонкости стандарта. Так что для полного понимания лучше бы спросить у него
1
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
21.05.2018, 21:39
Цитата Сообщение от Evg Посмотреть сообщение
Если ты имеешь в виду этот пост Из одномерного массива сформировать двумерный массив, то ты его неправильно интерпретируешь
Мой последний пост-эксперимент (Из одномерного массива сформировать двумерный массив) с constexpr-функциями меня убеждает в обратном.

Цитата Сообщение от Evg Посмотреть сообщение
В качестве "expression P" здесь имеется в виду &mm[0], &mm[1], &mm[2] и т.п. Т.е. имеется в виду указатель на одномерный массив. В нашем случае указатель должен быть на сущность, которая представляет собой массив из двух элементов. Т.е. имеет тип int(*)[2]. Это утверждение справедливо именно для таких типов указателей
В противном случае мы бы имели следующее. Есть указатель "int *ppp = &mm[0][1]". Формально такой указатель НЕ удовлетворяет условию "If the expression P points to element x[i] of an array object x with n elements", поскольку адрес этого выражения не совпадает ни с одним из адресов &mm[0], &mm[1] и т.п. (ведь в выдержке речь идёт про одномерный массив). При этом указатель "ppp + 1" совпадает с адресом элемента &mm[1]. Т.е. первая часть утверждения как бы ложна, а вторая как бы истина, а потому формально попадаем в "otherwise, the behavior is undefined", что выглядит заведомо абсурдным
Ничего не понял, если честно.

Цитата Сообщение от Evg Посмотреть сообщение
Он умеет доступно и человеческим языком объяснить многие тонкости стандарта.
Тут никаких тонкостей нет, всё на поверхности.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
21.05.2018, 22:24
Цитата Сообщение от rat0r Посмотреть сообщение
Мой последний пост-эксперимент (Из одномерного массива сформировать двумерный массив) с constexpr-функциями меня убеждает в обратном
Code
$ g++-4.9.2 t.cc -c -std=c++11
<ok>
Чисто для контроля в stati_assert воткнул сравнение не с 3, а с 4

Code
$ g++-4.9.2 t.cc -c -std=c++11
t.cc:3:1: error: static assertion failed: Wrong number.
 static_assert( get_third( &a[0][0] ) == 4, "Wrong number." );
 ^
чтобы убедиться, что всё запущено правильно и нигде нет опечаток

Получается, что этот эксперимент не говорит ни о чём, если один компилятор ведёт себя так, а другой эдак

Цитата Сообщение от rat0r Посмотреть сообщение
Ничего не понял, если честно
Вкратце и если на пальцах, то в стандарте говорится про свойство квадрата, но ты его применяешь к треугольнику

Цитата Сообщение от rat0r Посмотреть сообщение
Тут никаких тонкостей нет, всё на поверхности
С учётом того, что есть два противоположных мнения, уже нельзя говорить о том, что всё на поверхности
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
21.05.2018, 22:35
Цитата Сообщение от Evg Посмотреть сообщение
g++-4.9.2
Не показатель. Подревнее ничего не нашлось?
Кликните здесь для просмотра всего текста
Могу притащить пример кода, который должен компилироваться со времён C++98, но в g++ он компилируется только с 6-й версии (2016 год выпуска, вроде).


Цитата Сообщение от Evg Посмотреть сообщение
Вкратце и если на пальцах, то в стандарте говорится про свойство квадрата, но ты его применяешь к треугольнику
Ладно. Вообразим, что я в данном случае применяю не те пункты стандарта к арифметике указателей. Тогда прошу показать "те" пункты.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
21.05.2018, 22:59
Цитата Сообщение от rat0r Посмотреть сообщение
Подревнее ничего не нашлось?
Какой компилятор есть, тем и пользовался. В любом случае, если более поздние версии компилятора выдают ошибку, то почти наверняка по другой причине. Если бы те фрагменты стандарта, которые ты привёл, были применимы к этому месту, то грамотно построенный компилятор выдал бы предупреждение, а не ошибку, поскольку в стандарте не сказано, что так нельзя делать, в стандарте лишь сказано про UB. Поэтому выдача ошибки скорее всего подтверждает какой-нибудь другой пункт стандарта, например, связанный с constexpr'ами

Цитата Сообщение от rat0r Посмотреть сообщение
Тогда прошу показать "те" пункты
Я не отношусь к тем людям, которые читают стандарт на ночь, а потому с ходу вряд ли найду весь ворох нужных пунктов. Но описание в симметричном разделе для C99 выглядит следующим образом. Жирным выделил момент, где сказано о том, что указатель и арифметика над ним должны находиться внутри одного и того же объекта (а не типа одномерного массива)

Тут даже допускается выход на один элемент за правую границу объекта-массива, но в нашем случае это не интересно, т.к. где-то позже будет написано, что такой указатель можно использовать только для сравнений и других арифметических операций, но нельзя разыменовывать (или это станет следствием нескольких пунктов)

ISO/IEC 9899:1999 (E)

6.5.6 Additive operators

8
When an expression that has integer type is added to or subtracted from a pointer, the
result has the type of the pointer operand. If the pointer operand points to an element of
an array object, and the array is large enough, the result points to an element offset from
the original element such that the difference of the subscripts of the resulting and original
array elements equals the integer expression. In other words, if the expression P points to
the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and
(P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of
the array object, provided they exist. Moreover, if the expression P points to the last
element of an array object, the expression (P)+1 points one past the last element of the
array object, and if the expression Q points one past the last element of an array object,
the expression (Q)-1 points to the last element of the array object. If both the pointer
operand and the result point to elements of the same array object
, or one past the last
element of the array object, the evaluation shall not produce an overflow; otherwise, the
behavior is undefined. If the result points one past the last element of the array object, it
shall not be used as the operand of a unary * operator that is evaluated.
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
21.05.2018, 23:11
Цитата Сообщение от Evg Посмотреть сообщение
С учётом того, что есть два противоположных мнения, уже нельзя говорить о том, что всё на поверхности
Ну, скажем так. Конечно, нужен определённый уровень, чтоб читать стандарт.
Есть места, типа поведения темплейтов, где всё настолько запутано или недописано, что никто не может точно сказать, какое должно быть поведение при компиляции специально подобранного кода.
Тут же случай весьма простой и если для кого-то это не так — то просто значит уровень не тот.

Добавлено через 11 минут
Цитата Сообщение от Evg Посмотреть сообщение
Какой компилятор есть, тем и пользовался.
В GCC есть баги с constexpr (прокатывает код, который не должен компилироваться) даже в 6+ версии.

Цитата Сообщение от Evg Посмотреть сообщение
Если бы те фрагменты стандарта, которые ты привёл, были применимы к этому месту, то грамотно построенный компилятор выдал бы предупреждение, а не ошибку, поскольку в стандарте не сказано, что так нельзя делать, в стандарте лишь сказано про UB.
constexpr там не просто так, а именно для того, чтобы сделать UB ошибкой компиляции. Т.к. выражение не является константным, если оно содержит UB из Core Language:
Цитата Сообщение от http://eel.is/c++draft/expr.const#2
An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:

(2.6) — an operation that would have undefined behavior as specified in [intro] through [cpp] of this document [ Note: including, for example, signed integer overflow ([expr.prop]), certain pointer arithmetic ([expr.add]), division by zero, or certain shift operations — end note ];
(подчёркнуто мною)

Цитата Сообщение от Evg Посмотреть сообщение
Но описание в симметричном разделе для C99 выглядит следующим образом. Жирным выделил момент, где сказано о том, что указатель и арифметика над ним должны находиться внутри одного и того же объекта (а не типа одномерного массива)
Там написано, что должны получаться указатели на элементы одного и того же объекта-массива.
int* не является указателем на элемент массива int[50][2], т.к. элемент этого массива это int[2].
В массиве int mm[50][2], mm[0] и, например, mm[1] — это два разных объекта-массива int[2]. Получив указатель на элемент первого массива (например, &mm[0][0]), во второй никак арифметикой с этим указателем не попадёшь. Что в C, что в C++.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
23.05.2018, 21:12
Цитата Сообщение от rat0r Посмотреть сообщение
int* не является указателем на элемент массива int[50][2], т.к. элемент этого массива это int[2]
Так вот я про то и говорю. Ты в своих рассуждения пытаешься применить запрет, который касается одного типа указателя, к другому типу указателя. Если бы m имел тип "int (*)[2]" и был инициализирован адресом "&mm[0]", то твои рассуждения были бы справедливы, потому что именно про такой тип указателя речь идёт в приведённом тобой пункте стандарта. Но m имеет тип int*, а потому к этому пункту стандарта отношения не имеет

А про UB и constexpr - это я понимаю. Но если на этом тесте происходит выдачи ошибки компилятора, то это условно подтверждает, что в этом месте UB. Но который из миллиона всяких UB'ов - неизвестно. Ты утверждаешь, что UB именно этот. Я утверждаю, что нет, потому что этот UB про другое. Потому и написал, что в примере с constexpr'ами, возможно, речь идёт о каком-то другом пункте стандарта
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
23.05.2018, 21:55
Цитата Сообщение от Evg Посмотреть сообщение
Если бы m имел тип "int (*)[2]" и был инициализирован адресом "&mm[0]", то твои рассуждения были бы справедливы, потому что именно про такой тип указателя речь идёт в приведённом тобой пункте стандарта.
Не вижу, где в пункте стандарта написано, что там речь только про тип указателя int(*)[2]. Там про сложение числа с любым указателем.

Если честно, мне не понятно, что тут может вызывать затруднение, т.к. тут идёт речь про довольно простые вещи: массив, элемент массива, указатель на элемент массива.

Указатель int* m был инициализирован выражением &m[0][0]. m это массив int[50][2], m[0] это массив int[2], m[0][0] это первый элемент массива int[2], а &m[0][0] — адрес этого элемента. Следовательно, при прибавлении или вычитании числа к этому указателю нельзя выходить за пределы массива размера 2. Вот и всё. Я не знаю, как ещё понятнее это можно описать.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
23.05.2018, 22:34
Цитата Сообщение от rat0r Посмотреть сообщение
Если честно, мне не понятно, что тут может вызывать затруднение
А мне, как более-менее понимающему философию Си, не понятно, с какого бодуна в таком коде может быть UB. Я не вижу ни одной, даже высосанной из пальца причины для этого. Про Си++ я ещё как-то мог бы понять, если бы его создавали изначально, но он практически полностью наследует свойства Си

Стандарт, как и любой юридический документ не читают, а трактуют. У меня одна трактовка (в которой побеждает здравый смысл), у тебя своя трактовка (в которой побеждает юриспруденция, хотя я по прежнему с твоей трактовкой не согласен). Чтобы докопаться до реальной истины, как показывает практика, нужно найти в разных местах стандарты разные утверждения, из которых выстроится чёткая и однозначная трактуемая картина. Мне лень этим заниматься

Цитата Сообщение от rat0r Посмотреть сообщение
Указатель int* m был инициализирован выражением &m[0][0]. m это массив int[50][2], m[0] это массив int[2], m[0][0] это первый элемент массива int[2], а &m[0][0] — адрес этого элемента. Следовательно, при прибавлении или вычитании числа к этому указателю нельзя выходить за пределы массива размера 2. Вот и всё. Я не знаю, как ещё понятнее это можно описать
Мне не надо понятнее описывать, я прекрасно понимаю, что ты имеешь в виду. Ты считаешь, что &m[0][0] и &m[0] - это одно и то же. Я считаю, что нет (я говорю о формальной точке зрения, которой придерживается стандарт). Возможно, подробный анализ стандарта и покажет, это одно и то же, или нет. Но как только появились разные трактовки в этом месте, сразу же появились и разные выводы
1
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
23.05.2018, 22:59
Цитата Сообщение от Evg Посмотреть сообщение
У меня одна трактовка (в которой побеждает здравый смысл)
Побеждает банальная предвзятость, т.к. на UB указали в твоём коде.
Цитата Сообщение от Evg Посмотреть сообщение
Чтобы докопаться до реальной истины, как показывает практика, нужно найти в разных местах стандарты разные утверждения, из которых выстроится чёткая и однозначная трактуемая картина.
Если мы считаем, что нам известно, что такое массивы, как определена индексация и оператор взятия адреса, то на собственно арифметику указателей остаётся только один параграф что в стандарте C, что в стандарте C++. Копать некуда.
Цитата Сообщение от Evg Посмотреть сообщение
Мне лень этим заниматься
Ожидаемо.
Цитата Сообщение от Evg Посмотреть сообщение
Ты считаешь, что &m[0][0] и &m[0] - это одно и то же.
В каком смысле я считаю, что это одно и то же?
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
24.05.2018, 14:07
Цитата Сообщение от rat0r Посмотреть сообщение
Побеждает банальная предвзятость, т.к. на UB указали в твоём коде
Если ты действительно в это веришь, то разговор нужно заканчивать, ибо при таких раскладах это будет называть "пустой трёп"

Цитата Сообщение от rat0r Посмотреть сообщение
В каком смысле я считаю, что это одно и то же?
В соответствии со стандартом к &m[0] нельзя прибавлять 99. Мы оба с этим согласны. Однако ты считаешь, что из этого вытекает, что к &m[0][0] так же нельзя прибавлять 99. А я так не считаю. Как с точки зрения здравого смысла, так и с точки зрения того, что формально в стандарте я не вижу подтверждения этому

Добавлено через 3 часа 52 минуты
Кстати, я ещё понял, почему твой пример с constexpr'ом некорректный (демонстрирует не то)

C
int mm[50][2];
int *m = &m[0][0];
Если смотреть на указатель &mm[0], то в соответствии со стандартом к нему можно прибавлять 0, 1, 2, ... 49. Но нельзя прибавлять 50, 51, .... Поскольку mm является массивом из 50 элементов. Ты утверждаешь, что для &m[0][0] действуют те же ограничения, т.е. по твоему к m нельзя прибавлять 50, 51 и т.п.

В качестве подтверждения своей гипотезе ты приводишь тест с constexpr'ом. Но проблема в том, что ты в нём взял слишком вырожденный пример - массив 2x2 (т.е. с одинаковыми рамерностями), и эта симметрия ввела тебя в заблуждение

Если же этот пример переписать более культурно (с правильно указанным 2-мерным инициализаторов) и менее симметрично (с неквадратным массивом), то получим такую картину

C++
constexpr int a[3][2] = { {1,2}, {3,4}, {5,6} };
constexpr int get_third( int const * first ) { return * ( first + 2 ); }
static_assert( get_third( (int const*) &a[0][0] ) == 3, "Wrong number." );
Code
$ g++-7.3.0 t.cc -std=c++11 -c
t.cc:3:1: error: non-constant condition for static assertion
 static_assert( get_third( (int const*) &a[0][0] ) == 3, "Wrong number." );
 ^~~~~~~~~~~~~
t.cc:3:25:   in constexpr expansion of 'get_third((& a[0][0]))'
t.cc:3:1: error: array subscript value '2' is outside the bounds of array type 'const int [2]'
Видим, что ругань с constexpr'ом была из-за того, что при вычислении constexpr'а пришлось вылезти за границу подмассива {1,2}

В соответствии со стандартом к указателю &a[0] можно прибавлять 0, 1 или 2. Ты предположил, что эти же правила касаются и указателя &a[0][0] на основании того, что случилась ошибка. Потому что ты ошибку трактовал как относящуюся именно к этому пункту стандарта. Однако прибавление 2 к такому указателю вызвало проблему. Потому что эта причина, по которой компилятор в этом примере выдаёт ошибку, к данному пункту стандарта не относится, а относится к какому-то другому месту стандарта, т.к. проблему вызвал переход за границу младшего измерения, а не старшего

Другими словами, пример с constexpr'ом НЕ годится как аргумент в подтверждение твоей гипотезы
1
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
24.05.2018, 18:49
Цитата Сообщение от Evg Посмотреть сообщение
Если ты действительно в это веришь, то разговор нужно заканчивать, ибо при таких раскладах это будет называть "пустой трёп"
Пустой трёп начался, когда пошли апелляции к знанию философии.

Цитата Сообщение от Evg Посмотреть сообщение
по твоему к m нельзя прибавлять 50, 51 и т.п.
Даже 3 прибавлять нельзя.

Цитата Сообщение от Evg Посмотреть сообщение
В качестве подтверждения своей гипотезе ты приводишь тест с constexpr'ом.
В качестве подтверждения — стандарт. constexpr чисто в довесок.

Цитата Сообщение от Evg Посмотреть сообщение
с правильно указанным 2-мерным инициализаторов
{ 1, 2, 3, 4, 5, 6, } — тоже правильный инициализатор для массива 3 на 2.

Цитата Сообщение от Evg Посмотреть сообщение
Видим, что ругань с constexpr'ом была из-за того, что при вычислении constexpr'а пришлось вылезти за границу подмассива {1,2}
Через 3 дня до тебя дошло, о чём я писал с самого начала, браво!
Это наводит на мысль, что весь тред ты спорил сам с собой, а не с тем, что говорю я. Надеюсь, ещё через 3 дня ты поймёшь, почему там, где я говорю, UB.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.05.2018, 18:49
Помогаю со студенческими работами здесь

Как передать в функцию указатель на двухмерный массив?
Здравствуйте. Как передать в функцию указатель на двухмерный массив? Код компилируется, но дебаггер показал что в функции двухмерный...

Как можно передать массив по ссылке в функцию?
Привет всем! приведу пример вот функция fill заполняет массив a и извлекает 3-элемент public static int fill(int a){ ...

Передать двухмерный массив в функцию
Допустим, у меня есть двухмерный массив символов char level = { &quot; &quot;, &quot; &quot;, &quot; ...

Передать двухмерный массив структур в функцию
Всем привет. Есть такой код - struct Array { float a; float b; }; void wr() {

Нужно передать двухмерный динамический массив в функцию
В функции пользователь сам вводит размер матрицы(описывать функцию не вижу смысла, мне нужно только знать как написать строку...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru