Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CihatAltiparmak/902b19b435cc85975cbe8100e50c5c9b to your computer and use it in GitHub Desktop.
Save CihatAltiparmak/902b19b435cc85975cbe8100e50c5c9b to your computer and use it in GitHub Desktop.

#Uyarı Bu yazı, bu konu hakkında pek bir bilgisi olmayan bir öğrenci tarafından yazılmıştır. Bu yüzden anlatılanlardan bazıları doğru değildir. Umarım bunu bir ara düzeltebilirim. Ben sadece anladığım şeyleri anlatmaya çalıştım.

Merhaba arkadaşlar,

Bugün sizlerle

int a = 10;
if (a == --a)
    printf("deneme\n");

ifadesinin neden Undefined Behaviour olduğunu tartışacağız.

Öncelikle aşağıya kodumuzu yazalım.

deneme1.c

#include <stdio.h>

int main()
{
    int a = 10;
    if(a == --a)
        printf("deneme\n");
        
    return 0;
}

Şimdi de c kodumuzu aşağıdaki komutla derleyelim.

gcc -std=c99 -Wall -Werror deneme1.c -o deneme1 

O da ne, derleyici bize şöyle bir uyarı verecek.

deneme1.c: 'main' işlevinde:
deneme1.c:6:13: hata: 'a' ifadesinde işlem tanımsız olabilir [-Werror=sequence-point]
    6 |     if(a == --a)
      |             ^~~
cc1: all warnings being treated as errors

Dikkatinizi şu noktaya çekmek istiyorum. Hata mesajında dikkat ederseniz [-Werror=sequence-point] diye bir ifade geçiyor. Bu bir kenarda dursun.

Önce şu linke bakın, olayı anladıysan benim yazdıklarımı okumana gerek yok, çünkü ben olayı bu link sayesinde anladım ve anlatımımı bunu baz alarak yapmaya çalıştım.

Şimdi sıkı durun, kemerleri bağlayın.

Şu üç kavramın ne olduğunu bilmemiz lazım meseleyi anlamamız için:

  • full expressions
  • side effects
  • sequence point

Full Expressions

Expression nedir hiçbir fikrin yoksa lütfen şuraya bir göz at, sonra okumaya devam et. Şimdi full expression ne demek bunu bir inceleyelim. Şurada bir açıklama var ama pek anlaşımıyor gibi. O zaman bir de şuraya bir bakın. Ne yazık ki full expression'un tanımını yapamayacağım ama şöyle bir liste oluşturabiliriz.(liste eksik olabilir.)

  • Any full statement ended with semicolon like a = b;
  • return statements
  • The controlling expressions of if, switch, while, or do-while statements.
  • All three expressions in a for statement.

Şimdi bu maddelere aşağıdski resimde örnek verdim. Fosforlu kalemle çizdiğim yerler full expression dır.

resim1

side effects

Wikipedia'da şöyle bir ifade var.

In computer science, an operation, function or expression is said to have a side effect if it modifies some state variable value(s) outside its local environment

Lütfen ama lütfen şunu da okuyun. Özellikle önce en son cevabı okuyun, daha sonra ise çözümü okuyun.

Şimdi geldik en son noktaya.

Sequence Point

Merak etmeyin, korkmayın, önce size şurada geçen tanımı vereceğim, sonra da örneklerle açıklayacağım.

A sequence point is a point in time at which the dust has settled and all side effects which have been seen so far are guaranteed to be complete. The sequence points listed in the C standard are: 

* at the end of the evaluation of a full expression (a full expression is an expression statement, or any other expression which is not a subexpression within any larger expression);
* at the ||, &&, ?:, and comma operators; and
* at a function call (after the evaluation of all the arguments, and just before the actual call). 

İlk maddeyi ve 3. maddeyi anlayamadım ama 2. madde ile ilgili örnekler vereceğim. Aşağıdaki resimde örnekleri paylaştım.

resim2

Şimdi son noktayı koyuyoruz. C Standartları ne diyor bir kulak verelim:

The Standard states that

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. 

Mihenk taşları yerine oturacak şimdi. C Standard diyor ki: iki tane sequence point arasında bir değişkenin değerini en fazla bir kez değiştirebilirsin. Evet şimdi hemen örnek yapıyoruz ve bu işe son noktayı koyuyoruz.

Bir de şu cümle var.

A sequence point is a point in time at which the dust has settled and all side effects which have been seen so far are guaranteed to be complete.
// PROGRAM 1
#include <stdio.h>
int f1() { printf ("Geeks"); return 1;}
int f2() { printf ("forGeeks"); return 1;}
int main() 
{ 
  int p = f1() + f2();  
  return 0; 
}

Bu kod Undefined Behaviour'dur. Çünkü derleyici GeeksforGeeks de bastırabilir, forGeeksGeeks de bastırabilir. Bunun nedeni şu, hatırlıyor musunuz hangi operatörler sequence pointti?

Hemen hatırlatıyorum: && || , ?:

Peki int p = f1() + f2(); de + işareti sequence pointer mı, hayır. Öyleyse C standardı önce f1 in, sonra f2 nin çalışacağını garanti ediyor mu, hayır.

İşte bunu derleyicinin istifadesine bırakıyor. kimi derleyici f1 i önce çalıştırırken kimi derleyici de f2 yi önce çalıştırır, bu da Undefined Behaviour'dur.

// PROGRAM 1
#include <stdio.h>
int f1() { printf ("Geeks"); return 1;}
int f2() { printf ("forGeeks"); return 1;}
int main() 
{ 
  int p = f1() && f2();  
  return 0; 
}

Burada Undefined Behaviour yok. Çünkü && bir sequence point. Yani

expression1 && && expression2 && expression3

de önce expression1 çalışır, sonra expressipn2 çalışır en son expression3 çalışır.

Şimdi gelelim asıl meselemize

#include <stdio.h>

int main()
{
    int a = 10;
    if(a == --a)
        printf("deneme\n");
        
    return 0;
}

Undefined behaviour'dur. Çünkü ==, C standartlarında tanımlı bir sequence point değil. Bu yüzden önce ++a expressionunun mu çalışacağını, yoksa `a expressionunun mu çalışacağı derleyiciden derleyiciye göre değişir.

Kısaca özetlemek gerekirse:

  1. a önce, ++a sonra çalışırsa: if(10 == 11) olur ve if çalışmaz, bu yüzden deneme yazısı bastırmaz.

  2. ++a önce, a sonra çalışırsa: if(11 == 11) olur ve if çalışır, bu yüzden deneme yazısı bastırılır.

Görüldüğü üzere bu da derleyiciden derleyiciye göre değişiyor.

Lütfen aşağıdaki linki okumadan geçmeyin, üstte de yazdığım gibi, yazımı buna göre temellendirdim. link

Anladığım kadarıyla anlatmaya çalıştım, biliyorum çok eksiğim var. Eğer yanlış bir ifadem varsa lütfen ama lütfen bana belirtin bunu.

Hayırlı günler arkadaşlar, sağlıcakla kalın.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment