C++ Dersleri | Diziler - Dizilerin Başlatılması ( Array Initialization )

    C++ 'da bir dizi, yalnızca belirli bir değişken türü için sıralı şekilde bellekte yer almasını sağlayan veri bloğudur. C++ 'da bir değişkeni tanımlarken geçerli olan tüm kurallar geçerlidir. Ek olarak bir diziden bahsettiğimiz için, bu veri tipinden bellekte kaç adet saklayacağımızı belirtmemiz gerekir. Bunun için değişken ismine köşeli parantez [] içerisine adedi yazarız.
    Aşağıda int değişken tipi için adı arrInts olan ve 3 elemana sahip olduğu söylenen bir tanımlama görüyoruz :
int arrInts[3];
    Bir dizi tanımlanırken eleman değerleri de verilebilir, buna literatürde initialization deniyor, başlatma olarak çevrilmiş, bunun sebebi bir değişkeni sadece tanımlarsanız sadece tanımlamış olursunuz, değerini vermezseniz başlatmış olmazsınız :) ya compiler kafasına göre bir değer verir ya da vermez sadece adresi ve sığasını biliyor olur ve o anda bellekte o adreste ne veri varsa onun veri tipindeki karşılığını görüyor olursunuz, kararsız bir yapıdan bahsediyoruz yani. Tanımlamayı yaparken verileri gireceksek eşittir deyip süslü parantez içerisine elemanların arasına virgül koyarak yapabiliyoruz :

int arrInts[3] = { 1,256,14153 };

Eğer verileri bu şekilde giriyorsak dizi boyutunu belirtmek zorunlu değil, derleyicimiz 3 değer girildiğine göre boyutu da 3 olmalıdır inisiyatifini kullanabiliyor :

int arrInts[] = { 1,256,14153 };


Boyut belirttim ancak eksik veriler girdim :

int arrInts[5] = { 1,256,14153 };
boyutum beş olur, ilk üç elemanım bellidir diğer ikisi muallak, sıfır diyelim mi.
    Dizilerin içindeki elemana erişmek için index değerini kullanırız: bu değer için pozitif tam sayılardır diyebiliriz, 0 dan başlar birer birer artar. Beş elemanlı bir dizinin ilk elemanı sıfırıncı elemandır, son elemanı dördüncü elemandır. Yukarıdaki dizinin sıfır bir ve ikinci elemanlarına değer verilmiş, üçüncü elemanına değer verilmemiştir. Şu şekilde tekil olarak verebiliyoruz :

arrInts[3] = 15;

Dizideki herhangi bir elemana erişmek için değişken adının yanına erişmek istediğimiz elemanın index numarasını bir köşeli paranteze yazmak yeterlidir, Tüm elemanlarını ekrana yazdıralım dersek for ile şunu yazmak yeterli olacaktır :

for (int i = 0; i < 5; i++)
	cout << arrInts[i] << endl;

1
256
14153
15
0

Önceki Konu : C++ Diziler
Sonraki Konu : C++ 2 Boyutlu Diziler

C++ Dersleri | C++ Diziler [ Array ]

    C++ 'da diziler, aynı veri tipine sahip adetli verilerin tek bir değişken ismiyle erişilebilir hale gelmesine olanak tanır. Ne diyebiliriz; ADC 'den veri okuyoruz, saniyede 100 örnek alacağız, her biri için adcVal1, adcVal2 .. adcVal100 diye yüz adet değişken tanımlayıp her birine verimizi kaydedebiliriz, çok pratik olmayacak gibi geldi bana ve de örnekleme sayımız parametrik ise bu yolu kullanmak zaten imkansız oluyor. Bu noktada dizilerden faydalanıyoruz. AdcVals diye bir dizi oluşturup, boyutunu belirtip hafızada bizim için o veri tipinin yüz adedinin sığabileceği bir bellek alanı ayırmasını söylüyoruz, verilerimizi onun içinde saklayıp yine oradan erişebiliyoruz.

  C++ da bir diziyi her değişkende olduğu gibi önce tanımlamak "declare" sonrasında da dilersek başlatmak "initialize" gerekiyor. Sabit değerli diziler için dizi boyutunu da belirtmek gerekiyor ki hafıza organizasyonu işlevi düzgün görevini yerine getirebilsin. Sabit değerli diye bahsettiğimize göre boyutu sonradan belirlenebilen dinamik dizilerin kullanımı da mümkün. Dizilerin ve göstericilerin "pointer" bir araya geldiği aslında her göstericinin aynı zamanda bir dizi olabildiği falan gibi konuları da yazıyor olacağız.


Önceki Konu : Bit Alanları - Gömülü Sistemler Bellek Organizasyonu

Sonraki Konu : C++ Dizilerin Tanımlanması ve Kullanılması

