C sözdizimi - C syntax

C programlama dilinin sözdizimi yazılımın yazma düzenleyen kurallar bütünüdür C dilinde . Son derece özlü olan, sonuçta ortaya çıkan nesne koduyla yakın bir ilişkisi olan ve buna rağmen nispeten yüksek düzeyde veri soyutlaması sağlayan programlara izin vermek için tasarlanmıştır . C, taşınabilir işletim sistemi geliştirme için yaygın olarak başarılı olan ilk üst düzey dildi .

C sözdizimi, maksimum munch ilkesini kullanır.

Veri yapıları

İlkel veri türleri

C dili : Üç formlarda sayıları temsil ayrılmaz , gerçek ve karmaşık . Bu ayrım , çoğu merkezi işlem biriminin komut seti mimarisindeki benzer ayrımları yansıtır . İntegral veri türleri kümesinde numaralarını saklamak tamsayı iken, gerçek ve kompleks numaralar grubu sayıları (ya da numara çifti) 'i temsil gerçek sayılar olarak kayan nokta formu.

Tüm C tamsayı türlerinin signedve unsignedçeşitleri vardır. Eğer signedveya unsignedaçıkça belirtilmemişse, çoğu durumda signedolduğu varsayılır. Ancak, tarihi nedenlerden dolayı sade char, hem signed charve hem de unsigned char. Derleyiciye ve karakter kümesine bağlı olarak işaretli bir tür veya işaretsiz bir tür olabilir (C, C temel karakter kümesinin üyelerinin pozitif değerlere sahip olduğunu garanti eder). Ayrıca düz olarak belirtilen bit alanı türleri intderleyiciye bağlı olarak işaretli veya işaretsiz olabilir.

Tamsayı türleri

C'nin tamsayı türleri, çeşitli sayı aralıklarını temsil edebilen farklı sabit boyutlarda gelir. Tür , tipik olarak 8 bit genişliğinde olan chartam olarak bir bayt (en küçük adreslenebilir depolama birimi) kaplar . ( charC'nin "temel" karakterlerinden herhangi birini temsil edebilmesine rağmen , uluslararası karakter kümeleri için daha geniş bir tür gerekebilir.) Çoğu tamsayı türünün , ve anahtar sözcükleri tarafından belirtilen hem işaretli hem de işaretsiz çeşitleri vardır . İşaretli tamsayı türleri, ikinin tamamlayıcısını , birlerin tamamlayıcısını veya işaret ve büyüklük gösterimini kullanabilir . Çoğu durumda, türü belirlemenin birden çok eşdeğer yolu vardır; örneğin ve eş anlamlıdır. signedunsigned signed short intshort

Bazı türlerin temsili, depolamayı işgal eden ancak genişliğe dahil olmayan kullanılmayan "dolgu" bitlerini içerebilir. Aşağıdaki tablo, standart tamsayı türlerinin ve bunların izin verilen minimum genişliklerinin (herhangi bir işaret biti dahil) tam bir listesini sağlar .

Standart tamsayı türleri için özellikler
Belirticinin en kısa biçimi Minimum genişlik (bit)
_Bool 1
char 8
signed char 8
unsigned char 8
short 16
unsigned short 16
int 16
unsigned int 16
long 32
unsigned long 32
long long 64
unsigned long long 64

charTürü, hem farklıdır signed charve unsigned char, ancak bunların aynı gösterimi olduğu garanti edilir. _BoolVe long longçeşitleri 1999 yılından beri standardize edilir ve daha eski C derleyicileri tarafından desteklenmiyor olabilir. Türe _Boolgenellikle standart başlık stdbool.h tarafından tanımlanan typedefad aracılığıyla erişilir . bool

Genel olarak, herhangi bir platform için uygulanan genişlikler ve temsil şeması, diğer platformlar için geliştirilen kaynak kodunu içe aktarma kolaylığı göz önünde bulundurularak, makine mimarisine dayalı olarak seçilir. Türün genişliği, intözellikle C uygulamaları arasında büyük ölçüde değişir; genellikle belirli bir platform için en "doğal" kelime boyutuna karşılık gelir. Standart başlık limitleri.h , herhangi bir belirli platformda uygulandığı şekliyle standart tamsayı türlerinin minimum ve maksimum temsil edilebilir değerleri için makroları tanımlar.

Standart tamsayı türlerine ek olarak, typedefstandart başlıklarda s için kullanılabilen başka "genişletilmiş" tamsayı türleri olabilir . Genişliğin daha kesin bir şekilde belirtilmesi için, programcılar typedefstandart stdint.h başlığındaki s'yi kullanabilir ve kullanmalıdır .

Tamsayı sabitleri, kaynak kodda çeşitli şekillerde belirtilebilir. Sayısal değerler ondalık (örnek: 1022), önek olarak sıfır (0) ile sekizlik01776 veya önek olarak 0x (sıfır x) ile onaltılık olarak belirtilebilir ( 0x3FE). 'R'"Karakter sabiti" olarak adlandırılan tek tırnak içindeki bir karakter (örnek: ), tür ile yürütme karakter kümesindeki o karakterin değerini temsil eder int. Karakter sabitleri dışında, bir tamsayı sabitinin türü, belirtilen değeri temsil etmek için gereken genişlik tarafından belirlenir, ancak her zaman en az int. Bu, açık bir uzunluk ve/veya imza değiştiricisi eklenerek geçersiz kılınabilir; örneğin, 12lutürü vardır unsigned long. Negatif tamsayı sabitleri yoktur, ancak aynı etki genellikle bir tekli olumsuzlama operatörü "-" kullanılarak elde edilebilir.

Numaralandırılmış tür

Sayılan tip ile belirtilen C, enumgenellikle anahtar kelime ve sadece adında bir "enum" (genellikle belirgin ee'-num /ˌi.nʌm/ veya ee'-Noom /ˌi.nuːm/), değerlerini temsil etmek için tasarlanmış bir türüdür bir dizi adlandırılmış sabit boyunca. Numaralandırılmış sabitlerin her biri type değerine sahiptir int. Her enumtürün kendisi, charişaretli veya işaretsiz bir tamsayı türüyle uyumludur veya bir tür seçmek için kendi kurallarını tanımlar.

Bazı derleyiciler, numaralandırılmış türe sahip bir nesneye, sabitlerinden biri olmayan bir değer atandığında uyarır. Bununla birlikte, böyle bir nesneye, uyumlu türlerinin aralığında herhangi bir değer atanabilir ve enumsabitler, bir tamsayı beklendiği her yerde kullanılabilir. Bu nedenle, adlandırılmış sabitler oluşturmak enumiçin genellikle önişlemci #defineyönergeleri yerine değerler kullanılır . Bu tür sabitler, belirli bir tanımlayıcı ad alanı içinde bulundukları için genellikle makrolardan daha güvenlidir.

Numaralandırılmış bir tür, enumbelirteç ve numaralandırma için isteğe bağlı bir ad (veya etiket ), ardından küme parantezleri içinde yer alan ve virgüllerle ayrılmış bir veya daha fazla sabitin bir listesi ve isteğe bağlı bir değişken adları listesi ile bildirilir. Belirli bir numaralandırılmış türe yapılan sonraki başvurular, enumanahtar sözcüğü ve numaralandırmanın adını kullanır . Varsayılan olarak, bir numaralandırmadaki ilk sabite sıfır değeri atanır ve sonraki her değer, önceki sabite göre bir artırılır. Bildirimdeki sabitlere belirli değerler de atanabilir ve belirli değerleri olmayan sonraki sabitlere o noktadan itibaren artan değerler verilecektir. Örneğin, aşağıdaki beyanı göz önünde bulundurun:

enum colors { RED, GREEN, BLUE = 5, YELLOW } paint_color;

