Я верю, что то, что я пытаюсь сделать, вероятно, верно, потому что в обоих случаях оно разделено запятой (не типичное задание), но я точно не знаю, и поиск ничего не говорит об этих двух конкретные ситуации.
В обоих случаях я использовал переменную в качестве индекса для двух параллельных массивов.
int a[3] = {10, 20, 30};
int b[3] = {20, 40, 60};
Ситуация № 1: Инициализация структуры для массивов
struct testStruct {
int t1;
int t2;
};
int i = 0;
testStruct test = {a[++i], b[i]}
Ожидаемый результат финальной строки: test = {20, 40}
Ситуация № 2: Передача определенных значений из массивов в качестве аргументов функции
void testFunc(int t1, int t2) {
// do stuff
}
int i = 0;
test(a[++i], b[i]);
Ожидаемый результат финальной строки: test(20, 40)
Это действительный код? И если это так, действительно ли это во всех компиляторах?
Результат, который я ожидаю? Если так, это из-за массивов или из-за запятой?
Спасибо!
Я бы посоветовал не использовать такие «уловки» в вашем коде в долгосрочной перспективе, это кошмар обслуживания и о нем трудно рассуждать. Почти всегда есть альтернативы, например этот код:
testStruct test = {a[++i], b[i]}
может быть изменено на:
++i ;
testStruct test = {a[i], b[i]}
Таким образом, сказав, что ни в одном из этих случаев оператор запятой не используется ни в вызовах функций, ни в списках инициализации, запятая — это элементы грамматики и ничего более.
Ваша первая ситуация хорошо определена, хотя есть некоторые предостережения в зависимости от того, является ли это C ++ 11 или до C ++ 11.
В обоих случаях после каждой запятой есть точка последовательности, хотя до C ++ 11 порядок вычисления не указан. Таким образом, мы можем увидеть это для случая до C ++ 11, перейдя к дефект 430 который говорит:
Недавний отчет об ошибке GCC (
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11633) спрашивает о
срок действияint count = 23; int foo[] = { count++, count++, count++ };
это не определено или не указано или что-то еще?
и ответ (Акцент шахты идет вперед):
Я считаю, что стандарт ясно, что каждое выражение инициализатора в
вышеизложенное является полным выражением (1.9 [intro.execution] / 12-13; см. Также
выпуск 392) и, следовательно, после каждого
выражение (1.9 [intro.execution] / 16). я согласна с тем что стандарт делает
не похоже, чтобы диктовать порядок, в котором выражения,
и, возможно, так и должно быть. Кто-нибудь знает компилятор, который не
оценивать выражения слева направо?
В C ++ 11 он запекается в проект стандарта C ++ 11 в разделе 8.4.5
абзац, в котором говорится:
В пределах списка инициализатора списка фигурных скобок
пункты-инициализаторы, включая те, которые являются результатом расширений пакета
(14.5.3), оцениваются в порядке их появления. То есть,
каждое значение вычисления и побочный эффект, связанный с данным
предложение initializer секвенируется перед каждым вычислением значения и
побочный эффект связан с любым инициализатором-предложением, которое следует за ним в
разделенный запятыми список из списка инициализаторов.
Я придерживаюсь C ++ 11 в будущем, так как он не меняет ответ для остальной части контента, хотя формулировка секвенирования действительно отличается, вывод такой же.
Вторая ситуация вызывает неопределенное поведение поскольку порядок вычисления аргументов функции не определен, а их оценка неопределенно упорядочена по отношению друг к другу. Мы можем увидеть это неопределенное поведение из раздела 1.9
параграф 15 который говорит:
Если не указано иное, оценки операндов отдельных операторов
и подвыражений отдельных выражений не упорядочены. [
Примечание. В выражении, которое оценивается более одного раза в течение
выполнение программы, непоследовательное и неопределенно упорядоченное
оценки его подвыражений не должны выполняться последовательно
в разных оценках. —Конец примечания] Расчет стоимости
операнды оператора секвенируются до вычисления значения
результат оператора. Если побочный эффект на скалярном объекте
непоследовательный относительно любого другого побочного эффекта на том же скаляре
вычисление объекта или значения с использованием значения того же скаляра
объект, поведение не определено.
и предоставляет следующий пример:
f(i = -1, i = -1); // the behavior is undefined
Первый фрагмент кода
testStruct test = {a[++i], b[i]};
допустимо (если добавить точку с запятой), потому что в соответствии со стандартом C ++
4 В списке инициализаторов списка фигурных скобок
пункты-инициализаторы, включая те, которые являются результатом расширений пакета
(14.5.3), оцениваются в порядке их появления. То есть,
каждое значение вычисления и побочный эффект, связанный с данным
предложение initializer секвенируется перед каждым вычислением значения и
побочный эффект, связанный с любым пунктом инициализатора, который следует за ним в
разделенный запятыми список из списка инициализаторов.
Примите во внимание, что компилятор GCC 4.8.1 имеет (или, по крайней мере, имел) ошибку, которую я описал
Вот
Хотя описание написано на русском языке, вы можете перевести его, используя, например, сервис goofle «translate».
Однако второй фрагмент кода
test(a[++i], b[i]);
имеет неопределенное поведение, потому что порядок вычисления аргументов функции не определен.
Вы могли бы написать вместо
test( { a[++i], b[i] } );
В этом случае выражение будет правильно сформировано.