C++ Dersleri | Bit Alanları - Gömülü Sistemler Bellek Organizasyonu

    Gömülü sistemlerde hepimizin bildiği ya da şuanda öğreneceği üzere hafıza alanlarımız (flash - eprom - ram) oldukça kısıtlıdır. Atmega 328p için 2kb ram alanı var desek ve bunun da ancak 2048 tane harfi ram de barındırabileceği anlamına geldiğini söylesek, belki de şu okumakta olduğunuz metini bile ram de saklayamıyor olacağımızı kolayca tahmin edebiliriz. Bazı durumlarda herhangi bir parametrenin sadece açık ya da kapalı olduğunu tutmak istediğimiz bir değişkene ihtiyacımız olur. Ancak en küçük hafıza birimimiz 8 bit (1byte) olduğundan, 1 byte harcamadan 1 bitlik veriyi bir değişken içerisinde saklayabilmek mümkün değildir. Ancak bu bir byte 'ın geri kalan 7 bitini farklı değişkenler için kullanmamıza olanak tanıyan bit fields dediğimiz bir yapı vardır. Tanımlarken hangi değişken için kaç bitlik alan ayırmak istediğimizi belirtmemiz yeterli, bit ayırma işlemini compiler halleder.

    

C++ bit fields

    Bir projede parametreleri kaydetmek isteyelim, hatta daha net olarak örneklendirelim, bir televizyon için olsun bu. Parametrelerimiz limitleriyle birlikte şöyle olsun :

  • Mevcut kanal : 1-16 (toplam 16 kanal) 4 bit
  • Ses seviyesi  : 0-15 (toplam 16 seviye) 4 bit
  • Otomatik parlaklık : true / false (toplam 2 durum) 1 bit
  • Dil seçeneği 1-8 (enum 8 dil) 3 bit
  • Kaynak 1-4 (enum AV-SCART-TV) 2 bit
parametreler çoğaltılabilir.


Kodumuz şöyle olacak

enum languages
{
    Turkish,
    English,
    French,
    Dutch,
    Spanish,
    Arabic,
    Farsi
};
enum videoSources
{
    Vga,
    Tv,
    Scart
};
struct params
{
    // 2 byte yer kaplaması beklenir
    // 4 bit: kanal verisi 0-15 arasında
    // 4 bit: ses seviyesi verisi 0-15 arasında
    // 1 bit: Otomaik parlaklık açık / kapalı
    // 3 bit: Dil seçimi enum maksimum 8 seçenek 
    // 2 bit: Video kaynağı seçimi
    // 2 bit: boş
    unsigned char channel :4, volume :4, autoBrightness :1, language :3, source :2, :2;
};
 
int main()
{
    params TvParams;
    TvParams.channel = 11;
    TvParams.volume = 5;
    TvParams.autoBrightness = false;
    TvParams.language = Turkish;
    TvParams.source = Vga;
    cout << sizeof(TvParams);
}

Her bir türü için örnek vermeye çalıştım, sonraki parametreye dikkat ederseniz isim vermedik, kullanmıyoruz ama sen bunun 2 bit olduğunu bil ve bize toplamda 16 bit 2 bytelık bellek ayır demiş olduk.
    Uygulama bize 2 çıktısını verdi, beklediğimiz gibi. Ancak sizeof kullanırken şunu yapamıyoruz :

sizeof(TvParams.autoBrightness);

    Herkese kolay gelsin

Önceki konu : Bit kopyalama
Sonraki konu: C++ Diziler

C++ Dersleri | Bit İşlemleri - Bit Kopyalama

 C++ dersleri bit işlemlerinde bit kopyalama konusundayız, bit kopyalamaktan kastımız nedir bir kaynak bitimiz var onun değerini alıyoruz, hedef bitimize yazıyoruz : 0 ise 0, 1 ise 1:

int main()
{
	int source = 5;
	int target = 3;
	int number = 0b00100100; // 36
	number ^= (-source ^ number) & (1LL << target); // 0010 1100
	// target bitini source bitiyle aynı yapar.
	
	cout << "result=" << number << endl;
}

 result=44  çıktısını alıyoruz.

işlem yapacağımız değer 36 'ydı 5. bitin değerini 3. bite yazınca 44 olmuş oldu. Sırasıyla işlemlerimize bakmamız gerekirse: değişenlerin değerlerini yerine yazarak devam edelim : 

number = 36 ^  (-5 ^ 36) & (1 <<  3);

1 << 3 : 0000 1000b değerini elde ettik,

-5 ^ 36 : 1111 1011 ^ 0010 0100 -> 1101 1111b elde ettik,

bu iki değeri & liyoruz : 0000 1000b & 1101 1111b -> 0000 1000 elde ettik,

son olarak da 36 ile üst satırda elde ettiğimiz değeri Xor luyoruz:

0010 0100b ^ 0000 1000 -> 0010 1100 değeri de 44 e eşit

finalde olan 36 : 0010 0100b     0010 1100b 5. indekste olan biti 2. indekse yazdırmış olduk.

Herkese kolay gelsin!


Önceki konu :  C/C++ Bit Set ve Bit Clear

Sonraki konu : Bit Alanları - Gömülü Sistemler Bellek Organizasyonu


C++ Dersleri | Bit işlemleri, Bit Clear ve Bit Set

 C++ dersleri bit işlemlerinde belki de en çok kullandığımız bit işlemlerinden biri bit set diğeri de bit clear dir desek yanılmış olayız herhalde, bitwise OR konusunda örneğini vermiştik burda da kullanalım:

