Кэширование viewstate?

Кэширование ViewState

Это отличная идея, но она реализована для SharePoint. Интересно, есть ли решение для обычных страниц asp.net, которое делает то же самое, кэширует состояния просмотра. Е ( "% d", ++, х, х + 1); Какой выход он будет производить всегда? Большинство студентов сказали неопределенное поведение. Может ...

Наш класс задал этот вопрос профессору по программированию на C:

Вам дан код:

int x=1;
printf("%d",++x,x+1);

Какой вывод он всегда будет производить?

Большинство учеников сказали неопределенное поведение. Может кто-нибудь помочь мне понять, почему это так?

Спасибо за редактирование и ответы, но я все еще в замешательстве.

35
задан Stephen 23 August 2011 в 05:11
поделиться

8 ответов

Каждый раз, когда поведение программы не определено, может случиться что угодно - классическая фраза гласит, что «демоны могут вылететь из вашего носа» - хотя большинство реализаций не заходят так далеко .

Аргументы функции концептуально оцениваются параллельно (технический термин заключается в том, что между их оценками нет точки последовательности). Это означает, что выражения ++ x и x + 1 могут быть вычислены в этом порядке, в обратном порядке, или каким-то образом с чередованием . Когда вы изменяете переменную и пытаетесь получить доступ к ее значению параллельно, поведение не определено.

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

Однако компилятор может сгенерировать такой код:

  1. Загрузить x в регистр r1 .
  2. Вычислите x + 1 , прибавив 1 к r1 .
  3. Вычислите ++ x , прибавив 1 к r1 . Это нормально, потому что x загружен в r1 . Учитывая, как был спроектирован компилятор, шаг 2 не мог изменить r1 , потому что это могло произойти только в том случае, если x был прочитан, а также записан между двумя точками последовательности. Что запрещено стандартом C.
  4. Сохранить r1 в x .

И на этом (гипотетическом, но правильном) компиляторе программа выдаст 3.

( РЕДАКТИРОВАТЬ: передача дополнительного аргумента в printf верна (§7.19. 6.1–2 в N1256 ; спасибо Prasoon Saurav ) за указание на это. Также: добавлен пример.)

14
ответ дан 27 November 2019 в 06:59
поделиться

Какой результат будет всегда?

Он будет производить 2 во всех средах, которые я могу придумать. Однако строгая интерпретация стандарта C99 делает поведение неопределенным, поскольку доступ к x не соответствует требованиям, которые существуют между точками последовательности.

Большинство студентов отметили неопределенное поведение. Может ли кто-нибудь помочь мне понять, почему это так?

Теперь я отвечу на второй вопрос, который я понимаю как «Почему большинство студентов моего класса говорят, что показанный код представляет собой неопределенное поведение?» и я думаю, что до сих пор никто не ответил. Одна часть студентов помнит примеры неопределенного значения выражений, таких как

f(++i,i)

. Код, который вы даете, соответствует этому шаблону, но студенты ошибочно думают, что поведение определено в любом случае, потому что printf игнорирует последний параметр. Этот нюанс смущает многих студентов. Другая часть ученика будет так же хорошо разбираться в стандартах, как Дэвид Торнли, и будет говорить «неопределенное поведение» по правильным причинам, объясненным выше.

2
ответ дан 27 November 2019 в 06:59
поделиться

Правильный ответ: код вызывает неопределенное поведение.

Причина, по которой поведение не определено, заключается в том, что два выражения ++ x и x + 1 изменяют x и читают x ] по не связанной (с модификацией) причине, и эти два действия не разделены точкой последовательности. Это приводит к неопределенному поведению в C (и C ++). Требование изложено в 6.5 / 2 стандарта языка C.

Обратите внимание, что неопределенное поведение в этом случае не имеет абсолютно ничего общего с тем фактом, что функции printf передается только один спецификатор формата и два фактических аргумента. Предоставление большего количества аргументов для printf , чем есть спецификаторов формата в строке формата, совершенно законно в C. Опять же, проблема коренится в нарушении требований к оценке выражений языка C.

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

int inc_x(int *x) { return ++*x; }
int x_plus_1(int x) { return x + 1; }

int x = 1;
printf("%d", inc_x(&x), x_plus_1(x));

. Приведенный выше код «эквивалентен» исходному, за исключением того, что операции, в которых задействованы наши x , заключены в функции. Что произойдет в этом последнем примере?

В этом коде нет неопределенного поведения. Но поскольку порядок оценки printf аргументов не указан , этот код производит неопределенное поведение , т. Е.возможно, что printf будет вызываться как printf («% d», 2, 2) или как printf («% d», 2, 3) . В обоих случаях на выходе действительно будет 2 . Однако важным отличием этого варианта является то, что все обращения к x обертываются в точки последовательности, присутствующие в начале и в конце каждой функции, поэтому этот вариант не приводит к неопределенному поведению.

Это именно то рассуждение, которое некоторые другие плакаты пытаются навязать исходному примеру. Но это невозможно. Исходный пример дает поведение undefined , что является совершенно другим зверьком. Очевидно, они пытаются настаивать на том, что на практике неопределенное поведение всегда эквивалентно неопределенному поведению. Это полностью фальшивое заявление, которое указывает только на отсутствие опыта у тех, кто его делает. Исходный код производит неопределенное поведение, точка.

Чтобы продолжить пример, давайте изменим предыдущий пример кода на

