2017-01-21 3 views
1
//prog1.c  
#include <stdio.h> 
    int f(int *a,int *b,int c) { 
     if(c == 0) return 1; 
     else { 
     *a = *a + 1; 
     *b = *b - 1; 
     c = c - 1; 
     return (*a + f(a,b,c) + *b); 
     } 
    } 
    int main() { 
     int a = 3,b = 3,c = 3; 
     printf("%d\n",f(&a,&b,c)); 
     return 0; 
    } 

Я выполнил программу с помощью gcc и clang-3.5 и нашел выход = 16.Оценка в обратном заявлении

Я думаю, что может быть каким-то конкретная реализацией поведение, как происходит некорректно код

//prog2.c 
#include <stdio.h> 
int f(int *x,int *y,int *z) { 
    *x = *x + 1; 
    *y = *y + 1; 
    *z = *z + 1; 
    return 0; 
} 
int main() { 
    int a=0,b=0,c=0; 
    printf("%d %d %d\n",a,f(&a,&b,&c),b);; 
    return 0; 
} 
// gcc output : 1 0 0 
// clang-3.5 : 0 0 1 

В prog1.c есть какое-либо конкретная реализация поведение в return заявления? Если нет, то как это оценивается?

Возможно, я не знаю какого-либо undefined behaviour или unspecified behaviour. Пожалуйста, объясни. Thanks

+1

См. Также [Является ли это неопределенным поведением в C? Если нет, прогнозируйте вывод логически.] (Http://stackoverflow.com/questions/41775973) и (если вы пользователь 10K) [Как работает данный код C?] (Http://stackoverflow.com/ вопросы/41775508/how-the-given-c-code-works) - теперь удалены. –

+1

Обе программы зависят от порядка, в котором термины выражений оцениваются, и этот порядок не санкционирован стандартом C. Во втором примере допустимы результаты как от GCC, так и от Clang; их даже довольно легко объяснить. Но вы не можете рассчитывать на получение результата - или даже на получение одного из двух результатов (возможны и другие результаты). –

+1

Вы получили и приняли ошибочные ответы. –

ответ

2

Как отмечалось в комментариях и в ближайшее дубликата вопрос (Is this undefined behaviour in C? If not, predict the output logically.), результаты от обоих этих программы не полностью определены стандартом C - они производят «неуказанное поведение», потому что порядок оценки терминов в заявлении return первого и printf() во втором не указывается языком и по прихоти компилятор. (Обратите внимание, что это «неопределенное поведение», а не «неопределенное поведение», а не формальное «неопределенное поведение» - см. Обсуждение в комментариях. Это не «поведение, определяемое реализацией», но реализация не требуется для документирования того, что он делает.)

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

Первая программа:

#include <stdio.h> 

int f(int *a,int *b,int c) { 
    if(c == 0) return 1; 
    else { 
    *a = *a + 1; 
    *b = *b - 1; 
    c = c - 1; 
    return (*a + f(a,b,c) + *b); 
    } 
} 

int main() { 
    int a = 3,b = 3,c = 3; 
    printf("%d\n",f(&a,&b,c)); 
    return 0; 
} 

Проблематика часть return (*a + f(a,b,c) + *b); потому, что *a может быть оценена до или после того, как вызов рекурсивной функции, и f() изменяет значения, которые a и b точка поэтому порядок оценки вопросы. Различные компиляторы могут законно производить разные результаты. Один и тот же компилятор может производить разные результаты в разное время или под разными флагами оптимизации или по своему выбору. И *a, и *b могут быть оценены перед вызовом, или после вызова, либо либо можно было бы оценить раньше, а другое после - и это просто называет 4 правдоподобных альтернатива.

Вторая программа:

#include <stdio.h> 
int f(int *x,int *y,int *z) { 
    *x = *x + 1; 
    *y = *y + 1; 
    *z = *z + 1; 
    return 0; 
} 
int main() { 
    int a=0,b=0,c=0; 
    printf("%d %d %d\n",a,f(&a,&b,&c),b);; 
    return 0; 
} 

Проблема в том, что последовательность, в которой a, f(&a, &b, &c) и b оцениваются для вызова printf() не определяется стандартом, и вы получите разные результаты в зависимости от последовательность, выбранная компилятором. Вы показали, что GCC и Clang дают разные результаты - оба этих результата приемлемы в соответствии со стандартом, и так много других.

+1

Нет неопределенного поведения, есть точка последовательности до и после вызова функции. Это неуказанное поведение. –

+0

@ M.M - Я буду судить о «неопределенных» против «неуказанных»; Я пересмотрел текст, чтобы избежать «неопределенного поведения». –

+1

Я рекомендую вам убедиться, что он не является неопределенным, а затем обновляет ответ соответственно. Это важный момент, потому что UB может запускать ракеты и т. Д., Тогда как эта программа должна выводить число из (возможно большого) конечного набора возможностей –

0

В prog1.c есть ли какое-либо конкретное поведение в инструкции return? Если нет, то как это оценивается?

Там нет ничего плохого о return заявлении кроме того, что рекурсивный вызов будет бесконечным, если ваш оригинальный вызов f с c отрицателен.

Пока не ясно, цель вашей функции f - но условие терминатор должен быть лучше записать в виде:

if(c <= 0) return 1; 
+1

Вы также можете предложить изменение на 'if (c <= 0) return 1;' –

+0

@ DavidC.Rankin right Я подумал об этом – artm

+0

, цель состояла в том, чтобы проследить «рекурсию» и найти вывод, предполагающий 'f()' завершается с 'c> 0'. спасибо за ответ и разъяснение. @artm – Debashish

Смежные вопросы