int indexOfBitToSet = 5;
PORTB |= 1LL << indexOfBitToSet;

5. indexteki bit 'i set eder. portB 'nin 5 numaralı pini Set edilmiş (HIGH) olur. Burada diğer pin konfigürasyonları bu durumdan etkilenmezler.

PORTB 'nin 0000 0000b olduğunu düşünelim,

1 << 5 bize 0010 0000b değerini verir, bu değerle 0000 0000b değeri orlanırsa, gayet basitçe 5. indexin 1 olduğunu görebiliyoruz.

Aynı şekilde bir bit dizesindeki belirli bir biti CLEAR (0) yapmak için bitwise and kullanıyoruz:

  int indexOfBitToClear = 5;
  PORTB &= ~(1LL << indexOfBitToClear);

şimdide PORTB 'nin tümünün HIGH olduğunu varsayalım, 1111 1111b, 1 << 5 'den 0010 0000b değeri gelir, ifadenin başında yer alan ~ işaretiyle bit dizisindeki tüm değerler inverse oldu, yani tüm 1 ler 0, tm sıfırlar 1 oldu -> 1101 1111, son olarak da PORTB nin değeri olan 1111 1111 ü 1101 1111 ile and işlemine tabi tuttuğumuz vakit, diğer hiçbir bit eklilenmeden sadece 5. intexteki bitin Clear olduğunu görebiliyoruz.

Herkese kolay gelsin!

Önceki konu : Set Bitleri sayma

Sonraki konu : Bit Kopyalama

C++ Dersleri | Bit işlemleri - Bir Tamsayının 2'nin Kuvveti Olup Olmadığının Kontrol Edilmesi

 C++ dersleri bit işlemlerinde bir tam sayının 2 'nin kuvvetlerinden olup olmadığını kontrol edebilmek için bitwise operatörlerinden faydalanıyoruz :

int main()
{
	int number = 128;
	bool isPowerOfTwo = number && !(number & (number - 1));
	
	cout << "result=" << isPowerOfTwo << endl;
}

 result=1 

dikkat edilirse en sağdaki set biti resetleme konusuna, konunun genelinde ihtiyaç duyuluyor. Adım adım inceleyelim neler oluyor : 

128 : 1000 0000b en sağdaki set biti clear yaptığımız zaman değerimiz 0 oldu, yani false, başında ! not operatörü var bu da && operatörünün sağ tarafını true yaptı, sol tarafta da number 0 olmaması sebebiyle true döndürüyor, true && true sonucunda true dönmüş oluyor.

127 olsaydı değerimiz :

127 : 0111 1111b olacaktı, en sağdaki set biti clear yapınca : 0111 1110b ye dönüyor değerimiz : bu da true olarak değerlendirilir, başındaki not ! ile false olur, number true da olsa artık çıktımız false olmuştur.

Herkese kolay gelsin!

Önceki konu : Set Bitleri Sayma

Sonraki konu : Bit Clear ve Bit Set

C++ Dersleri | Bit İşlemleri - Set Bitleri sayma

 C++ bit işlemlerinde bir bit dizesi içerisindeki SET (1) olmuş bitlerin sayısını elde etmek için bir kaç yol izleyebiliriz, basitçe programlama kafasıyla for kullanarak yapılabilir :

int main()
{
	unsigned int a = 1234;     // 0100 1101 0010
	int bitCount = 0;
	for (bitCount = 0; a; a >>= 1)
		bitCount += a & 1LL;
	
	cout << "result=" << bitCount << endl;
}

 result=5 

ne yapmış olduk açıklamaya çalışamadan önce for ne yapıyor onu anlatalım : for 'un ilk ifadesi bir kez çalıştırılır, ikinci ifadesi kontrol edilecek durumu belirler; burada yalnızca a var, bu ne anlama geliyor, bu ifade boolean bir ifade olmalıdır, 0 olmamışsa durumun sağlandığını kabul eder yani 3 5 7 vs diğer tüm sayılar true kabul edilir, yani for 'un bitme şartı a nın sıfır olması durumudur, en son ifadesi de her dönüşte yürütülecek kod ifadesidir, for'u yazmadan for'u da anlatmış olduk kısaca, yazarız ilerde detaylı bir şekilde.

  • bitCount = 0    a = 1234 : 0100 1101 0010b    a & 1LL -> 0100 1101 0010 & 1 den +0 oldu
  • a >>= 1 -> 0010 0110 1001   a & 1LL den bu sefer 1 geldi bitCount +1 oldu,
yaani her defasında a bir bit sağa kaydırılarak değeri düştü en sondaki biti 1 ise bitCount 1 arttı sıfırsa değişmedi, adımlar tamamlandığında a sıfır oldu ve for çalışmayı durdurdu, bu arada bitCount 5 değerine ulaşmış oldu, dileyenler for 'un içerisinde bitCount 'a değer verdiğimiz satıra bir breakpoint atarak adım adım değerleri izleyebilirler.


Daha basitçe yine for kullanarak; en sağda set edilmiş biti kaldır formuna dayanan şu algoritma da kullanılabilir :