printf("%d %d", inc_x(&x), x_plus_1(x));

, вывод кода в целом станет непредсказуемым. Он может печатать 2 2 или 2 3 . Однако обратите внимание, что даже несмотря на то, что поведение непредсказуемо, оно по-прежнему не приводит к неопределенному поведению . Поведение не указано , бит не не определен . Неопределенное поведение ограничено двумя возможностями: либо 2 2 , либо 2 3 . Неопределенное поведение ничем не ограничивается. Он может отформатировать жесткий диск вместо того, чтобы что-то печатать. Почувствуйте разницу.

11
ответ дан 27 November 2019 в 06:59
поделиться

На выходе вероятно будет 2 в каждом разумном случае. На самом деле у вас есть неопределенное поведение.

В частности, стандарт гласит:

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

Существует точка последовательности перед , оценивающая аргументы функции, и точка последовательности после , где все аргументы были оценены (но функция еще не вызывалась). Между этими двумя (т. Е. Пока оцениваются аргументы) есть не точка последовательности (если аргумент не является выражением, содержащим внутреннее выражение, например, используя && || или , оператор).

Это означает, что вызов printf считывает предыдущее значение как , чтобы определить сохраняемое значение (т. Е., ++ x ) и для определения значения второго аргумента (т. е. x + 1 ). Это явно нарушает приведенное выше требование и приводит к неопределенному поведению.

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

40
ответ дан 27 November 2019 в 06:59
поделиться

Мы говорим о неопределенном поведении правильно, но есть еще один недостаток: printf может дать сбой. Он выполняет файловый ввод-вывод; существует множество причин, по которым он может выйти из строя, и их невозможно устранить, не зная полной программы и контекста, в котором она будет выполняться.

1
ответ дан 27 November 2019 в 06:59
поделиться

При повторении codaddict ответ будет 2.

printf будет вызван с аргументом 2, и он распечатает его.

Если этот код поместить в контекст вроде:

void do_something()
{
    int x=1;
    printf("%d",++x,x+1);
}

, тогда поведение этой функции полностью и однозначно определено. Я, конечно, не утверждаю, что это хорошо или правильно или что значение x можно определить впоследствии.

0
ответ дан 27 November 2019 в 06:59
поделиться

Вывод будет всегда (для 99,98% наиболее важных компиляторов и систем, совместимых со стандартом) 2.

Согласно стандарту, это, по определению, "неопределенное поведение", определение/ответ, который сам себя оправдывает и ничего не говорит о том, что на самом деле может произойти, и особенно почему.

Утилита splint (которая не является инструментом проверки соответствия std), а значит и программисты splint, считают это "неопределенным поведением". В принципе, это означает, что оценка (x+1) может дать 1+1 или 2+1, в зависимости от того, когда будет произведено обновление x. Поскольку, однако, выражение отбрасывается (формат printf читает 1 аргумент), на вывод это не влияет, и мы можем сказать, что это 2.

undefined.c:7:20: Аргумент 2 изменяет x, используемый аргументом 3 (порядок порядок оценки фактических параметров не определен): printf("%d\n", ++x, x + 1) Код имеет неопределенное поведение. Порядок оценки параметров функции или подвыражений не определен, поэтому если значение используется и изменяется в различных местах, не разделенных точкой последовательности, ограничивающей порядок оценки порядок, то результат выражения будет неопределенным.

Как было сказано ранее, неопределенное поведение влияет только на оценку (x+1), а не на все выражение или другие его выражения. Поэтому в случае "неопределенного поведения" мы можем сказать, что на выходе получается 2, и никто не сможет возразить.

Но это не неопределенное поведение, это, похоже, "неопределенное поведение". И "неопределенное поведение", похоже, должно быть чем-то, что влияет на все высказывание, а не на отдельное выражение. Это связано с неясностью того, где на самом деле происходит "неопределенное поведение" (т.е. что именно влияет).

Если бы существовали мотивы присоединить "неопределенное поведение" только к выражению (x+1), как в случае "неопределенного поведения", то мы все равно могли бы сказать, что выход всегда (100%) 2. Присоединение "неопределенного поведения" только к (x+1) означает, что мы не можем сказать, будет ли это 1+1 или 2+1; это просто "что угодно". Но опять же, это "что угодно" отпадает из-за printf, и это означает, что ответ будет "всегда (100%) 2".

Вместо этого, из-за непонятной асимметрии, "неопределенное поведение" не может быть прикреплено только к x+1, но действительно должно влиять по крайней мере на ++x (который, кстати, и отвечает за неопределенное поведение), если не на все высказывание. Если он заражает только выражение ++x, то на выходе получается "неопределенное значение", то есть любое целое число, например, -5847834 или 9032. Если он заражает все выражение, то вы можете увидеть gargabe в выводе консоли, скорее всего, вам придется остановить программу с помощью ctrl-c, возможно, до того, как она начнет рубить ваш процессор.

Согласно городской легенде, "неопределенное поведение" заражает не только всю программу, но и ваш компьютер и законы физики, так что таинственные существа могут быть созданы вашей программой и улететь или съесть вас.

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

-1
ответ дан 27 November 2019 в 06:59
поделиться

Большинство студентов отметили неопределенное поведение. Может ли кто-нибудь помочь мне понять, почему это так?

Потому что порядок, в котором вычисляются параметры функции, не указан.

2
ответ дан 27 November 2019 в 06:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: