LINUX.ORG.RU

это UB?

 


0

0
#include<stdio.h>
int b=0;
void f(a){
  printf("a is %d , b is %d\n",a,b);
}
void main(void){
   f(b++);
}

постинкримент завершается
1.до вызова f 2. после завершения f ?

★★☆
Ответ на: комментарий от theNamelessOne

т.е компилятор тут эталонно повторяет стандарт?

qulinxao ★★☆ ()
Ответ на: комментарий от theNamelessOne

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

Что мы получим в данном примере:

  1. Вычисляется постфиксный инкремент, его значение становится фактическим значением формального аргумента a функции, при этом качестве побочного эффекта операции инкремента увеличивается значение переменной b
  2. Происходит вызов функции, печать, etc.
theNamelessOne ★★★★★ ()
Ответ на: комментарий от qulinxao

стандартом это как обосновывается?

Да прочти ж ты хоть что-нибудь, школота!

anonymous ()

Нет тут никакого UB, все строго.

andreyu ★★★★★ ()
Ответ на: комментарий от netcat

постинкримент завершается
1.до вызова f 2. после завершения f ?

После завершения f()

Вызов функции — это точка следования, которая гарантирует, что перед входом в функцию побочные эффекты, проявившиеся при вычислении ее аргументов, будут завершены. Так что постинкремент завершится до входа в функцию.

theNamelessOne ★★★★★ ()
Последнее исправление: theNamelessOne (всего исправлений: 2)

Автор прочитал тред про ++i + ++i и теперь думает, что везде, где используется инкремент, будет UB. Логичненько

amphibrakhij ()

Это UR.
ГК, если в правильной раскладке.

thesis ★★★★★ ()
Ответ на: комментарий от amphibrakhij

ещё 7 вариантов (*(оp({pre++,post++,e})с))(*(оp({pre++,post++,e})с))

ха ха

#include<stdio.h>
typedef void ff(void*);
ff* b[2];
ff** c;
void f(ff a){
	printf("f cmp is %d\n",f==a);
}
void g(ff a){
	printf("g cmp is %d\n",g==a);
}
void main(void){
	b[0]=f;b[1]=g;

	c=b;
	f(*c);
	g(*c);
	
	c=b;
	(*c)(*c++);

	printf("%d %d %d %d\n",f,b[0],g,b[1]);

	c=b;
	(*++c)(*c);
}

вот стою я в лыжи обутый.

qulinxao ★★☆ ()

Если что, то 1. По стандарту указатели на функции особенные. К void* и обратно можно безопасно кастовать только указатели на объекты, коими функции не являются. 2. Порядок вычисления аргументов и самой вызываемой фунции не определён. 3. main() возвращает void.

ilammy ★★★ ()
Ответ на: комментарий от ilammy

(если void main() то там обязано в конце быть return 0 - это какбе компилер «гарантирует» ) вроде.

т.е всё таки неопределён порядок вычисления между самой функции и её аргрументов . хм. ... хм... ага!!!

qulinxao ★★☆ ()

Постинкремент возвращает в выражение старое значение. А в следующем выражении будет использовано новое. На то он и «пост».

Xellos ★★★★★ ()
Ответ на: комментарий от qulinxao

(если void main() то там обязано в конце быть return 0 - это какбе компилер «гарантирует» ) вроде.

Не вроде, а 5.1.2.2.1/1:

The function called at program startup is named main. <...> It shall be defined with a return type of int and with no parameters <...> or with two parameters <...> or equivalent; or in some other implementation-defined manner.

и 5.1.2.2.3/1:

If the return type of the main function is a type compatible with int <...> reaching the } that terminates the main function returns a value of 0. If the return type is not compatible with int, the termination status returned to the host environment is unspecified.

ilammy ★★★ ()

Этот даун в рубашке уже реально запарил. Иди стандарт скачай, полено.

anonymous ()

нет, вернёт 0 и 1. Аргументы вычисляются _перед_ вызовом функции. Это даже не стандарт, а К.О.

ЗЫЖ вопрос глупый, можно было-бы и самому подумать, о том, КАК реализовать что-то другое? Временную переменную для реализации UB вводить что-ли? C писался не для развлечений.

drBatty ★★ ()
Ответ на: комментарий от qulinxao

(если void main() то там обязано в конце быть return 0 - это какбе компилер «гарантирует» ) вроде.

ЩИТО? откуда ты вообще взял void main()? В UNIX _любая_ программа возвращает код возврата от 0 до 127, или 128..255 если её прервали.

drBatty ★★ ()
Ответ на: комментарий от qulinxao

т.е всё таки неопределён порядок вычисления между самой функции и её аргрументов

facepalm

как можно вызвать функцию, не вычислив её аргументы???