int main()
{
	unsigned int a = 1234;     // 0100 1101 0010
	int bitCount = 0;
	for (; a; ++bitCount)
		a &= (a - 1);
	
	cout << "result=" << bitCount << endl;
}

 result=5 

Burada for için başlangıç koşulu verilmemiş, yine a sıfır değilse devam ediyor, preincrement kullanılmış, bu da önce değer ver sonra aksiyona geç demekti, for içerisinde de en sağdaki biti resetle demiş olduk, bu sayede kaç resetlenecek bit varsa o kadar bitCount++ olmuş olacak.

Son olarak Hamming weight (üzerine tıklayarak detaylarına ulaşabilirsiniz) algoritmasıyla geliştirilen bir fonksiyonla şu şekilde de yapılabiliyor, armut piş durumu :)

unsigned popcount(std::uint64_t x)
{
	const std::uint64_t m1 = 0x5555555555555555; // binary: 0101...
	const std::uint64_t m2 = 0x3333333333333333; // binary: 00110011..
	const std::uint64_t m4 = 0x0f0f0f0f0f0f0f0f; // binary: 0000111100001111
	const uint64_t h01 = 0x0101010101010101; //the sum of 256 to the power of 0,1,2,3...
	x -= (x >> 1) & m1; // put count of each 2 bits into those 2 bits
	x = (x & m2) + ((x >> 2) & m2); // put count of each 4 bits into those 4 bits
	x = (x + (x >> 4)) & m4; // put count of each 8 bits into those 8 bits
	return (x * h01) >> 56; // left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ...
}
 
int main()
{
	unsigned int a = 1235;     // 0100 1101 0010
	int bitCount = popcount(a);
	
	cout << "result=" << bitCount << endl;
}


Herkese kolay gelsin!

Önceki konu : Bit Kontrol

Sonraki konu  : Bir Tamsayının 2'nin Kuvveti Olup Olmadığının Kontrol Edilmesi

C++ Dersleri | Bit işlemleri - Bit Kontrol

 C++ bit işlemlerinde bir bit dizesindeki belirli bir bitin durumunu kontrol etmek için değeri elde etmek istediğimiz bitin indeks değeri kadar right shift yapıp üzerinde and işlemi uygulayarak yapılabilir. Cümle şeklinde ifade edince bana bile anlaşılabilir gelmedi :) kodla bakalım :

int main()
{
	int a = 170;     // 10101010
	int result = (a >> 5) & 1LL;
	cout << "result=" << result << endl;  
}

 result = 5 

5. numaralı indexte yer alan bitin değerini sorguluyoruz, bu indexle kastettiğim sayma sayılarıyla değil, en sağdaki bit için 0 'dan başlayarak sayıyoruz anlamını ifade ediyor. Adım Adım şöyle gidiyor işlem :

a = 10101010 değerini   a >> 5 : 00000101 : yaptığımız zaman zaten istediğimiz bit en sağda yerini almış oluyor, bu değeri de 1 ile & işlemine tabi tutunca 1 ise 1, 0 ise döndürüyor result değişkenine. LL kullanmamızın sebebi Long Long deyip, değişkenin boyutundan bağımsız tüm veri tipleri için yapılacak işlemi garanti altına almaktır.

Şayet bitin değerine yerinde ihtiyacımız varsa; yani diğer tüm bitler 0 olacak, istediğimiz bitin değeri neyse yerinde o değer olacak, 5 için 00X00000 şeklinde

int main()
{
	int a = 170;     // 10101010
	int bitValueinPlace = a & (1LL << 5);
	cout << "result=" << bitValueinPlace << endl;
}

 result = 32 

5. biti 0 olan 218 gibi bir sayı kullansaydık; result=0 çıktısını elde etmiş olacaktık.

Kafanıza takılan herhangi birşey olursa lütfen yorumlarda sormaktan çekinmeyiniz.

Önceki konu : Bit toggle

Sonraki konu : Set Bitleri Sayma

C++ Dersleri | Bit İşlemleri - Bit Toggle

 C++ Dersleri | Bit İşlemleri - Bit Toggle; kısaca açıklamak gerekirse bir bit dizesinin istenen bitini toggle etmek, mevcut değerini ters çevirmek anlamına gelir, yani 0 ise 1, 1 ise 0 a çevirir.

int main()
{
	int a = 255;     // 11111111
	a ^= 1LL << 7;	  // 01111111	127
	cout << "a=" << a << endl;  
}

a değişkeninin 7 bitini toggle yap demiş olduk, işlemi adım adım yazmamız gerekirse

a 255 değerindeyken 8 bit, hepsi 1 şeklinde değer buluyor ikili sistemde -> 11111111 bu değeri (1 << 7) ile -> 10000000 xor işlemine tabii tutarsak 01111111 elde etmiş oluyoruz.

Önceki konu : Tüm Bitleri Set Etme

Sonraki konu : Bit Kontrol

