Polito Python’dan C’ye Geçiş: Değer, Adres ve Fonksiyon

Polito Python’dan C’ye geçişi aynı problemle çalışın: nesne paylaşımı, değer ve adres, fonksiyon parametreleri, array sınırları ve bellek yönetimi.

📅Yayın:
Harun BüyükçolakHarun Büyükçolak, Full Stack Developer
Polito Python’dan C’ye Geçiş: Değer, Adres ve Fonksiyon

Yazı içeriği

Python'da bir problemi çözebildiğiniz hâlde C'de aynı fonksiyonu yazarken takılıyorsanız, bütün programlamayı yeniden öğrenmeniz gerekmiyor. Döngü, koşul ve problem parçalama becerileri taşınır; verinin nerede tutulduğu, fonksiyonun neyi değiştirdiği ve erişimin ne zaman geçerli olduğu ise yeniden düşünülmelidir. Polito C / Programming Techniques hazırlığında bu ayrımı küçük bir problem üzerinde görmek, uzun bir pointer listesini ezberlemekten daha kullanışlıdır.

Bu yazıda negatif ölçümleri sıfıra çeviren aynı görevi Python ve C ile çözeceğiz. Ardından paylaşılan listeyi, kopyalanan parametreyi, adresi ve yaşam süresini ayıracağız. Örnekler Websoftik Academy'nin özgün alıştırmalarıdır; resmî sınav soruları veya öğrencinin yerine hazırlanmış teslimler değildir.

Bu geçiş, her Polito öğrencisinin aynı sırayla Python ve C dersi aldığı anlamına gelmez. Kendi programınızı, tam ders kodunuzu ve akademik yılınızı Polito Python ders rehberi ve Programming Techniques 2026/27 rehberi üzerinden doğrulayın. Buradaki odak müfredat takvimi değil, iki dil arasındaki düşünme farkıdır.

1. Önce problemi ve veri sözleşmesini yazın

Elimizde bir dizi tam sayı ölçüm olsun. Negatif değerler hatalı ölçüm kabul ediliyor: onları 0 yapacağız, diğerlerini koruyacağız ve değiştirilen eleman sayısını döndüreceğiz. Örneğin 6, -2, 0, -5 girdisi işlem sonunda 6, 0, 0, 0 olacak; dönüş değeri 2 olacak. Baştan sıfır olan eleman değiştirilmiş sayılmayacak.

Fonksiyon yeni bir koleksiyon üretmeyecek; çağıranın verdiği veriyi yerinde değiştirecek. Bu karar, çıktı kadar önemlidir. Sonucun doğru görünmesi fakat eski verinin korunması, başka bir sözleşmenin doğru uygulanması olur. Boş girdinin sonucu da açık: değiştirilen eleman sayısı sıfırdır ve hiçbir elemana erişilmez.

Karşılaştırmayı küçük bir ortak alanda yapacağız: en fazla 1000 eleman ve -10000 ile 10000 arasındaki tam sayılar. Python'un tam sayılarıyla C'nin int türünü bütün değerlerde eşdeğer kabul etmiyoruz. Verilen aralık C'nin standartta güvence altına alınan asgari int aralığına sığar; örneğimizde toplama veya çarpma da yoktur. Fonksiyonlara bu koşulları sağlayan girdi verildiğini varsayacağız.

2. Python çözümünde ne değişiyor?

measurements.pyPython
def sanitize_measurements(values):    changed = 0    for i in range(len(values)):        if values[i] < 0:            values[i] = 0            changed += 1    return changedmeasurements = [6, -2, 0, -5]changed = sanitize_measurements(measurements)print(measurements, changed)# [6, 0, 0, 0] 2

Döngü başında changed, daha önce incelenen elemanlar içindeki negatif değer sayısını tutar. Her adımda bir eleman kontrol edilir; negatifse o indeksin bağlı olduğu değer sıfırla değiştirilir. Fonksiyon sona erdiğinde liste nesnesi hâlâ vardır ve değişiklik çağıranın kullandığı listeden görünür.

Burada values[i] = 0, listenin bir elemanını değiştirir. changed += 1 ise yerel sayacın adını yeni bir tam sayı sonucuna bağlar. İki satırın sözdizimi benzer görünse de aynı nesne etkisini üretmez. Fonksiyonun dönüş değeri liste değil, değişiklik sayısıdır.

Önce programı çalıştırmadan her indeks sonrasındaki listeyi ve sayacı yazın. Ardından koşulu values[i] <= 0 olarak düşünün: sıfır değer hâlâ sıfır kalmasına rağmen sayaca eklenir. Çıktı listesinin değişmemesi, sözleşmenin korunmuş olduğunu tek başına göstermez; dönüş değeri de test edilmelidir.