drBatty ★★ ()
Ответ на: комментарий от drBatty

как можно вызвать функцию, не вычислив её аргументы???

google://нормальный порядок редукции

google://ленивые вычисления

ilammy ★★★ ()
Ответ на: комментарий от drBatty

Но вообще здесь под «вычислением функции» подразумевается не вычисление возвращаемого значения, а вычисление того, что вызывается. Указатель на функцию же надо разыменовать перед тем, как вызывать функцию — вот это и есть те самые вычисления.

ilammy ★★★ ()
Ответ на: комментарий от ilammy

как можно вызвать функцию, не вычислив её аргументы???

ленивые вычисления

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

Т.е. _выражение_ X || Y считается вычисленным, даже если X истинно, и Y никто не вычислял. Ибо _аргументом функции_ Y НЕ является. Аргумент это X||Y.

drBatty ★★ ()
Ответ на: комментарий от ilammy

Но вообще здесь под «вычислением функции» подразумевается не вычисление возвращаемого значения, а вычисление того, что вызывается. Указатель на функцию же надо разыменовать перед тем, как вызывать функцию — вот это и есть те самые вычисления.

указатель на функцию можно считать одним из аргументов. Он вычисляется ДО вызова функции. Т.е. есть чёткая граница:

  • сначала вычисляются аргументы, в т.ч. адрес самой функции. Порядок тут не определён. Аргументы и адрес раскладывается в памяти(регистрах) (например в стековом фрейме).
  • потом функция вызывается. Т.е. самый последний «аргумент», адрес возврата, заносится в стековый фрейм, и управление передаётся на адрес функции(он к этому моменту уже вычислен). Во многих CPU одной командой.
drBatty ★★ ()
Ответ на: комментарий от drBatty

как можно вызвать функцию, не вычислив её аргументы???

int foo(int bar){
    return 10;
}

....
smth=foo(a+b)

здесь допускать вычисление a+b (==аргумента функции) емнип будут вычислять далеко не все компиляторы, а то и вообще выкинут к чертям всю функцию, оставив только 10.

arkhnchul ★★ ()
Ответ на: комментарий от arkhnchul

здесь допускать вычисление a+b (==аргумента функции) емнип будут вычислять далеко не все компиляторы, а то и вообще выкинут к чертям всю функцию, оставив только 10.

как можно попасть в Америку, не переплыв(не перелетев) океан? Да элементарно! Мы не поедем в Америку!

drBatty ★★ ()
Ответ на: комментарий от arkhnchul

выкинут к чертям всю функцию, оставив только 10.

gcc ессно так и делает с -O3 а с -O0 сначала складывает, а потом передаёт аргументы.

drBatty ★★ ()
Ответ на: комментарий от qulinxao

кто вызовится? f? g? старая функция *с?

как я уже выше говорил, указатель можно считать в данном контексте аргументом. В силу того, что порядок вычисления аргументов не определён, в _этом_ случае имеем неопределённость, потому-что мы не знаем, какой аргумент будет вычислен первым.

Во всяком случае в x86, указатель на функцию транслируется в call eax(обычно), т.е. eax это один из аргументов, который будет считаться так, как оно удобнее компилятору.

drBatty ★★ ()
Ответ на: комментарий от drBatty

подповерхностная фантастика менее фантастична чем чрезцентрземли.

то биш для прихода по «подземелью» достаточно прохождение на глубине 1-2 км от поверхности земли (не уровня моря) - т.е от поверхности дна.

такое устройство по факту

1. медленное. 2. по потреблямой мощьности требования выше атомного_ледокола/авиацосца - так что ограничение отсутствие компактного «котла» достаточной мощьности - ситуация анологичная появлению самолётов до появления двг.

qulinxao ★★☆ ()
Ответ на: комментарий от qulinxao

а ещё код C можно транслировать в код VM от Java, и выполнять его сразу на Over9000 компьютерах одновременно. Тогда да, 7512 компьютеров будут считать сумму, а 2170 дадут ответ 10.

drBatty ★★ ()
Ответ на: комментарий от drBatty

7512 компьютеров будут считать сумму, а 2170 дадут ответ 10.

там несколько другое соотношение будет) явовский компилятор и/или рантайм зайинлайнят 10 сходу.

arkhnchul ★★ ()
Ответ на: комментарий от arkhnchul

там несколько другое соотношение будет) явовский компилятор и/или рантайм зайинлайнят 10 сходу.

дык мне предлагают иной путь:

то биш для прихода по «подземелью» достаточно прохождение на глубине 1-2 км от поверхности земли (не уровня моря) - т.е от поверхности дна.

С такими проектами, 10 дадут ровно 2170, из Over9000.

drBatty ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.