C++ Dersleri | Bit İşlemleri - Tüm Bitleri Set Etme

 C++ ve gömülü sistemlerde bir değişkene ya da yazmaca ait tüm bitlerin set edilmesi çokça kolay bir mantığa dayanır. Eğer değişkenin ya da yazmacın boyutunu biliyorsak o kadar bit sayısına eşit olan en büyük sayıya eşitleyerek işin içinden sıyrılabiliriz: 8 bitlik bir yazmaç için 0xFF 'e eşitlemek bir çözüm olmakla beraber eğer bilmiyorsak bir fonksiyon içerisine template ile geliyorsa mesela daha basit bir yolu da söz konusu: değeri -1 e eşitlemek. 

uint8_t a = 0xFF;

    Yazının birinde bahsetmiştik, işaretli sayıların MSB biti (en solda) işaret biti olup 0 ise sayının pozitif 1 ise negatif olduğu anlamına geliyordu ve negatif tarafta anlamlı bitler 1 'ler değil 0'lardı. Ne demeye çalışıyorum ? 8 bit için konuşursak : -1 sayısı 2 lik sistemde 11111111b olarak ifade edilir, bence tüm bitleri set etmek için güzel yöntem :)

  PORTB = -1;

Tüm bitleri resetlemek istersek? Bilmem söylemeye gerek var mı ama yazmış olalım : a=0; işinizi çözecektir.

Herkese kolay gelsin!

Önceki konu : En Sağdaki Set Edilmiş Biti Resetleme

Sonraki konu : Bit Toggle

C++ Dersleri | Bit Manipulasyon - En Sağdaki Set Edilmiş Biti Resetleme

 Başlığın açıklayıcı olduğundan çok da emin olamadım :) Ancak durum şudur: 00110000 şeklinde güzide bir bit dizemiz olsun: Amacımız bu bit dizesinde en sağda bulunan 1 'i tespit edip 0 yapmak : yani yukarıdaki arkadaşı şuna çevirmek istiyoruz: 00100000 Kodumuz şu şekilde :

template <typename T>
T resetTheRightMostSetBit(T n)
{
	return n & (n - 1);
}
int main()
{
 	int a = 48;     // 00110000
	a = resetTheRightMostSetBit(a); // 00100000 -> 32
	cout << "a=" << a << endl;  
}

Template konusunu henüz yazmadık, ileride yazdığım zaman buralara linkini bırakıyor olurum-unutursam bir yorumla hatırlatır mısınız bana? :) - bilmeyen arkadaşlarımız için: kısaca anlatalım yine de T bir typename dolayısıyla hemen altına yazdığımız fonksiyonun içine herhangi bir tipte veri gönderip aynı tipte geri dönüş yapabilmesini sağlıyoruz, yani bu fonksiyonu int için ayrı char için ayrı byte için ayrı ayrı yazmamış oluyoruz. Bu şekilde yazmamın nedeni farklı örneklerle içeriklere devam etmek, basitçe şöyle de yapabilirdik :

int main()
{
	int a = 48;     // 00110000
	a = a & (a - 1); // 00100000 -> 32
	cout << "a=" << a << endl;  
}

her iki kod da bize  a=32  çıktısını verecek. 

int için konuuyor olursak a = 0 ise; 0 ile herhangi birşeyi & 'lediğimiz zaman 0 elde ediyor olacağız

int sıfır dışında birşeyse örneğimiz üzerinden gidelim 00110000 ile a - 1 den elde ettiğimiz   00101111 sayısını & 'leyerek (dikkat edin sıfırlamak istediğimiz bit'i -1 le zaten sıfır yapmış olduk bu noktada) nihai hedefimize  kolayca ulaşmış oluyoruz. Benden bir tavsiye floating point sayılar ile denemeyin bile :)

Herkese kolay gelsin.

Önceki konu : Bit Manipülasyonları

Sonraki konu : Tüm Bitleri Set Etme

C++ Dersleri | Bit Manipülasyonları

    C++ bit işlemlerine devam ediyoruz, bit manipülasyonları çoğu zaman insanda yahu bunu nasıl yapıcaz diye kendisini sorgulatan bir his uyandırsa da öğrenildiğinde bu kadar basit miymiş yahu dedirtebilecek kadar da güçlü bir konudur :) Zevklidir demeden de geçmeyelim.

    Bir bit dizemiz olsa ve set edilmiş bitlerden en sağdakini tespit edip reset etmeniz istense, programcının kafası önce en sağdan başlayarak tek tek bitleri 0 mı 1 mi diye kontrol ettirip 0 ise ilerleyip 1 ise reset et ve orayı terk et diye bir kod yazmaya gidiyor, yok canım bu kadar zor olmamalı. Bu konuda bir çözüm önerisi olan cesur arkadaşım ileriki konularda yazdıklarımızı okumadan burada yorum olarak bizlere görüşünü bildirmeni şiddetle rica ediyoruz, farklı kafalardan farklı fikirler çıkar severim discussion ları.

Ya da tüm bitleri set etmemiz istense ? bu biraz daha görece basit geliyor, boyutu biliyorsak sorun yok mesela 8 bitlik bir dize için konuşuyorsak a = FF; der ve çıkarım işin içinden, ya bilmiyorsam? 😱