3. Paylaşılan nesne ile yeniden bağlamayı ayırın

names_and_objects.pyPython
def change_then_rebind(values):    values[0] = 99    values = [0]    return valuesmeasurements = [6, -2]alias = measurementsresult = change_then_rebind(measurements)print(measurements, alias, result)# [99, -2] [99, -2] [0]

Çağrı sırasında yerel values adı, measurements ve alias ile aynı liste nesnesine bağlanır. İlk atama bu ortak nesnenin içeriğini değiştirir. İkinci atama yeni bir liste oluşturup yalnız yerel adı ona bağlar; çağıranın adlarını yeni listeye yönlendirmez. Sonuçta iki ayrı liste vardır.

Python'u açıklamak için “her şey referansla geçer” demek bu ayrımı gizleyebilir. Fonksiyon çağıranın değişken adını değil, verilen nesneye erişimi paylaşır; nesneyi değiştirmekle parametre adını yeniden bağlamak farklıdır. Tam sayı ve string gibi değiştirilemeyen nesnelerde içerik güncellemesi yapamazsınız; yeni sonucu bir ada bağlarsınız.

Şimdi çağıranda measurements = result yazıldığını düşünün. alias eski listeye bağlı kalır. İki adı tek kutuya değil, iki ayrı okla ortak bir nesneye çizmek bu davranışı açıklamayı kolaylaştırır. Bu çizim, C'de adres kopyalarını izlerken de yararlı olacaktır; iki dilin kurallarını aynı kabul etmeden benzer soruları sorabilirsiniz.

4. Aynı problemi C ile uygulayın

measurements.cC
#include <stddef.h>#include <stdio.h>size_t sanitize_measurements(int values[], size_t n){    size_t changed = 0;    for (size_t i = 0; i < n; ++i) {        if (values[i] < 0) {            values[i] = 0;            ++changed;        }    }    return changed;}int main(void){    int measurements[] = {6, -2, 0, -5};    size_t n = sizeof measurements / sizeof measurements[0];    size_t changed = sanitize_measurements(measurements, n);    printf("%d %d %d %d | %zu\n",           measurements[0], measurements[1],           measurements[2], measurements[3], changed);    return 0;}/* Çıktı: 6 0 0 0 | 2 */

Algoritma aynı; veri sözleşmesi artık daha açık taşınıyor. Fonksiyon ilk n elemana yazabilir. n > 0 olduğunda values, en az o kadar geçerli ve yazılabilir int elemanına erişim sağlamalıdır. Daha küçük bir diziyi büyük uzunlukla vermek, bu fonksiyonun kontrol ettiği bir giriş hatası değildir; sözleşme ihlalidir.

size_t, nesne boyutları ve eleman sayıları için kullanılan işaretsiz türdür. %zu bu dönüş değerini yazdırır. n = 0 için döngü çalışmaz; bu özel sözleşmede NULL ile sıfır uzunluk verilebilir. Bu izin, bütün C fonksiyonlarının null pointer kabul ettiği anlamına gelmez.

Python çıktısı ile C çıktısını yalnız görünüm olarak değil, kalan veri ve dönüş sayısı olarak karşılaştırın. Ortak girdi alanında aynı sonucu üretmeleri gerekir. Python'un int değerleri kullanılabilir bellekle sınırlı büyüyebilir; C'de işaretli int aritmetiğinde sonuç türün aralığını aşarsa davranış tanımsızdır. Bu durum, işaretsiz türlerin modüler aritmetiğiyle aynı değildir. Büyük sayıları toplamak gibi yeni bir işlem eklediğinizde taşma koşullarını ayrıca tasarlayın; örneğimizin eşdeğerliği başka işlemlere otomatik taşınmaz.

5. C parametreleri daima değer olarak geçer

parameters.cC
#include <stddef.h>#include <stdio.h>int reset_copy(int value){    value = 0;    return value;}void reset_target(int *target){    if (target != NULL) {        *target = 0;    }    target = NULL;}int main(void){    int measurement = -2;    int *route = &measurement;    reset_copy(measurement);    printf("%d\n", measurement);  /* -2 */    reset_target(route);    printf("%d %d\n", measurement, route == &measurement); /* 0 1 */    return 0;}

reset_copy, tam sayının kopyasını değiştirir. Dönüş değerini kullanmadığımız için çağıranın measurement nesnesi değişmez. Çağıranda measurement = reset_copy(measurement) yazarsanız sonucu açıkça saklamış olursunuz. Fonksiyonun dönüşü ile çağıranın ataması iki ayrı adımdır.