Bu, enum colorstürü bildirir ; intsabitleri RED(değeri = 0), GREEN(değeri birden büyük olduğu RED, 1) BLUE(bunun değeri, belirli bir değer, 5'tir) ve YELLOW(değeri birden büyük olduğu BLUE, 6); ve enum colorsdeğişken paint_color. Sabitler, numaralandırma bağlamı dışında kullanılabilir (herhangi bir tamsayı değerine izin verildiğinde) ve sabitler dışındaki değerler paint_colorveya herhangi bir tür değişkene atanabilir enum colors.

Kayan nokta türleri

Kayan nokta formu, sayıları kesirli bir bileşenle temsil etmek için kullanılır. Bununla birlikte, çoğu rasyonel sayıyı tam olarak temsil etmezler; onlar bunun yerine yakın bir yaklaşımdır. Belirticileriyle gösterilen üç tür gerçek değer vardır: tek kesinlik ( float), çift kesinlik ( double) ve çift genişletilmiş kesinlik ( long double). Bunların her biri, değerleri farklı bir biçimde, genellikle IEEE kayan nokta biçimlerinden biri olarak temsil edebilir .

Kayan nokta türleri
Tür belirteçleri Hassasiyet (ondalık basamak) Üs aralığı
Asgari IEEE 754 Asgari IEEE 754
float 6 7.2 (24 bit) ±37 ±38 (8 bit)
double 10 15.9 (53 bit) ±37 ±307 (11 bit)
long double 10 34.0 (113 bit) ±37 ±4931 (15 bit)

Kayan nokta sabitleri ondalık gösterimde yazılabilir , örn 1.23. Ondalık bilimsel gösterim , E gösterimi olarak da bilinen bir ondalık üs eklenerek eveya Etakip edilerek kullanılabilir , ör. 1.23e2(1.23 × 10 2 = 123.0 değerine sahiptir ). Ya bir ondalık nokta ya da bir üs gereklidir (aksi halde sayı bir tamsayı sabiti olarak çözümlenir). Onaltılık kayan noktalı sabitler benzer kuralları takip eder, ancak ön eki ile ön eki getirilmeleri 0xve ikili bir üs belirtmek için pveya kullanılması gerekir P, örn. 0xAp-2(A h × 2 −2 = 10 × 2 −2 = 10 ÷ 4 ). Hem ondalık ve onaltılık kayan nokta sabitleri karakterleri eklenmiş olabilir fveya Ftürde bir sabit belirtmek için float, tarafından l(letter l) veya Ltürünü belirtmek için long doubleya da bir için unsuffixed sol doublesabiti.

Standart başlık dosyası float.h, uygulamanın kayan nokta türlerinin float, double, ve maksimum değerlerini tanımlar long double. Ayrıca, kayan noktalı sayıların işlenmesiyle ilgili diğer sınırları da tanımlar.

Depolama sınıfı belirteçleri

Her nesnenin bir depolama sınıfı vardır. Bu, en temel olarak, diğer özelliklerle (bağlantı ve kayıt ipucu) birlikte statik (varsayılan için genel), otomatik (yerel için varsayılan) veya dinamik (tahsis edilmiş) olabilen depolama süresini belirtir .

Depolama sınıfları
belirteçler Ömür Dürbün Varsayılan başlatıcı
auto Blok (yığın) Engellemek başlatılmamış
register Blok (yığın veya CPU kaydı) Engellemek başlatılmamış
static programı Blok veya derleme birimi Sıfır
extern programı Küresel (tüm program) Sıfır
(yok) 1 Dinamik (yığın) Başlatılmamış (başlatıldı 0kullanılıyorsa calloc())
1malloc() ve free()kitaplık işlevleri kullanılarak tahsis edildi ve tahsis edildi .

Varsayılan olarak bir blok içinde bildirilen değişkenler , autoveya registerdepolama sınıfı belirteçleriyle açıkça bildirilenler gibi otomatik depolamaya sahiptir . autoVe registerbelirteçleri, fonksiyonları ve işlevi bağımsız değişken bildirimleri içinde kullanılabilmektedir; bu nedenle, autobelirteç her zaman gereksizdir. Tüm blokların dışında bildirilen ve staticdepolama sınıfı belirteci ile açıkça bildirilen nesnelerin statik depolama süresi vardır. Statik değişkenler, derleyici tarafından varsayılan olarak sıfıra başlatılır .

Otomatik depolamaya sahip nesneler, bildirildikleri bloğa yereldir ve bloktan çıkıldığında atılır. Ek olarak, registerdepolama sınıfıyla bildirilen nesnelere , derleyici tarafından kayıtlara erişim için daha yüksek öncelik verilebilir ; ancak derleyici bunların hiçbirini bir kayıt defterinde saklamamayı seçebilir. Bu depolama sınıfına sahip nesneler, ( &) unary işlecinin adresiyle kullanılamaz . Statik depolamaya sahip nesneler, programın tüm süresi boyunca kalır. Bu şekilde, aynı nesneye bir fonksiyon tarafından birden çok çağrı üzerinden erişilebilir. Ayrılan depolama süresine sahip nesneler malloc, free, ve ilgili işlevlerle açıkça oluşturulur ve yok edilir .

externDepolama sınıfı belirteci bir nesne için bir depolama herhangi bir yerde tanımlanan olduğunu gösterir. Bir bloğun içinde kullanıldığında, depolamanın o bloğun dışında bir bildirimle tanımlandığını gösterir. Tüm blokların dışında kullanıldığında, depolamanın derleme biriminin dışında tanımlandığını gösterir. externBir işlev bildiriminde kullanıldığında bellek sınıfı olarak gereksizdir. Bildirilen işlevin derleme biriminin dışında tanımlandığını gösterir.

Depolama belirteçlerinin yalnızca işlevler ve nesneler için geçerli olduğunu unutmayın; tür ve numaralandırma bildirimleri gibi diğer şeyler, göründükleri derleme birimine özeldir. Öte yandan, türlerin niteleyicileri vardır (aşağıya bakın).

Tür niteleyicileri

Türler, verilerinin özel özelliklerini belirtmek için nitelenebilir. Tür niteleyicisi const, bir değerin başlatıldıktan sonra değişmediğini belirtir. constNitelikli bir değeri değiştirmeye çalışmak tanımsız davranış sağlar, bu nedenle bazı C derleyicileri bunları rodatada veya (gömülü sistemler için) salt okunur bellekte (ROM) depolar . Tür niteleyici volatile, herhangi bir ifade veya deyim tarafından değiştirilmemiş olsa bile değer değişebileceğinden veya bellek eşlemeli I için olduğu gibi birden çok yazmanın gerekli olabileceğinden, görünüşte gereksiz okumaları veya yazmaları kaldıramayacağını optimize eden bir derleyiciye belirtir. /O .

Eksik türler

Eksik tip, üyeleri henüz belirtilmemiş bir yapı veya birleşim tipi, boyutu henüz belirtilmemiş bir dizi tipi veya voidtip ( voidtür tamamlanamıyor). Böyle bir tür somutlaştırılamaz (boyutu bilinmemektedir) veya üyelerine erişilemez (onlar da bilinmemektedir); ancak, türetilmiş işaretçi türü kullanılabilir (ancak başvurudan çıkarılamaz).

Genellikle ileri veya dış bildirimler olarak işaretçilerle birlikte kullanılırlar. Örneğin, kod bunun gibi eksik bir tür bildirebilir:

struct thing *pt;

Bu, ptbir işaretçi struct thing ve tamamlanmamış tür olarak bildirir struct thing. Verilere yönelik işaretçiler, neyi işaret ettiklerine bakılmaksızın her zaman aynı bayt genişliğine sahiptir, bu nedenle bu ifade kendi başına geçerlidir ( ptbaşvurusu kaldırılmadığı sürece ). Eksik tür, daha sonra yeniden bildirilerek aynı kapsamda tamamlanabilir:

struct thing {
    int num;
}; /* thing struct type is now completed */

Özyinelemeli yapıları uygulamak için eksik türler kullanılır ; tür bildiriminin gövdesi, çeviri biriminde daha sonra ertelenebilir:

typedef struct Bert Bert;
typedef struct Wilma Wilma;

struct Bert {
    Wilma *wilma;
};

struct Wilma {
    Bert *bert;
};

Eksik türler de veri gizleme için kullanılır ; eksik tür bir başlık dosyasında ve gövde yalnızca ilgili kaynak dosyada tanımlanır.

işaretçiler

Bildirimlerde yıldız değiştirici ( *) bir işaretçi tipi belirtir. Örneğin, belirteç inttamsayı tipine atıfta bulunduğunda, belirteç int*"işaretçiden tamsayıya" tipine başvurur . İşaretçi değerleri iki bilgi parçasını ilişkilendirir: bir bellek adresi ve bir veri türü. Aşağıdaki kod satırı, ptr adında bir işaretçiden tamsayıya değişken bildirir :

int *ptr;

referans

Statik olmayan bir işaretçi bildirildiğinde, kendisiyle ilişkilendirilmiş belirtilmemiş bir değere sahiptir. Böyle bir işaretçi ile ilişkili adres, kullanılmadan önce atama ile değiştirilmelidir. Aşağıdaki örnekte, ptr , a değişkeniyle ilişkili verilere işaret edecek şekilde ayarlanır :

int a = 0;
int *ptr = &a;

Bunu gerçekleştirmek için "address-of" operatörü (unary &) kullanılır. Takip eden veri nesnesinin hafıza konumunu üretir.

referanstan çıkarma

İşaret edilen verilere bir işaretçi değeri aracılığıyla erişilebilir. Aşağıdaki örnekte, b tamsayı değişkeni , 10 olan a tamsayı değişkeninin değerine ayarlanmıştır :

int a=10;
int *p;
p = &a;
int b = *p;

Bu görevi gerçekleştirmek için yıldız işareti (*) ile gösterilen tekli referans kaldırma operatörü kullanılır. İşaretçi türünde olması gereken işleneninin işaret ettiği verileri döndürür. Böylece, ekspresyonu * p aynı değere temsil eder , bir . Bir boş göstericinin referansını kaldırmak yasa dışıdır.

diziler

dizi tanımı

Diziler, aynı tipteki ardışık elemanların yapılarını temsil etmek için C'de kullanılır. (Sabit boyutlu) bir dizinin tanımı aşağıdaki sözdizimine sahiptir:

int array[100];

burada bir dizi adlı tanımlayan bir dizi temel türün 100 değerleri tutmak için int. Bir işlev içinde bildirilirse, dizi boyutu sabit olmayan bir ifade de olabilir, bu durumda belirtilen sayıda öğe için bellek ayrılacaktır. Daha sonraki kullanımlarda çoğu bağlamda, değişken dizisinin bir ifadesi, dizideki ilk öğeye yönelik bir işaretçiye dönüştürülür. sizeofOperatör bir istisnadır: sizeof arraytüm dizinin büyüklüğü (yani, bir 100 kat daha büyük verir intve sizeof(array) / sizeof(int)100 döndürür). Diğer bir istisna, örneğin tüm diziye bir işaretçi veren & (adres-of) operatörüdür.

int (*ptr_to_array)[100] = &array;

Öğelere erişim

Bir dizinin öğelerinin değerlerine erişmek için birincil olanak, dizi alt simge operatörüdür. Dizinin i dizinli öğesine erişmek için sözdizimi , o dizi öğesinde depolanan değeri ifade eden olacaktır . array[i]

Dizi alt simge numaralandırması 0'dan başlar (bkz. Sıfır tabanlı dizin oluşturma ). İzin verilen azami dizi indis, bir dizi dikkate açıklamak için, bir dizi eksi 1. öğelerin sayısı nedenle eşit olan bir 10 elemanı olan ilan; ilk eleman olur a[0]ve son eleman olur a[9].

C, dizi kullanımı için otomatik sınır denetimi yapma olanağı sağlamaz . Mantıksal olarak 10 elemanlı bir dizideki son indis 9 olsa da, 10, 11 ve benzeri indisler tanımsız sonuçlarla yanlışlıkla belirtilebilir.

Diziler ve işaretçiler değiştirilebilir olduğundan, dizi öğelerinin her birinin adresleri eşdeğer işaretçi aritmetiği ile ifade edilebilir . Aşağıdaki tablo, mevcut dizi için her iki yöntemi de göstermektedir:

Dizi abonelikleri ve işaretçi aritmetiği
eleman Birinci Saniye Üçüncü n inci
Dizi alt simgesi array[0] array[1] array[2] array[n - 1]
Başvurusu kaldırılmış işaretçi *array *(array + 1) *(array + 2) *(array + n - 1)

İfade a[i]semantik olarak 'ye eşdeğer olduğundan *(a+i), bu da 'ye eşdeğerdir , bu form nadiren kullanılmasına rağmen *(i+a)ifade olarak da yazılabilir i[a].

Değişken uzunluklu diziler

Blok kapsamında C99 standartlaştırılmış değişken uzunluklu diziler (VLA'lar). Bu tür dizi değişkenleri, bir bloğa girdikten sonra çalışma zamanında bir tamsayı değerinin değerine göre tahsis edilir ve bloğun sonunda serbest bırakılır. İtibariyle C11 bu özellik artık derleyici tarafından uygulanmak üzere gereklidir.

int n = ...;
int a[n];
a[3] = 10;

Bu sözdizimi, boyutu bloğun sonuna kadar sabitlenen bir dizi üretir.

Dinamik diziler

C standart kütüphanesi yardımıyla dinamik olarak yeniden boyutlandırılabilen diziler üretilebilir . mallocFonksiyon bellek tahsis edilmesi için basit bir yöntem sağlar. Bir parametre alır: bayt olarak ayrılacak bellek miktarı. Başarılı ayırmanın ardından , ayrılan alanın başlangıcına işaret malloceden genel bir ( void) işaretçi değeri döndürür . Döndürülen işaretçi değeri, atama ile örtük olarak uygun bir türe dönüştürülür. Tahsis tamamlanamazsa, mallocbir boş gösterici döndürür . Bu nedenle, aşağıdaki bölüm, yukarıdaki istenen bildirime işlev olarak benzer:

#include <stdlib.h> /* declares malloc */
...
int *a = malloc(n * sizeof *a);
a[3] = 10;

Sonuç, n bitişik nesnenin ilkine işaret eden bir "işaretçi int" değişkenidir ( a ) ; dizi-işaretçi denkliği nedeniyle bu, son satırda gösterildiği gibi gerçek bir dizi adı yerine kullanılabilir. Bu dinamik ayırmayı kullanmanın avantajı , kendisine ayrılan bellek miktarının, çalışma zamanında gerçekten ihtiyaç duyulanla sınırlı olabilmesi ve gerektiğinde değiştirilebilmesidir (standart kitaplık işlevi kullanılarak ). intrealloc

Dinamik olarak ayrılan belleğe artık ihtiyaç kalmadığında, çalışma zamanı sistemine geri bırakılmalıdır. Bu, freeişlev çağrısı ile yapılır . Tek bir parametre alır: önceden tahsis edilmiş belleğe bir işaretçi. Bu, önceki bir çağrı tarafından döndürülen değerdir malloc.

Bir güvenlik önlemi olarak, bazı programcılar işaretçi değişkenini şu şekilde ayarlar NULL:

free(a);
a = NULL;

Bu, çoğu sistemde işaretçiyi yeniden başlatma girişimlerinin programı çökertmesini sağlar. Bu yapılmazsa, değişken, ücretsiz kullanım sonrası bir hataya yol açabilecek sarkan bir işaretçi haline gelir . Ancak, işaretçi yerel bir değişkense, onu olarak ayarlamak NULL, programın işaretçinin diğer kopyalarını kullanmasını engellemez. Yerel kullanım sonrası ücretsiz hataları, statik analizörlerin tanıması genellikle kolaydır . Bu nedenle, bu yaklaşım yerel işaretçiler için daha az kullanışlıdır ve uzun ömürlü yapılarda depolanan işaretçiler ile daha sık kullanılır. Genel olarak, işaretçileri olarak ayarlamak NULLiyi bir uygulamadır, çünkü bir programcının NULLreferanstan çıkarmadan önce işaretçileri kontrol etmesine izin verir , böylece çökmeleri önlemeye yardımcı olur.

Dizi örneğini hatırlayarak, dinamik ayırma yoluyla sabit boyutlu bir dizi de oluşturulabilir:

int (*a)[100] = malloc(sizeof *a);

...Bu, bir işaretçiden diziye bir işaret verir.

İşaretçiden diziye erişim iki şekilde yapılabilir:

(*a)[index];

index[*a];

Yineleme iki şekilde de yapılabilir:

for (int i = 0; i < 100; i++)
    (*a)[i];

for (int *i = a[0]; i < a[1]; i++)
    *i;

İkinci örneği kullanmanın yararı, ilk örneğin sayısal sınırının gerekli olmamasıdır; bu, işaretçiden diziye herhangi bir boyutta olabileceği ve ikinci örneğin herhangi bir değişiklik yapılmadan yürütülebileceği anlamına gelir.

Çok boyutlu diziler

Ek olarak, C, büyük satır sırasına göre saklanan çok boyutlu dizileri destekler . Teknik olarak, C çok boyutlu dizileri, elemanları dizi olan tek boyutlu dizilerdir. Çok boyutlu dizileri bildirmek için sözdizimi aşağıdaki gibidir:

int array2d[ROWS][COLUMNS];

nerede ROWS ve KOLONLAR sabitlerdir. Bu, iki boyutlu bir diziyi tanımlar. Abonelikleri soldan sağa doğru okuyan dizi2d , her bir öğesi bir COLUMNS tamsayı dizisi olan bir ROWS uzunluğu dizisidir .

Bu çok boyutlu dizideki bir tamsayı öğesine erişmek için

array2d[4][3]

Yine soldan sağa okuma, bu 5. satıra ve o satırdaki 4. öğeye erişir. İfade array2d[4], daha sonra dördüncü tam sayıya erişmek için [3] ile abone olduğumuz bir dizidir.

Dizi abonelikleri ve işaretçi aritmetiği
eleman Birinci İkinci satır, ikinci sütun i. satır, j. sütun
Dizi alt simgesi array[0][0] array[1][1] array[i - 1][j - 1]
Başvurusu kaldırılmış işaretçi *(*(array + 0) + 0) *(*(array + 1) + 1) *(*(array + i - 1) + j - 1)

Daha yüksek boyutlu diziler de benzer şekilde bildirilebilir.

Çok boyutlu bir dizi, dizilere yapılan bir dizi referansla karıştırılmamalıdır ( Iliffe vektörleri veya bazen diziler dizisi olarak da bilinir ). İlki her zaman dikdörtgendir (tüm alt diziler aynı boyutta olmalıdır) ve bitişik bir bellek bölgesini işgal eder. Sonuncusu, her biri bellekte farklı bir yerde bir alt dizinin ilk öğesine işaret edebilen tek boyutlu bir işaretçi dizisidir ve alt dizilerin aynı boyutta olması gerekmez. İkincisi, çoklu kullanımlarla oluşturulabilir malloc.

Teller

C'de, dize değişmezleri çift tırnak ( ") ile çevrilidir , örneğin "Hello world!"ve dizenin sonunu işaretlemek için charek bir boş sonlandırma karakteri (0 değerli) koduyla belirtilen değerlerin bir dizisine derlenir .

Dize değişmezleri katıştırılmış yeni satırlar içeremez; bu yasaklama, dilin ayrıştırılmasını biraz basitleştirir. Bir dizgeye yeni bir satır eklemek için aşağıdaki gibi ters eğik çizgi çıkışı \n kullanılabilir.

charBu boş sonlandırılmış biçimi kullanma dizisi olarak düzenlenmiş dize verileriyle (sabit olması gerekmez) çalışmak için birkaç standart kitaplık işlevi vardır ; aşağıya bakın .

C'nin string-literal sözdizimi çok etkili olmuştur ve C++, Objective-C, Perl, Python, PHP, Java, Javascript, C#, Ruby gibi diğer birçok dile girmiştir. Günümüzde, neredeyse tüm yeni diller C-tarzı dizi sözdizimini benimsiyor veya geliştiriyor. Bu söz diziminden yoksun diller, C'den önce gelme eğilimindedir.

Ters eğik çizgi kaçışları

Dizenin içine bir çift tırnak işareti eklemek isterseniz, bu, \örneğin, bir ters eğik çizgi ( ) ile kaçarak yapılabilir "This string contains \"double quotes\".". Değişmez bir ters eğik çizgi eklemek için ikiye katlanmalıdır, örneğin "A backslash looks like this: \\".

Bir dizgeye kontrol karakterlerini vb. girmek için ters eğik çizgiler kullanılabilir:

Kaçmak Anlam
\\ değişmez ters eğik çizgi
\" çift ​​alıntı
\' Tek alıntı
\n Yeni satır (satır besleme)
\r Satırbaşı
\b geri al
\t Yatay sekme
\f Form besleme
\a Uyarı (zil)
\v Dikey sekme
\? Soru işareti ( trigraflardan kaçmak için kullanılır )
%% Yüzde işareti, yalnızca printf biçimi dizeleri (Not \% standart değildir ve her zaman tanınmaz)
\OOO OOO sekizlik değerine sahip karakter (burada OOO 1-3 sekizlik basamak, '0'-'7')
\xHH Onaltılık değeri HH olan karakter ( HH 1 veya daha fazla onaltılık basamaktır, '0'-'9','A'-'F','a'-'f')

Diğer ters eğik çizgi kaçışlarının kullanımı C standardı tarafından tanımlanmamıştır, ancak derleyici satıcıları genellikle dil uzantıları olarak ek kaçış kodları sağlar. Bunlardan biri, ASCII onaltılık değeri 1B olan ve diğer karakter kümelerinde ( EBCDIC gibi ) temsil edilmemesi nedeniyle C standardına eklenmemiş olan kaçış karakteri\e için kaçış dizisidir . O mevcuttur GCC , clang ve TTK .

Dize değişmez birleştirme

C'de dize değişmezi bitiştirme vardır , yani bitişik dize değişmezleri derleme zamanında birleştirilir; bu, uzun dizelerin birden çok satıra bölünmesine ve ayrıca C önişlemci tanımlarından kaynaklanan dize değişmezlerinin ve derleme zamanında dizelere eklenmesine makroların eklenmesine izin verir :

    printf(__FILE__ ": %d: Hello "
           "world\n", __LINE__);

genişleyecek

    printf("helloworld.c" ": %d: Hello "
           "world\n", 10);

hangi sözdizimsel eşdeğerdir

    printf("helloworld.c: %d: Hello world\n", 10);

Karakter sabitleri

Bireysel karakter sabitleri tek tırnaklıdır, örn 'A'. ve türü vardır int(C++'da, char). Aradaki fark "A", 'A' ve '\0' olmak üzere iki karakterden oluşan boş sonlandırılmış bir diziyi 'A'temsil ederken, doğrudan karakter değerini (ASCII kullanılıyorsa 65) temsil etmesidir. Aynı ters eğik çizgi kaçışları, karakter dizileri için olduğu gibi desteklenir, ancak (elbette) "bir karakter olarak kaçış yapılmadan geçerli bir şekilde kullanılabilir, ancak 'şimdi kaçılmalıdır.

Bir karakter sabiti boş olamaz (yani ''geçersiz sözdizimidir), ancak bir dize olabilir (hala boş sonlandırma karakterine sahiptir). Çok karakterli sabitler (örn. 'xy') nadiren yararlı olmalarına rağmen geçerlidir - bir tamsayıda birkaç karakterin saklanmasına izin verirler (örn. 32-bit tamsayıya 4 ASCII karakteri, 64-bit tamsayıya 8 sığabilir). Karakterlerin an içine paketlenme sırası intbelirtilmediği için (tanımlaması uygulamaya bırakıldı), çok karakterli sabitlerin taşınabilir kullanımı zordur.

Bununla birlikte, belirli bir platformla ve derleyici uygulamasıyla sınırlı durumlarda, çok karakterli sabitler, imzaların belirtilmesinde kullanımlarını bulurlar. Yaygın bir kullanım durumu, Klasik Mac OS derleyicilerinin ve doğal büyük endianlığının birleşiminin, tamsayıdaki baytların, değişmezde tanımlanan karakterlerin tam sırasına göre göründüğü anlamına geldiği OSType'tır . Popüler "uygulamaları" ile tanım aslında tutarlıdır: GCC, Clang ve içinde Visual C ++ , '1234'verim ASCII altında. 0x31323334

Geniş karakter dizileri

Tür char1 bayt genişliğinde olduğundan, tek bir chardeğer tipik olarak en fazla 255 farklı karakter kodunu temsil edebilir; bu, dünya çapında kullanılan tüm karakterler için neredeyse yeterli değildir. Uluslararası karakterlere daha iyi destek sağlamak için, ilk C standardı (C89), geniş karakterleri (type olarak kodlanmış wchar_t) ve geniş karakter dizilerini tanıttı .L"Hello world!"

Geniş karakterler genellikle 2 bayt ( UTF-16 gibi 2 baytlık bir kodlama kullanılarak ) veya 4 bayttır (genellikle UTF-32 ), ancak Standart C genişliği belirtmez wchar_tve seçimi uygulayıcıya bırakır. Microsoft Windows genellikle UTF-16 kullanır, bu nedenle yukarıdaki dize bir Microsoft derleyicisi için 26 bayt uzunluğunda olacaktır; Unix Dünya GCC 52 bayt dize oluşturmak gibi böylece bu tür derleyicileri, UTF-32 tercih eder. 2 bayt genişlik , belirli karakterlerin ( BMP dışındakiler ) tek bir karakterde temsil edilememesiyle wchar_taynı sınırlamaya sahiptir ; ancak vekil çiftler kullanılarak temsil edilmelidir . charwchar_t

Orijinal C standardı, geniş karakter dizileriyle çalışmak için yalnızca minimal işlevleri belirtir; 1995'te standart, dizilere kıyasla çok daha kapsamlı destek içerecek şekilde değiştirildi char. İlgili işlevler çoğunlukla chareşdeğerlerine göre adlandırılır , "w" eklenir veya "str" ​​yerine "wcs" eklenir; onlar belirtilen <wchar.h>ile <wctype.h>geniş karakter sınıflandırma içeren ve işlevleri haritalama.

Uluslararası karakterler destekleyen şimdi genel olarak önerilen yöntem geçer UTF-8 , depolanan charUTF-8 doğrudan çünkü, diziler ve UTF-8 editörü kullanarak eğer doğrudan kaynak kodunda yazılabilir ASCII uzantısı .

Değişken genişlikli diziler

için yaygın bir alternatif , bir mantıksal karakterin dizenin birden çok konumuna yayılabileceği değişken genişlikli bir kodlamawchar_t kullanmaktır . Değişken genişlikli dizeler, derleyiciyi karıştırma veya sayısal ters eğik çizgi kaçışları kullanma riskiyle (örneğin UTF-8'de "é" için) harfi harfine kodlanabilir . UTF-8 kodlama spesifik olarak (tasarlanmıştı Plan 9 standart kitaplığı dizge işlevleri ile uyumluluk için); kodlamanın destekleyici özellikleri arasında gömülü boş değerlerin olmaması, alt diziler için geçerli yorumların olmaması ve önemsiz yeniden eşitleme yer alır. Bu özelliklerden yoksun kodlamaların standart kitaplık işlevleriyle uyumsuz olması muhtemeldir; kodlamaya duyarlı dize işlevleri genellikle bu tür durumlarda kullanılır. "\xc3\xa9"

Kütüphane işlevleri

Hem sabit hem de değişken olan dizeler , standart kitaplık kullanılmadan manipüle edilebilir . Ancak kitaplık, boş sonlandırılmış dizelerle çalışmak için birçok yararlı işlev içerir .

Yapılar ve birlikler

Yapılar

C'deki yapılar ve birlikler, çeşitli türlerde adlandırılmış üyelerden oluşan bir dizi veri kapsayıcıları olarak tanımlanır. Diğer programlama dillerindeki kayıtlara benzerler. Bir yapının üyeleri bellekte ardışık konumlarda depolanır, ancak derleyicinin verimlilik için veya hedef mimari tarafından uygun hizalama için gerekli dolgu olarak üyeler arasına veya sonra (ancak ilk üyeden önce değil) dolgu eklemesine izin verilir . Bir yapının boyutu, elemanlarının boyutlarının toplamı ile dolgunun boyutunun toplamına eşittir.

Birlikler

C'deki sendikalar yapılarla ilgilidir ve farklı tür ve boyutlarda nesneleri (farklı zamanlarda) tutabilen nesneler olarak tanımlanır. Diğer programlama dillerindeki değişken kayıtlara benzerler. Yapılardan farklı olarak, bir birliğin bileşenlerinin tümü bellekte aynı konuma atıfta bulunur. Bu şekilde, her yeni tür için ayrı bir nesne oluşturmaya gerek kalmadan farklı türdeki nesneleri tutmak için çeşitli zamanlarda bir birleşim kullanılabilir. Bir birleşimin boyutu, en büyük bileşen türünün boyutuna eşittir.

beyanname

Yapılar structanahtar kelime ile, birleşimler ise anahtar kelime ile bildirilir union. Belirtici anahtar sözcüğünü, yapının veya birleşimin biçimini tanımlamak için kullanılan isteğe bağlı bir tanımlayıcı adı izler. Tanımlayıcıyı, yapının veya birliğin gövdesinin bildirimi izler: küme parantezleri içinde yer alan ve her bildirimin noktalı virgülle sonlandırıldığı üye bildirimlerinin bir listesi. Son olarak, bildirim, yapının veya birliğin örnekleri olarak bildirilen isteğe bağlı bir tanımlayıcı adları listesiyle sona erer.

Örneğin, aşağıdaki ifade s, üç üye içeren bir yapı bildirir ; ayrıca şu şekilde bilinen yapının bir örneğini de bildirecektir tee:

struct s {
    int   x;
    float y;
    char  *z;
} tee;

Ve aşağıdaki ifade, adlı benzer bir birlik uve bunun bir örneğini adlandıracak n:

union u {
    int   x;
    float y;
    char  *z;
} n;

Yapıların ve birliklerin üyeleri, eksik veya işlev türüne sahip olamaz. Bu nedenle üyeler, beyan edilen yapının veya birliğin bir örneği olamaz (çünkü o noktada eksiktir), ancak beyan edilen türe işaretçiler olabilir.

Bir yapı veya birlik gövdesi bildirildiğinde ve bir ad verildiğinde, structveya unionuygun şekilde belirteci ve adı kullanan yeni bir veri türü olarak kabul edilebilir . Örneğin, yukarıdaki yapı bildirimi verilen aşağıdaki ifade, yapının sadlı yeni bir örneğini bildirir r:

struct s r;

Yapıya daha sonraki referanslarda veya anahtar sözcüğüne typedefolan ihtiyacı ortadan kaldırmak için belirteci kullanmak da yaygındır . Yapının gövdesinden sonraki ilk tanımlayıcı, yapı tipinin yeni adı olarak alınır (yapı örnekleri bu bağlamda bildirilemez). Örneğin, aşağıdaki ifade, bazı yapıları içerecek olan s_type olarak bilinen yeni bir tür bildirecektir : structunion

typedef struct {...} s_type;

Gelecekteki ifadeler daha sonra yapıya atıfta bulunmak için s_type belirtecini (genişletilmiş struct... belirteci yerine ) kullanabilir.

Üyelere erişim

Üyelere bir yapı veya birlik örneğinin adı, nokta ( .) ve üyenin adı kullanılarak erişilir . Örneğin, yukarıdan tee bildirimi verildiğinde, y (type float) olarak bilinen üyeye aşağıdaki sözdizimi kullanılarak erişilebilir:

tee.y

Yapılara genellikle işaretçiler aracılığıyla erişilir. ptr_to_tee olarak bilinen, tee için bir işaretçi tanımlayan aşağıdaki örneği göz önünde bulundurun :

struct s *ptr_to_tee = &tee;

Üye y arasında tee sonra kaldırma tarafından erişilebilir ptr_to_tee ve sol işlenen olarak sonuç kullanılarak:

(*ptr_to_tee).y

ptr_to_tee tee işaret ettiği tee.ysürece yukarıdaki daha basit olanla aynıdır . Operatör önceliği nedeniyle (".", "*" den daha yüksek olduğu için), bu amaç için daha kısa olan yanlıştır, bunun yerine olarak ayrıştırılır ve bu nedenle parantezler gereklidir. Bu işlem yaygın olduğu için C, bir üyeye doğrudan bir işaretçiden erişmek için kısaltılmış bir sözdizimi sağlar . Bu sözdizimi ile, örneğin adı, işaretçinin adıyla değiştirilir ve nokta, karakter dizisiyle değiştirilir . Bu nedenle, aşağıdaki y erişim yöntemi önceki ikisiyle aynıdır: *ptr_to_tee.y*(ptr_to_tee.y)->

ptr_to_tee->y

Sendika üyelerine de aynı şekilde ulaşılmaktadır.

Bu zincirlenebilir; örneğin, bağlantılı bir listede, n->next->nexttakip eden ikinci düğüm için başvurulabilir ( n->nextbunun boş olmadığı varsayılarak ).

Görev

Yapıların ve birliklerin tek tek üyelerine değer atamak, sözdizimsel olarak diğer herhangi bir nesneye değer atamakla aynıdır. Tek fark, bir lvalue sözdizimi yukarıda belirtilen tarafından erişilen atama elemanın adıdır.

Bir yapı, aynı tipteki başka bir yapıya birim olarak da atanabilir. Yapılar (ve yapıların işaretçileri), işlev parametresi ve dönüş türleri olarak da kullanılabilir.

Örneğin, aşağıdaki ifade, tee yapısındaki x adlı üyeye yukarıdan 74 değerini ('t' harfi için ASCII kod noktası) atar :

tee.x = 74;

Ve aynı atama, tee yerine ptr_to_tee kullanılarak şöyle görünür:

ptr_to_tee->x = 74;

Sendika üyeleri ile atama aynıdır.

Diğer işlemler

C standardına göre, bir yapı üzerinde yapılabilecek yasal işlemler, onu kopyalama, ona birim olarak atama (veya başlatma), ( &) unary operatörünün adresi ile adresini alma ve üyelerine erişmedir. . Sendikalar da aynı kısıtlamalara sahiptir. Dolaylı olarak yasaklanmış işlemlerden biri karşılaştırmadır: yapılar ve birlikler C'nin standart karşılaştırma olanakları ( ==, >, <, vb.) kullanılarak karşılaştırılamaz.

Bit alanları

C ayrıca, açıkça belirtilen sayıda bit içeren bir tam sayı olan, bit alanı olarak bilinen özel bir yapı elemanı türü sağlar . Biraz alan türü bir yapı elemanı olarak bildirilir int, signed int, unsigned intya da _Bool, bir kolon ile (üye adı aşağıdaki :) ve kalan, gereken bit sayısı. Tek bir bit alanındaki toplam bit sayısı, belirtilen türdeki toplam bit sayısını geçmemelidir.

Her zamanki C sözdizimi kuralları için özel istisna olarak, biraz alan türü olarak ilan verip uygulama tanımlı olan intbelirtmeden, signedya unsigned, imzalı veya imzasız olduğunu. Bu nedenle, taşınabilirlik için tüm yapı elemanlarında signedveya açıkça belirtilmesi önerilir unsigned.

Yalnızca iki nokta üst üste ve ardından birkaç bitten oluşan adsız alanlara da izin verilir; bunlar dolguyu gösterir . Adsız bir alan için sıfır genişliğinin belirtilmesi, yeni bir kelimeye hizalamaya zorlamak için kullanılır .

Bit alanlarının üyelerinin adresleri yoktur ve bu nedenle ( &) tekli işlecinin adresi ile kullanılamaz . sizeofOperatör bit alanlara uygulanabilir olmayabilir.

Aşağıdaki bildirim, olarak bilinen yeni bir yapı türünü fve bunun olarak bilinen bir örneğini bildirir g. Yorumlar, üyelerin her birinin açıklamasını sağlar:

struct f {
    unsigned int  flag : 1;  /* a bit flag: can either be on (1) or off (0) */
    signed int    num  : 4;  /* a signed 4-bit field; range -7...7 or -8...7 */
    signed int         : 3;  /* 3 bits of padding to round out to 8 bits */
} g;

başlatma

Varsayılan başlatma , yukarıda açıklanan depolama sınıfı belirtecine bağlıdır .

Dilin dilbilgisi nedeniyle, herhangi bir sayıda kaşlı ayraç çiftine bir skaler başlatıcı eklenebilir. Yine de çoğu derleyici, böyle birden fazla çift varsa bir uyarı verir.

int x = 12;
int y = { 23 };     //Legal, no warning
int z = { { 34 } }; //Legal, expect a warning

Yapılar, birlikler ve diziler, bir başlatıcı listesi kullanılarak bildirimlerinde başlatılabilir. Göstericiler kullanılmadıkça, bir başlatıcının bileşenleri, tanımlandıkları ve saklandıkları sırayla öğelere karşılık gelir, bu nedenle önceki tüm değerler, herhangi bir belirli öğenin değerinden önce sağlanmalıdır. Belirtilmemiş tüm öğeler sıfıra ayarlanır (birleşimler hariç). Çok fazla başlatma değerinden bahsetmek hata veriyor.

Aşağıdaki deyim yapısının yeni bir örneğini başlatır s olarak bilinen pi :

struct s {
    int   x;
    float y;
    char  *z;
};

struct s pi = { 3, 3.1415, "Pi" };

Belirlenmiş başlatıcılar

Belirlenmiş başlatıcılar, üyelerin, önceki değerleri açıkça sağlamadan, herhangi bir sırada ada göre başlatılmasına izin verir. Aşağıdaki başlatma öncekine eşdeğerdir:

struct s pi = { .z = "Pi", .x = 3, .y = 3.1415 };

Bir başlatıcıda bir işaretleyici kullanmak, başlatma "imlecini" hareket ettirir. Aşağıdaki örnekte, MAX10'dan büyükse, ortasında sıfır değerli öğeler olacaktır a; 10'dan küçükse, ilk beş başlatıcı tarafından sağlanan değerlerden bazıları ikinci beş tarafından geçersiz kılınacaktır ( MAX5'ten küçükse bir derleme hatası olacaktır):

int a[MAX] = { 1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0 };

Olarak C89 , bir birlik ilk elemanına uygulanan tek bir değer ile başlatıldı. Olduğunu, birlik u yukarıda tanımlanan sadece olabilirdi int x üyesi başlatıldı:

union u value = { 3 };

Belirlenmiş bir başlatıcı kullanarak, başlatılacak üyenin ilk üye olması gerekmez:

union u value = { .y = 3.1415 };

Bir dizinin boyutu bilinmiyorsa (yani dizi tamamlanmamış bir türse ), başlatıcıların sayısı dizinin boyutunu belirler ve türü tamamlanmış olur:

int x[] = { 0, 1, 2 } ;

Süslenmemiş başlatıcı listeleri yanlış anlaşıldığında, açık başlatma sağlamak için bileşik tanımlayıcılar kullanılabilir. Aşağıdaki örnekte w, her yapı bir üyeden a(bir dizi 3 int) ve bir üyeden b(an int) oluşan bir yapılar dizisi olarak bildirilmiştir . Başlatıcı, boyutunu w2 olarak ayarlar ve her birinin ilk öğesinin değerlerini ayarlar a:

struct { int a[3], b; } w[] = { [0].a = {1}, [1].a[0] = 2 };

Bu şuna eşdeğerdir:

struct { int a[3], b; } w[] =
{
   { { 1, 0, 0 }, 0 },
   { { 2, 0, 0 }, 0 } 
};

Standart C'de bir başlatıcının tekrarını belirtmenin bir yolu yoktur.

Bileşik değişmezler

Bileşik yapı ve dizi değişmezleri oluşturmak için başlatma metodolojisini ödünç almak mümkündür:

// pointer created from array literal.
int *ptr = (int[]){ 10, 20, 30, 40 };

// pointer to array.
float (*foo)[3] = &(float[]){ 0.5f, 1.f, -0.5f };

struct s pi = (struct s){ 3, 3.1415, "Pi" };

Bileşik değişmezler, bildirimi daha okunabilir hale getirmek için genellikle belirlenmiş başlatıcılarla birleştirilir:

pi = (struct s){ .z = "Pi", .x = 3, .y = 3.1415 };

operatörler

Kontrol Yapıları

C serbest biçimli bir dildir .

Destekleme stili , programcıdan programcıya değişir ve tartışma konusu olabilir. Daha fazla ayrıntı için Girinti stiline bakın.

Bileşik ifadeler

Bu bölümdeki öğelerde, herhangi bir <deyim>, bir bileşik ifade ile değiştirilebilir . Bileşik ifadeler şu şekildedir:

{
    <optional-declaration-list>
    <optional-statement-list>
}

ve bir işlevin gövdesi olarak veya tek bir ifadenin beklendiği herhangi bir yerde kullanılır. Bildirim listesi, o kapsamda kullanılacak değişkenleri bildirir ve ifade listesi, gerçekleştirilecek eylemlerdir. Parantezler kendi kapsamlarını tanımlar ve bu parantezler içinde tanımlanan değişkenler, kapanış parantezinde otomatik olarak serbest bırakılır. Bildirimler ve ifadeler, bir bileşik ifade içinde serbestçe karıştırılabilir ( C++ 'da olduğu gibi ).

Seçim ifadeleri

C'nin iki tür seçim deyimi vardır : ifdeyim ve switchdeyim .

ifİfadesi şeklindedir:

if (<expression>)
    <statement1>
else
    <statement2>

In ifeğer açıklamada, <expression>parantez içinde sıfırdan farklı (doğru) olduğunu kontrol geçer <statement1>. Eğer elseyan tümce mevcutsa ve <expression>sıfır (yanlış) ise, kontrol 'ye geçecektir <statement2>. else <statement2>Sahte bir devamsızlık durumunda parçası, isteğe bağlıdır ve <expression>basitçe atlayarak neden olacaktır <statement1>. An elseher zaman en yakın eşleşmeyen ile eşleşir if; Gerektiğinde veya netlik için bunu geçersiz kılmak için parantezler kullanılabilir.

switchDeyim nedenleri bir değerine bağlı olarak çeşitli tabloların birine transfer edilmesi kontrol ifadesi olmalıdır, ayrılmaz türü . Bir anahtar tarafından kontrol edilen alt ifade tipik olarak bileşiktir. Alt ifade içindeki herhangi bir ifade, bir veya daha fazla caseetiketle etiketlenebilir; bu etiket, anahtar kelimeyi casetakiben sabit bir ifade ve ardından iki nokta üst üste (:)'den oluşur. Sözdizimi aşağıdaki gibidir:

switch (<expression>)
{
    case <label1> :
        <statements 1>
    case <label2> :
        <statements 2>
        break;
    default :
        <statements 3>
}

Aynı anahtarla ilişkili iki durum sabiti aynı değere sahip olamaz. defaultBir anahtarla ilişkilendirilmiş en fazla bir etiket olabilir . Durum etiketlerinin hiçbiri aşağıdaki parantez içindeki ifadeye eşit değilse switch, kontrol defaultetikete geçer veya etiket yoksa default, yürütme tüm yapının hemen ötesinde devam eder.

Anahtarlar iç içe olabilir; a caseveya defaultetiket, switchonu içeren en içtekiyle ilişkilendirilir . Switch ifadeleri "düşebilir", yani bir vaka bölümü yürütmesini tamamladığında, bir break;ifadeyle karşılaşılıncaya kadar ifadeler aşağı doğru yürütülmeye devam eder . Düşüş bazı durumlarda yararlıdır, ancak genellikle istenmez. Önceki örnekte, eğer <label2>ulaşılırsa, ifadeler <statements 2>yürütülür ve parantezler içinde başka bir şey yoktur. Ancak, <label1>ulaşılırsa, iki case ifadesini ayıracak bir şey olmadığı için hem <statements 1>ve hem <statements 2>de yürütülür break.

Alışılmadık olmasına rağmen, switchetiketleri diğer kontrol yapılarının alt bloklarına eklemek mümkündür . Buna örnek olarak aşağıdakiler Duff cihazı ve Simon Tatham 's uygulanmasını değiş tokuş eden kavramlar içinde Macun .

yineleme ifadeleri

C'nin üç yineleme ifadesi biçimi vardır :

do
    <statement>
while ( <expression> ) ;

while ( <expression> )
    <statement>

for ( <expression> ; <expression> ; <expression> )
    <statement>

Gelen whileve dotablolar, alt deyimi değeri olarak çok uzun defalarca yürütülür expressionsıfırdan (true eşdeğeri) kalıntıları. ile while, tüm yan etkiler dahil olmak üzere test, <expression>her yinelemeden önce gerçekleşir (yürütülmesi <statement>); ile do, test her yinelemeden sonra gerçekleşir. Bu nedenle, bir dodeyim her zaman alt deyimini en az bir kez whileyürütürken, alt deyimi hiç yürütmeyebilir.

İfade:

for (e1; e2; e3)
    s;

şuna eşittir:

e1;
while (e2)
{
    s;
cont:
    e3;
}

bir continue;ifadenin davranışı dışında ( fordöngüde e3yerine atlar e2). Eğer e2boştur, bir ile değiştirilmesi gerekir 1.

forDöngüdeki üç ifadeden herhangi biri atlanabilir. Eksik bir ikinci ifade, whiletesti her zaman sıfırdan farklı hale getirir ve potansiyel olarak sonsuz bir döngü oluşturur.

C99'dan beri , ilk ifade, tipik olarak aşağıdakiler gibi bir başlatıcı içeren bir bildirim biçimini alabilir:

for (int i = 0; i < limit; ++i) {
    // ...
}

Bildirimin kapsamı, fordöngünün kapsamıyla sınırlıdır .

ifadeleri atla

Jump ifadeleri, kontrolü koşulsuz olarak aktarır. Dört çeşit vardır atlama tablolarda C: goto, continue, break, ve return.

gotoDeyimi şuna benzer:

goto <identifier> ;

Tanımlayıcı bir olmalı etiket geçerli fonksiyonu bulunan (iki nokta üst üste). Kontrol, etiketli ifadeye aktarılır.

Bir continueifade yalnızca bir yineleme ifadesi içinde görünebilir ve kontrolün en içteki yineleme ifadesinin döngü-devam eden kısmına geçmesine neden olur. Yani, ifadelerin her biri içinde

while (expression)
{
    /* ... */
    cont: ;
}

do
{
    /* ... */
    cont: ;
} while (expression);

for (expr1; expr2; expr3) {
     /* ... */
     cont: ;
}

a continue, iç içe geçmiş bir yineleme deyiminde yer almayan ile aynıdır goto cont.

breakİfadesi bir sona erdirmek için kullanılır fordöngü, whiledöngü, dodöngü veya switchdeyimi. Kontrol, sonlandırılan deyimin ardından deyime geçer.

Bir işlev, deyimle çağırana geri döner return. Bir returnifadenin ardından değer, işlevin değeri olarak arayan kişiye döndürülür. İşlevin sonuyla karşılaşmak, returnifadesi olmayan a ile eşdeğerdir . Bu durumda, işlevin bir değer döndürdüğü bildirilirse ve çağıran, döndürülen değeri kullanmaya çalışırsa, sonuç tanımsızdır.

Bir etiketin adresini saklama

GCC , C dilini &&bir etiketin adresini döndüren tekli bir operatörle genişletir . Bu adres bir void*değişken tipinde saklanabilir ve daha sonra bir gototalimatta kullanılabilir. Örneğin, aşağıdakiler "hi "sonsuz bir döngüde yazdırılır :

    void *ptr = &&J1;

J1: printf("hi ");
    goto *ptr;

Bu özellik, bir atlama tablosu uygulamak için kullanılabilir .

Fonksiyonlar

Sözdizimi

AC işlev tanımı, bir dönüş türünden ( voiddeğer döndürülmezse), benzersiz bir ad, parantez içindeki bir parametre listesi ve çeşitli ifadelerden oluşur:

<return-type> functionName( <parameter-list> )
{
    <statements>
    return <expression of type return-type>;
}

Geri voiddönüşü olmayan tipte bir fonksiyon en az bir returndeyim içermelidir . Parametreler, <parameter-list>virgülle ayrılmış parametre bildirimleri listesi tarafından verilir , listedeki her öğe bir veri türü ve ardından bir tanımlayıcıdır: <data-type> <variable-identifier>, <data-type> <variable-identifier>, ....

Parametre yoksa <parameter-list>boş bırakılabilir veya isteğe bağlı olarak tek kelime ile belirtilebilir void.

...Bir veri türü ve değişken tanımlayıcısı yerine son parametre olarak anahtar sözcüğü sağlayarak, bir işlevi değişken sayıda parametre almak olarak tanımlamak mümkündür . Bunu yapan yaygın olarak kullanılan bir işlev printf, bildirime sahip standart kitaplık işlevidir :

int printf (const char*, ...);

Bu parametrelerin manipülasyonu, standart kütüphane başlığındaki rutinler kullanılarak yapılabilir <stdarg.h>.

İşlev İşaretçileri

Bir işleve işaretçi aşağıdaki gibi bildirilebilir:

<return-type> (*<function-name>)(<parameter-list>);

Aşağıdaki program, toplama ve çıkarma arasında seçim yapmak için bir işlev işaretçisinin kullanımını gösterir :

#include <stdio.h>

int (*operation)(int x, int y);

int add(int x, int y)
{
    return x + y;
}

int subtract(int x, int y)
{
    return x - y;
}

int main(int argc, char* args[])
{
   int  foo = 1, bar = 1;

   operation = add;
   printf("%d + %d = %d\n", foo, bar, operation(foo, bar));
   operation = subtract;
   printf("%d - %d = %d\n", foo, bar, operation(foo, bar));
   return 0;
}

Küresel yapı

Ön işlemeden sonra, en üst düzeyde bir C programı , dosya kapsamındaki bir dizi bildirimden oluşur. Bunlar, ayrı ayrı derlenebilen birkaç ayrı kaynak dosyaya bölünebilir; daha sonra ortaya çıkan nesne modülleri, yürütülebilir bir görüntü üretmek için uygulama tarafından sağlanan çalışma zamanı destek modülleriyle birlikte bağlanır .

Bildirimler, işlevleri , değişkenleri ve türleri tanıtır . C işlevleri, Fortran'ın alt rutinlerine veya Pascal'ın prosedürlerine benzer .

Bir tanım bildiriminin bir özel bir türüdür. Değişken bir tanım, depolamayı bir kenara bırakır ve muhtemelen onu başlatır, bir işlev tanımı gövdesini sağlar.

Tüm standart kitaplık işlevlerini sağlayan bir C uygulamasına barındırılan uygulama denir . Barındırılan uygulamalar için yazılan programların main, bir program yürütülmeye başladığında çağrılan ilk işlev olan adlı özel bir işlevi tanımlaması gerekir .

Barındırılan uygulamalar main, aşağıdaki prototiplerden birinin ardından tanımlanması gereken işlevi çağırarak program yürütmeyi başlatır :

int main() {...}
int main(void) {...}
int main(int argc, char *argv[]) {...}
int main(int argc, char **argv) {...}

İlk iki tanım eşdeğerdir (ve her ikisi de C++ ile uyumludur). Hangisinin kullanılacağı muhtemelen bireysel tercihe bağlıdır (mevcut C standardı iki main()ve iki örneği içerir main(void), ancak taslak C++ standardı kullanır main()). main(olması gereken int) dönüş değeri , ana bilgisayar ortamına döndürülen sonlandırma durumu olarak işlev görür .

C standardı, dönüş değerlerini 0ve EXIT_SUCCESSbaşarıyı gösteren ve başarısızlığı gösteren olarak tanımlar EXIT_FAILURE. ( EXIT_SUCCESSve EXIT_FAILUREiçinde tanımlanmıştır <stdlib.h>). Diğer dönüş değerlerinin uygulama tanımlı anlamları vardır; örneğin, Linux altında , bir sinyal tarafından öldürülen bir program , sinyalin sayısal değeri artı 128'in bir dönüş kodunu verir.

Minimal doğru bir C programı, mainhiçbir argüman almayan ve hiçbir şey yapmayan boş bir rutinden oluşur :

int main(void){}

Hiçbir returnifade bulunmadığından main, çıkışta 0 döndürür. (Bu, C99'da sunulan ve yalnızca için geçerli olan özel bir durum özelliğidir main.)

mainİşlev genellikle işini gerçekleştirmek yardımcı olmak için diğer işlevleri arayacak.

Bazı uygulamalar, genellikle bir işletim sistemiyle kullanılmak üzere tasarlanmadıkları için barındırılmaz . Bu tür uygulamalara C standardında bağımsız denir . Bağımsız bir uygulama, program başlatmayı nasıl ele alacağını belirtmekte serbesttir; özellikle bir mainişlevi tanımlamak için bir programa ihtiyaç duymaz .

Fonksiyonlar programcı tarafından yazılabilir veya mevcut kütüphaneler tarafından sağlanabilir. İkincisi için arabirimler genellikle - #include ön işleme yönergesiyle birlikte - başlık dosyaları dahil edilerek bildirilir ve kitaplık nesneleri son yürütülebilir görüntüye bağlanır. gibi belirli kitaplık işlevleri printfC standardı tarafından tanımlanır; bunlara standart kitaplık işlevleri denir .

Bir işlev, arayana bir değer döndürebilir (genellikle başka bir C işlevi veya işlev için barındırma ortamı main). printfFonksiyonu birçok karakter baskılı nasıl getiriler yukarıda belirtilen, ancak bu değer genellikle göz ardı edilir.

argüman geçişi

C'de, argümanlar fonksiyonlara değere göre iletilirken , diğer diller değişkenleri referans olarak iletebilir . Bu, alma işlevinin değerlerin kopyalarını aldığı ve orijinal değişkenleri değiştirmenin doğrudan bir yolu olmadığı anlamına gelir. Bir işlevin başka bir işlevden geçirilen bir değişkeni değiştirmesi için, arayan kişinin adresini ( ona bir işaretçi ) iletmesi gerekir , bu daha sonra alıcı işlevde referansı kaldırılabilir. Daha fazla bilgi için İşaretçiler'e bakın .

void incInt(int *y)
{
    (*y)++;  // Increase the value of 'x', in 'main' below, by one
}

int main(void)
{
    int x = 0;
    incInt(&x);  // pass a reference to the var 'x'
    return 0;
}

scanf işlevi aynı şekilde çalışır:

int x;
scanf("%d", &x);

Bir işleve düzenlenebilir bir işaretçi iletmek için (örneğin, çağrılan koda tahsis edilmiş bir diziyi döndürmek amacıyla), o işaretçiye bir işaretçi iletmeniz gerekir: adresi.

#include <stdio.h>
#include <stdlib.h>

void allocate_array(int ** const a_p, const int A) {
/* 
 allocate array of A ints
 assigning to *a_p alters the 'a' in main()
*/
    *a_p = malloc(sizeof(int) * A); 
}

int main(void) {
    int * a; /* create a pointer to one or more ints, this will be the array */

 /* pass the address of 'a' */
    allocate_array(&a, 42);

/* 'a' is now an array of length 42 and can be manipulated and freed here */

    free(a);
    return 0;
}

Parametre int **a_p, bu durumda ana işlevde tanımlanan intişaretçinin adresi olan bir işaretçiye bir işaretçidir . p

dizi parametreleri

Dizi türünün işlev parametreleri, ilk bakışta C'nin değere göre geçiş kuralının bir istisnası gibi görünebilir. Aşağıdaki program 1 değil 2 yazdıracaktır:

#include <stdio.h>

void setArray(int array[], int index, int value)
{
    array[index] = value;
}

int main(void)
{
    int a[1] = {1};
    setArray(a, 0, 2);
    printf ("a[0]=%d\n", a[0]);
    return 0;
}

Ancak bu davranışın farklı bir nedeni vardır. Aslında, bir dizi türüyle bildirilen bir işlev parametresi, bir işaretçi olarak bildirilen bir parametre gibi değerlendirilir. Yani, önceki beyanı setArrayaşağıdakine eşdeğerdir:

void setArray(int *array, int index, int value)

Aynı zamanda, Cı değerine neden ifadelerde dizilerin kullanımı için kurallar aarama için setArraydizinin ilk elemanı için bir işaretçi dönüştürülecek a. Bu nedenle, aslında bu, dizinin içeriğine göre değil, değere göre iletilen dizinin ilk öğesinin adresi olduğu uyarısıyla, yine de bir değere göre geçiş örneğidir.

Çeşitli

Ayrılmış anahtar kelimeler

Aşağıdaki kelimeler saklıdır ve tanımlayıcı olarak kullanılamaz:

Uygulamalar, gibi diğer anahtar kelimeleri ayırabilir asm, ancak uygulamalar tipik olarak bir veya iki alt çizgi ile başlayan standart olmayan anahtar kelimeler sağlar.

Büyük küçük harf duyarlılığı

C tanımlayıcıları büyük/küçük harf duyarlıdır (örneğin, foo, FOO, ve Foofarklı nesnelerin adlarıdır). Bazı bağlayıcılar, harici tanımlayıcıları tek bir duruma eşleyebilir, ancak bu çoğu modern bağlayıcıda nadirdir.

Yorumlar

Belirteçle başlayan metin /*, yorum olarak kabul edilir ve yok sayılır. Yorum bir sonrakinde sona eriyor */; ifadeler içinde oluşabilir ve birden çok satıra yayılabilir. Yorum sonlandırıcının yanlışlıkla atlanması, bir sonraki yorumun uygun şekilde oluşturulmuş yorum sonlandırıcısının ilk yorumu sonlandırmak için kullanılacağı ve yorumlar arasındaki tüm kodların bir yorum olarak kabul edileceği için sorunludur. C tarzı yorumlar iç içe geçmez; yani, yanlışlıkla bir yorumun içine yorum yerleştirmek, istenmeyen sonuçlara yol açar:

/*
This line will be ignored.
/*
A compiler warning may be produced here. These lines will also be ignored.
The comment opening token above did not start a new comment,
and the comment closing token below will close the comment begun on line 1.
*/
This line and the line below it will not be ignored. Both will likely produce compile errors.
*/

C++ stili satır yorumları ile başlar //ve satırın sonuna kadar uzanır. Bu yorum tarzı BCPL'de ortaya çıktı ve C99'da geçerli C sözdizimi oldu ; orijinal K&R C'de veya ANSI C'de mevcut değildir :

// this line will be ignored by the compiler

/* these lines
   will be ignored
   by the compiler */

x = *p/*q;  /* this comment starts after the 'p' */

Komut satırı bağımsız değişkenleri

Parametreler bir verilen komut hattı komut satırı bağımsız değişkenleri sayımı - iki önceden değişkenli bir C programa geçirilir argcve tek tek bağımsız değişken olarak karakter dizileri işaretçi dizi argv. Yani komut:

myFilt p1 p2 p3

şöyle bir şeyle sonuçlanır:

m y F ben ben T \0 P 1 \0 P 2 \0 P 3 \0
argüman[0] argv[1] argv[2] argv[3]

Tek tek dizeler bitişik karakter dizileri olsa da, dizelerin bitişik bir grup olarak saklanacağının garantisi yoktur.

Programın adı, argv[0], tanı mesajlarını yazdırırken veya bir ikili programın birden çok amaca hizmet etmesini sağlamak için yararlı olabilir. Parametrelerin tek tek değerler ile erişilebilir argv[1], argv[2]ve argv[3]aşağıdaki programa gösterildiği gibi,:

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("argc\t= %d\n", argc);
    for (int i = 0; i < argc; i++)
        printf("argv[%i]\t= %s\n", i, argv[i]);
}

Değerlendirme sırası

Herhangi bir makul karmaşık ifadede, ifade bölümlerini değerlendirmek sırayla için bir seçenek ortaya çıkmaktadır: amacıyla değerlendirilebilir , , , , ya da sırayla , , , . Biçimsel olarak, uyumlu bir C derleyicisi, ifadeleri sıra noktaları arasında herhangi bir sırada değerlendirebilir (bu, derleyicinin bir miktar optimizasyon yapmasına izin verir). Sıra noktaları şu şekilde tanımlanır: (1+1)+(3+3)(1+1)+(3+3)(2)+(3+3)(2)+(6)(8)(1+1)+(3+3)(1+1)+(6)(2)+(6)(8)

  • İfade noktalı virgülle biter .
  • Dizileme operatörü : virgülle. Ancak, işlev bağımsız değişkenlerini sınırlayan virgüller sıra noktaları değildir.
  • Kısa devre operatörleri : mantıksal ve ( &&, okunabilir ve daha sonra ) ve mantıksal ya da ( ||okunabilir, ya da başka ).
  • Üçlü operatör ( ?:): Bu Operatör daha sonra ilk değerine dayalı ikinci veya üçüncü (asla ikisi de) ilk olarak birinci alt ifadeyi değerlendirir ve.
  • Bir işlev çağrısına giriş ve çıkış (ancak bağımsız değişkenlerin değerlendirmeleri arasında değil).

Bir dizi noktasından önceki ifadeler, her zaman bir dizi noktasından sonraki ifadelerden önce değerlendirilir. Kısa devre değerlendirmesi durumunda, birinci ifadenin sonucuna bağlı olarak ikinci ifade değerlendirilemeyebilir. Örneğin, ifadede , ilk argüman sıfırdan farklı (doğru) olarak değerlendirilirse, tüm ifadenin sonucu true dışında bir şey olamaz, bu nedenle değerlendirilmez. Benzer şekilde, ifadede , ilk argüman sıfır (yanlış) olarak değerlendirilirse, tüm ifadenin sonucu false'tan başka bir şey olamaz, bu nedenle değerlendirilmez. (a() || b())b()(a() && b())b()

Bir işlev çağrısına ilişkin argümanlar, işlev girildiği zamana göre değerlendirildikleri sürece herhangi bir sırada değerlendirilebilir. Örneğin, aşağıdaki ifade tanımsız davranışa sahiptir:

 printf("%s %s\n", argv[i = 0], argv[++i]);

tanımsız davranış

C standardının (C'ye özgü olmayan) bir yönü, belirli kodun davranışının "tanımsız" olduğu söylenmesidir. Pratikte bu, bu koddan üretilen programın, programcının amaçladığı gibi çalışmaktan her çalıştırıldığında çökmesine kadar her şeyi yapabileceği anlamına gelir.

Örneğin, aşağıdaki kod tanımsız davranış üretir, çünkü b değişkeni , araya giren bir sıra noktası olmadan birden fazla kez değiştirilir:

#include <stdio.h>

int main(void)
{
    int b = 1;
    int a = b++ + b++;
    printf("%d\n", a);
}

Modifikasyonları arasında dizi nokta olduğu için , b de " b ++ + b ++", bir belirsiz açıklamada ortaya çıkan, fazla bir sırayla değerlendirme adımları gerçekleştirmek mümkündür. Bu, açık bir davranışı zorlamak için bir sıra noktası eklemek üzere kodu yeniden yazarak düzeltilebilir, örneğin:

a = b++;
a += b++;

Ayrıca bakınız

Referanslar

Genel

Dış bağlantılar