Bir bit dizesinin belirli bir bitini toggle etmek; toggle etmek ne demek? acaba; toggle etmek demek 1 ise 0, 0 ise 1 yapmak demek, ya da yine dize içerisindeki belirli bir biti kontrol etmek, set durumunda mı reset durumunda mı? ( set : 1 , reset : 0 olduğu anlamına gelir). Belki de bit dizesindeki set edilmiş bitlerin sayısını bilmemiz gerekecek, ya da reset durumdaki bitlerin sayısını. Ne derin konular. Yine belirli bir biti set etmek ya da clear etmek (sıfır yapmak). Yahut bir tam sayının 2 nin kuvveti olup olmadığını kontrol etmek? Bunlar masking işlemlerinde hayat kurtarıcı oluyor, bildiğimiz bitmask yahu, bilmiyor muyuz.. takipte kalın hepsini yazacak bu kardeşiniz size.

Son olarak da bitlerin yer değiştirmesine bakabiliriz: yani 3 bit in sayısal değerini 5. bitin sayısal değeriyle değiştirmek isteyebiliriz: 0100 1101 -> 0110 0101. 

Hepsini halledeceğiz merak etmeyin takipte kalın, kafanıza takılan herşeyi yorumlarda sormaktan lütfen çekinmeyin, blog yazmanın en güzel yolu, yazıları yeniden düzenleyebilmek sanırım. Youtube videoları için geçerli olmayan bu durum burada bizleri avantajlı hale getiriyor, yorumdan gelen bir soru üzerine ekleme çıkartma yapılabiliyor, haydi içeriklere siz de destekte bulunun :)


Şimdilik herkese kolay gelsin.

Önceki konu : Bitwise Operatörleri | Right Shift Operatör

Sonraki konu : Bit Manipulasyon - En Sağdaki Set Edilmiş Biti Resetleme

Video :



C++ Dersleri | Bitwise Operatörleri | Right Shift Operatör

 C++ bitwise operatörlerden right shift operatörünü konu alıyoruz >> . Right shift operatörü,  C++ Dersleri | Bitwise Operatörleri | Left Shift Operatör konusunda bahsettiğimiz tüm özellikleri taşıyor, tek farkla : bit dizisini sağa doğru kaydırıyor. Bir örnekle right shift operatörünün nasıl kullanıldığına bakalım:

int main()
{
	int a = 2;	// 0010b
	int b = a >> 1;	// 0001b
	cout << "a=" << a << ", b=" << b;
}

çıktımız şu şekilde :  a=2, b=1 

Kolayca anlayabileceğimiz şekilde a değişkeni için oluşan binary sistem diziliminde indexlemeye göre 1. bit hanesinde yer alan operatöre gönderdiğimiz sayı :1 adedince sağ tarafa kaydırılmış. Left Shift operatörü için sayıyı 2 'nin kuvvetleriyle çarpmakla aynı şey demiştik, burada olan da sayıyı 2 'nin kuvvetleriyle bölmekle aynı şeydir. a değişkeninin değeri olan 2 'yi 2^1 'e (bu 1 operatöre gönderilen 1) bölerek 1 elde etmiş olduk:

Farklı sayılarla denememiz gerekirse :

int main()
{
	int a = 44;		
	int b = a >> 2;
	cout << "a=" << a << ", b=" << b; // 44/2^2 -> 44/4 -> b=11 çıktısını üretir.
	a = 128;
	b = a >> 5;
	cout << "a=" << a << ", b=" << b; //128/2^5 ->128/32 -> b = 4 çıktısını üretir.
}

Yine, left shift operatöründe olduğu gibi kaydırma operatörüne gönderdiğimiz kaç bit kaydırılacağı değeri, negatif olamaz Önemli bir nokta daha işaretli sayılarla çalışıyorsak şayet, bit kaydırması yapılacak operandın yani a değişkeninin de pozitif olması gerekir, negatif sayılardaki davranışı da işlemi yapacağını garanti etmez ve undefined behavior olarak tanımlanır.

Son olarak bu operatörün operandlar üzerinde değer değiştirmediğini unutmayın diyelim :

int main()
{
	int a = 2;
	a >> 1;
	cout << "a=" << a << endl;  // a=2
	a >>= 1;
	cout << "a=" << a << endl;  // a=1
}

yani a >> 1 yaparak a 'nın değerini değiştiremeyiz, eşittir operatörünü kullanmak durumundayız :)

Herkese kolay gelsin.



Önceki konu:  C++ Left Shift Operatörü

Sonraki Konu: C++ ile Bit Manipülasyonları


C++ Dersleri | Bitwise Operatörleri | Left Shift Operatör

 C++ bitwise operatörlerinden left shift << operatörüne gelmiş bulunmaktayız, adından da anlaşılabileceği üzere binary düzendeki bir değişkeni  MSB (most significant bit) tarafından kayıplarla LSB (least significant bit) tarafından yeni eklemelerde düzenleyen bir operatördür, ne demek istiyorum bir örnekle açıklamaya çalışalım:

int main()
{
	int a = 4;		//0100
	int b = a << 1;		//1000
	cout << "a=" << a << ", b=" << b << endl;
}