reset_target ise bir pointer değerinin kopyasını alır. Parametre ve route, aynı geçerli nesneyi gösterir. *target = 0 o nesneye yazar; target = NULL yalnız yerel pointer kopyasını değiştirir. Bu nedenle dışarıdaki route hâlâ ölçümün adresini taşır. Pointer vermek, C'nin değerle parametre geçirme kuralını değiştirmez.

Çiziminizde ölçüm nesnesini, çağıranın pointer nesnesini ve fonksiyonun pointer parametresini ayrı tutun. Çağıranın pointer'ını değiştirmek gerekiyorsa yeni pointer'ı döndürüp çağıranda atamak veya uygun bir pointer-to-pointer arayüzü kurmak gerekir. İlk çözümünüzde bu ihtiyacı, işaret edilen tam sayıyı değiştirmekle karıştırmayın.

6. Array, pointer ve uzunluk aynı bilgi değildir

C'de array ile pointer aynı nesne veya aynı tür değildir. Yukarıdaki measurements gerçek bir dizidir. Birçok ifadede ilk elemana pointer'a dönüşür. Fonksiyon parametresindeki int values[] bildirimi ise int *values biçimine ayarlanır; dizinin eleman sayısı bu parametrede saklanmaz.

Bu yüzden sizeof measurements / sizeof measurements[0] hesabını gerçek dizinin tanımlandığı main içinde yaptık. Aynı hesabı fonksiyondaki values için kullanmak uzunluğu vermez: pointer'ın boyutunu elemanın boyutuna bölmüş olursunuz. Dışarıdan gelen pointer için de “uzunluk bulma” yöntemi değildir.

Uzunluk sözleşmesinde iki soru vardır: kapasite ne kadar, hangi bölüm bu görevde kullanılacak? Beş elemanlık bir dizinin yalnız ilk üçünü işlemek mümkündür. Fonksiyonun n parametresi kullanılan bölümün sınırını belirtir. Pointer'ın null olmaması, beş elemanın da erişilebilir olduğunu kanıtlamaz. Her erişimden önce doğru nesne ve doğru aralık düşünülmelidir.

7. Python string ile C string sözleşmesini karıştırmayın

Python'da string uzunluğunu len ile alır, indeks dışına çıktığınızda bir istisnayla karşılaşırsınız. C string ise geçerli bir karakter dizisinde sonlandırıcı sıfır karakterine kadar uzanır. char label[] = "Lab"; dört eleman içerir: üç görünen karakter ve \0. Görünen uzunlukla ayrılmış kapasiteyi aynı sayı sanmayın.

Yalnız L, a ve b karakterlerinden oluşan üç elemanlık bir dizi, sonlandırıcısı olmadığı için C string değildir. Böyle bir tamponu sonlandırılmış string bekleyen fonksiyona vermek güvenli olmaz. strlen da keyfî bir tamponun güvenli boyutunu bulmaz; erişilebilir bir sonlandırılmış string ister.

Özgün bir alıştırma yapın: en fazla üç karakterlik etiketi saklayacak tamponun kapasitesini hesaplayın. Sonlandırıcı için de yer bırakın; dört karakterlik girdiyi nasıl reddedeceğinizi yazın. Boş etiketin ilk elemanı ne olmalı? Girdi taşmasını, dizinin sonuna geldikten sonra değil, kopyalamadan önce engelleyin. Bu bölümde ASCII örnekleri kullanıyoruz; Python karakter sayısı ile UTF-8 byte sayısını eşitlemiyoruz.

8. Ownership, yaşam süresi ve NULL için ayrı sorular sorun

Ölçüm örneğinde fonksiyon belleğin sahibi değildir: çağıranın dizisini geçici olarak kullanır, ayırma veya serbest bırakma yapmaz. Bu basit sözleşmeyi korumak faydalıdır. Yerel bir dizinin adresini fonksiyondan döndürmek ise başka bir durumdur; ilgili otomatik nesnenin yaşam süresi bittiğinde o adres üzerinden erişim geçerli kalmaz.

Dinamik bellek eklemeden önce üç soruyu yanıtlayın: alanı kim ayırıyor, kim kullanıyor, kim tam bir kez serbest bırakıyor? malloc başarısızlığını kontrol etmek gerekir. Başarılı olması da içeriğin sizin için başlatıldığı anlamına gelmez. Her elemanı okumadan önce uygun bir değerle başlatın ve kapasiteyi saklayın.

free sonrasında eski nesneye erişmeyin. Bir pointer'ı NULL yapmak, aynı adresi taşıyan başka pointer'ları geçerli hâle getirmez veya otomatik değiştirmez. Null olmayan bir değer, geçerli nesne ve yaşam süresi kanıtı değildir. Başlatılmamış pointer'ı null kontrolü için bile okumayın; önce uygun bir geçerli adres veya NULL atayın. Null kontrolü, sahiplik ve sınır denetiminin yerine geçen genel bir güvenlik testi değildir.

9. Aynı görevi üç küçük değişiklikle sınayın

İlk testi örnek girdiye sınırlamayın. Boş veri için sıfır değişiklik; yalnız pozitif ve sıfır değerler için sıfır değişiklik; yalnız negatif değerler için bütün elemanların değişmesi beklenir. Sıfırı ve eksi biri aynı küçük testte kullanmak koşulun sınırını özellikle görünür kılar.

  1. Kısmi işlem: beş elemanın yalnız ilk üçünü temizleyin. Son iki elemanın korunmasını da doğrulayın. Python arayüzünü bu görev için nasıl değiştireceğinizi önce yazın.
  2. Yeni çıktı: girdiyi değiştirmeden temizlenmiş bir kopya üretin. Python'da yeni listeyi; C'de çağıranın sağladığı çıktı tamponunu ve kapasitesini açıkça tanımlayın.
  3. Genelleme: negatifleri sıfırlamak yerine alt sınırın altındakileri verilen alt sınıra yükseltin. Eşit değerlerin sayılmayacağı kuralını ve kullanılabilir sayı aralığını koruyun.

C örneğini kendi dosyanızda, C17 modunda uyarıları açık derleyin: cc -std=c17 -Wall -Wextra -Wpedantic measurements.c -o measurements. Ortamınız destekliyorsa adres ve tanımsız davranış denetleyicilerini de kullanabilirsiniz. Derleme veya denetleyici başarısı bütün olası girdilerin doğruluğunu ispatlamaz; beklenen veriyi ve dönüş değerini ayrıca karşılaştırın.

Python ile C testlerinin çıktısını yan yana tutun. Hata olduğunda önce sözleşmeyi, sonra döngü aralığını, ardından hangi nesnenin değiştiğini kontrol edin. Her düzeltmeden sonra eski testleri de yeniden çalıştırın; yeni bir örneği düzeltirken önceki davranışı bozmadığınızı görün.

10. Academy Lab'i bağımsız kod pratiğiyle tamamlayın

Python/C Programming Skills Diagnostic, başlangıçtaki kod okuma ve üretim eksiklerini ayırmanıza yardımcı olabilir. Sonucu bir geçme tahmini olarak kullanmayın; kendi ölçüm probleminizdeki hatayla birlikte yorumlayın. Python'da döngü açıklaması zaten zayıfsa pointer'a geçmeden o beceriyi güçlendirin.

Pointers & Memory Lab rehberinden değer, adres ve yaşam süresini izleme çalışmalarına geçebilirsiniz. Önce hangi nesnenin değişeceğini tahmin edin, sonra trace ile karşılaştırın. Lab'deki hazırlanmış senaryoyu anlamak, bu yazıdaki her C programının o araçta çalıştırılabildiği anlamına gelmez. Kendi örneklerinizi bağımsız derleyici ve kendi testlerinizle de doğrulayın.

İki dilde aynı sözleşmeyi açıklayabiliyor fakat adres veya veri modeli kararlarında düzenli takılıyorsanız, ders kodunuz ve hata kaydınızla Polito C / Programming Techniques birebir çalışma sürecini inceleyebilirsiniz. Amaç öğrencinin kendi çözümünü üretip savunabilmesidir; değerlendirilecek ödev veya sınav öğrenci yerine yapılmaz. Polito'daki diğer kaynaklar üniversite merkezinde yer alır.

Dil davranışını kontrol etmek için birincil kaynaklar

Websoftik Academy, Politecnico di Torino'dan bağımsızdır. Bu özgün çalışma rehberi resmî ders duyurusu, değerlendirme ölçütü veya başarı garantisi değildir. Kullanılan veri alanını, fonksiyon sözleşmesini ve bellek yaşam süresini açıklayabilmek, çalışmanın temel çıktısıdır.

Sonraki Adım: Bunları da Oku

Bu yazıyı tamamladıysan, bir sonraki seviyeye geçmek için şu içeriklerle devam etmeni öneririz:

Ders kodunuza göre çalışma planı

Müfredatınızı, sınav tarihinizi ve zorlandığınız bir soruyu birlikte inceleyerek birebir ders ve Lab pratiği için uygun sırayı belirleyebiliriz.

Polito Programming Techniques (C) özel ders planı →

Hedefe Uygun Ders Planını Netleştirelim

Sınav, proje ve ders hedefinize göre haftalık çalışma planı ile kontrollü ilerleyelim.

WhatsApp