şöyle bir çıktıya ulaştık :  a=4, b=8 

burada olan; indekse göre konuşacak olursam, a değişkeninin 2. bitinde yer alan 1 değeri, 1 bit sola kaydırılmış oldu. Olayı bu kadar basit olmakla beraber dikkat edilmesi gereken noktalarımız vardır; ilk dikkat etmemiz gereken şey değişkenin boyutu, int yukarıdaki kod için benim sistemimde 4 bytes. Bu da şu anlama gelir 4bytes * 8 bit 'ten 32 bitlik bir değişkenimiz var demektir,  ve bu 32 bitlik değişkenin en soldaki biti işaret bitidir, değişkenimiz int olduğu için negatif sayıları da barındırır, bunu da sistem MSB yani en soldaki en anlamlı en yüksek değerlikli olan bitten alır bu bit 0 ise pozitif 1 ise negatif olarak değerlendirilir, nereye gelmeye çalışıyorum : int a = 1 deyip, 31 defa left shift yaparsanız şayet sayımız: en solda 1 gerisi 0 olarak değişmiş olur, ayrıca bir bilgi : negatif tarafta anlamlı bitler 0 lardır, işler ters yürür yani, dolayısıyla int değişkeni için negatif tarafta alabileceği en son değeri yakalamış oluruz, deneyelim mi? 

int main()
{
	int a = 1;
	int b = a << 31;		
	cout << "a=" << (int)a << ", b=" << (int)b << endl;
}

 a=1, b=-2147483648 

gördüğünüz üzere sayı negatif taraftaki ulaşabileceği maksimum (sayı değeri bakımından en küçük) değere ulaşmış oluyor. Finalde olan şudur: sağdan yeni bir sıfır eklenir en soldaki bit de kaybolur. Merak edenler için söylemiş olalım left shift gibi, right shift operatörümüz de var, kaydırmak istediğimiz bit sayısı pozitif, sola kaydırma operatörü ile negatif bir sayı kullanarak sağa kaydırabilir miyiz acaba davranışı belirsiz bir davranışa yol açar, bu sebeple o maceraya girmeyin :)

Arithmetic overflow: Left shift count is negative or greater than or equal to the operand size which is undefined behavior.

Arithmetic overflow: Left shift count is negative or greater than or equal to the operand size which is undefined behavior.

Buradan anladığımız üzere üst limitimiz de değişken boyutumuz, yani a << 32 diyemiyoruz, 32 bitlik bir int değişkeni için. Bunlar keyifli konular üzerinde oynayarak ve keyif alarak tecrübe edinebilirsiniz. Bir şeyi farketmiş olmanızı ümit ediyorum bu notaya kadar: eğer etmediyseniz, left shift operatörü aslında sayıyı 2 üzeri kaydırdığınız bit sayısı ile çarpar : yaani, 

1 << 1 demişseniz bu -> 1*2^1 demektir, sonuç olarak 2 üretir,

1 << 2 demişseniz bu -> 1*2^2 demektir, sonuç olarak 4 üretir,

1 << 3 demişseniz bu -> 1*2^3 demektir, sonuç olarak 8 üretir.

İlk örneğimizde a değişkenimiz 10 olsaydı ve b = a << 3; yazsaydık, 10*2^3 'ten 80 sonucuna ulaşacaktık. 10 luk sistemde de böyle değil mi bi sayıyı 10 ile çarpmak istediğimizde sağına bir sıfır ekliyoruz bitti gitti.

Gömülü sistemlerde nasıl karşımıza çıkar ona da bir bakış atalım; yine bir register 'e ait özel bit bitin değerini değiştirmek istediğimizde left shift operatörüne rastlamamız mümkün, buraya kadar gördüklerimizi de üst üste koymuş olalım :

  DDRB |= (1 << DDB1);
  PORTB |= (1 << PORTB1);
  PORTB &= ~(1 << PORTB1);

ilk satırı al setup 'ın içine diğer iki satırı da aralarına delay ekleyerek loop 'un içine at, bildiğimiz blink kodu. Şimdi bakalım şair burada ne anlatmak istemiş,

DDRB ; atmega328p için DataDirectionRegisterB den gelmekte, PORTB için giriş çıkış durumlarının belirlendiği register, kendisini |= yaparak eski konfigürasyonunu koruyarak 1 nolu pinini çıkış olarak ayarlamışız, peki neler olmuş burda adım adım bakalım:

DDRB 'nin başlangıç notasında 0000 0000 olduğunu kabul ediyoruz, DDB1 iom328p.h dosyasında 

#define DDB1 1

olarak tanımlanmış, bu yazarken ne yaptığımızı da görelim bilelim diye, o zaman parantez içinde şu olmuş (1 << 1 ) => 0000 0001 miş sola bir bit kaydırmışız 0000 0010 olmuş, sonra bu değerle DDRB yi orlamışız : 0000 0000 | 0000 0010 => 0000 0010 elde etmişiz, aslında basit değil mi? anlattıklarımın aynısı bir alt satır için de geçerli PORTB1 neymiş ona bakalım sadece :

#define PORTB1 1

o da 1 'miş yani tıpatıp aynısı, sadece PORTB yazmacına yazmış olduk.

Son satır biraz karmaşık gibi, ama değil. Şimdiye dek gördüklerimizden tek eksiğimiz ~ lambda işareti, bunun da olayı çok basit; önüne yerleştirilen operandın 1 lerini 0, 0 larını 1 yapar. Parantezin içi aynı: 0000 0010, ~ ile şu hale gelir => 1111 1101 sonra PORTB 'yi bir önceki satırda 0000 0010 yapmıştık, bununla & işlemine tabii tutuyoruz : 0000 0010 & 1111 1101 => 0000 0000, loop un içerisinde B portunun 1 numaralı pini bir HIGH bir LOW oluyor.

Kafanıza takılan bir şey olursa yorumlarda sormaya lütfen çekinmeyin, herkese kolay gelsin!

Bu arada ben bu left shift operatörüyle PORTB içinde çalışan bir kara şimşek kodu yazabilirim diyen cesur arkadaşım, seni yorumlara bekliyoruz,  😉 Bir tüyo lazım olabilir: sağa kaymak için right shift operatörünü kullanacaksın >> Bir sonraki konumuzda onu yazıyor olacağız.



Önceki konu: Bitwise And ~ C++ ve operatörü &

Sonraki konu: C++ Right Shift Operatörü

C++ Dersleri | Bit işlemleri - Bitwise And - C++ ve operatörü &

 C++ bitwise and (ve operatörü) & , dijital elektronikten bildiğimiz ve kapısıyla aynı mantıkla çalışmaktadır, iki operandı bulunup, her iki operand da doğru ise doğru (true) sonucunu üretir, diğer tüm olaslıklarda yanlış (false) sonucunu üretir. C++ ve operatörü için doğruluk tablosunu bir görsel ile paylaşalım :

cpp and operator truth table

kodlarken de aynı isimdeki değişkenleri kullanalım:

int main()
{
	int a = 7;		//0111
	int b = 13;		//1101
	int aANDb = a & b;	//0101
	cout << "a=" << a << ", b=" << b << ", a&b=" << aANDb;
}

programın çıktısı şu şekilde :  a=7, b=13, a&b=5 

Sonuç olarak 5 elde ettik, C++ 'ın bu hesaplamayı nasıl yaptığını alttaki görselde açıklamaya çalıştım:

Adım adım and işlemi

Her sütunu kendi içinde and işlemine tabi tutup aynı haneye cevap olarak döndürüyor. Bu operatörün kendi başına değişkenin değerinde bir değişiklik yapmadığını unutmayın, a değişkenini 5 rakamıyla and işlemine tabi tutup çıkan değeri a ' ya atamak için mutlaka eşittir operatörü kullanmak gerekiyor:

int main()
{
	int a = 7;			//0111
	a & 5;
	cout << "a=" << a << endl;
	a &= 5; // => a = a & 5;
	cout << "a=" << a << endl;
}

ilk satır 7 çıktısını verirken, ikinci satırda 7 & 5 in sonucu olan 5 değerini görebiliriz.

Bitwise operatörlerden bahsettiğimiz ilk bölümde dediğimiz gibi bitwise operatörler çoğunlukla gömülü sistemlerde karşımıza çıkar; and operatörü için register seviyesinde bir atmega328p programladığımızı düşünelim, kodumuzun önceki kısımlarında da PORTB 'nin 3. pinini çıkış olarak ayarladığımızı ve şimdide 2.pinini giriş olarak ayarlamak istediğimizi kabul edelim.

  DDRB =  0b00001000; // 3 pini giriş olarak ayarladık
  DDRB &= 0b11111011; // 3 pini giriş olarak ayarladığımız
                       // konfigurasyona zarar vermeden 2 pini
                       // giriş olarak ayarladık

Bunu yaptığınız zaman hem 2. pinin (en sağdan 0 dan başlayarak sola doğru sayıyoruz-MSB -LSB dizilimi) giriş olarak ayarlanmasını garanti etmiş olursunuz: çünkü eski konfigurasyonu ne olursa olsun biz & ile birlikte o pin için 0 gönderdiğimiz için sonucun 0 üretmesini garanti altına almış oluyoruz, hem de diğer bütün pinleri 1 ile and işlemine tabi tutarak evvelce 1 iseler 1 kalmalarını 0 iseler sıfır kalmalarını garantilemiş oluyoruz. Aynı mantıkla pinin dijital seviyesini de bu şekilde LOW 'a çekmeyi garantileyebilirsiniz.

Kafanıza takılan her şeyi lütfen yorumlarda sormaktan çekinmeyin, Şimdilik herkese kolay gelsin



Önceki konu :  Bitwise XOR, Özel Veya Operatörü

Sonraki konu : Bitwise Operatörleri | Left Shift Operatör

Türksat Saat Kanalı ve IRIG-B Time Code

Türksat Saat Kanalından Saat Bilgisi Nasıl Alınır? Uyduda kanalları dolaşırken, şu Türksat Saat kanalı hep dikkatimi çekmiştir. Özellikle  S...