C karakter dizisi başlatma


119

Aşağıdaki şekillerde başlattıktan sonra char dizisinde ne olacağından emin değilim.

1. char buf[10] = "";
2. char buf[10] = " ";
3.char buf[10] = "a";

Durum 2 için, sanırım buf[0]olmalı ' ', buf[1]olmalı '\0've gelen buf[2]etmek buf[9]rastgele içerik olacaktır. Durumda 3 için, sanırım buf[0]olmalı 'a', buf[1]olmalı '\ 0' ve gelen buf[2]etmek buf[9]rastgele içerik olacaktır.

Bu doğru mu?

Ve 1. durum için, içinde ne olacak buf? buf[0] == '\0've gelen buf[1]için buf[9]rasgele içerik olacak?


2
Derleyicim (düzeltilmiş) kodunuzu kabul etmiyor: "dizi türü 'char [10]' atanamaz".
Martin R

@MartinR şimdi işe yarayacak ...
lkkeepmoving

1
@lkkeepmoving: char buf[10]; buf = "a";yok değil derlemek. - Lütfen önce deneyin ve ardından gerçek kodunuzu kopyalayıp soruya yapıştırın . Bu, sizin ve sorunuzun tüm okuyucuları için çok fazla çalışma tasarrufu sağlar.
Martin R

@MartinR Bunun için üzgünüm. Buf [] 'i ikinci olarak atayabileceğimi düşündüm ama öyle görünüyor. Şimdi kod çalışıyor.
lkkeepmoving

Yanıtlar:


222

Bu, bir diziyi nasıl başlatacağınız değil, bunun için:

  1. İlk beyan:

    char buf[10] = "";

    eşdeğerdir

    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  2. İkinci beyan:

    char buf[10] = " ";

    eşdeğerdir

    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
  3. Üçüncü beyan:

    char buf[10] = "a";

    eşdeğerdir

    char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};

Gördüğünüz gibi rastgele içerik yok: Daha az sayıda başlatıcı varsa, dizinin geri kalanı ile başlatılır 0. Dizi bir işlev içinde bildirilse bile durum budur.


47
Soruyu soran kişinin iyiliği için, C standardının, kalan öğeler için (derleyici tarafından) kısmen tamamlanmış herhangi bir dizi başlatmanın sıfır ile doldurulmasını gerektirdiğine işaret etmeye değer. Bu sadece tüm veri türleri için geçerli değil char.
paddy

4
@ouah neden buf [] sonunda '\ 0' yok?
lkkeepmoving

14
@lkkeepmoving 0ve '\0aynı değere sahip.
ouah

1
@lkkeepmoving Başlatma ve atama iki farklı canavardır, bu nedenle C bir karakter dizisi için başlatıcı olarak bir dizge sağlamanıza izin verir, ancak dizi atamalarını yasaklar (ouah'ın söylediği gibi).
Lorenzo Donati - Codidact.com

3
@Pacerier char buff[3] = "abcdefghijkl";geçersiz.char p3[5] = "String";ayrıca geçersizdir. char p[6] = "String";geçerlidir ve ile aynıdır char p[6] = {'S', 't', 'r', 'i', 'n', 'g'};.
ouah

28

Düzenleme: OP (veya bir editör), bu cevabı verdikten sonra bir noktada orijinal sorudaki bazı tek alıntıları sessizce çift tırnak işareti yapacak şekilde değiştirdi.

Kodunuz derleyici hatalarına neden olacaktır. İlk kod parçanız:

char buf[10] ; buf = ''

iki kat yasadışı. İlk olarak, C'de boş diye bir şey yoktur char. Boş bir dizeyi belirtmek için çift tırnak kullanabilirsiniz, örneğin:

char* buf = ""; 

Bu size bir NULdizgeye bir işaretçi verecektir , yani sadece içinde NULkarakter bulunan tek karakterli bir dizge . Ancak içinde hiçbir şey olmayan tek tırnakları kullanamazsınız - bu tanımsızdır. Belirttiğiniz gerekiyorsa NULkarakteri, bunu belirtmek zorunda:

char buf = '\0';

Ters eğik çizgi karakterden ayırmak için gereklidir '0'.

char buf = 0;

aynı şeyi başarıyor, ancak ilkini okumak için biraz daha az belirsiz olduğunu düşünüyorum.

İkinci olarak, dizileri tanımlandıktan sonra başlatamazsınız.

char buf[10];

diziyi bildirir ve tanımlar. Dizi tanımlayıcısı bufartık bellekte bir adres ve nerede olduğunu değiştiremezsiniz.buf atama yoluyla işaret . Yani

buf =     // anything on RHS

yasa dışıdır. İkinci ve üçüncü kod parçalarınız bu nedenle yasa dışıdır.

Bir diziyi başlatmak için, tanım anında yapmanız gerekir:

char buf [10] = ' ';

size ilk karakterin boşluk olduğu 10 karakterlik bir dizi verecektir '\040' ve geri kalan varlık NUL, yani '\0'. Bir dizi bir başlatıcı ile bildirildiğinde ve tanımlandığında, belirtilen başlangıç ​​değerlerine sahip olanları geçen dizi öğeleri (varsa) otomatik olarak doldurulur0 . Herhangi bir "rastgele içerik" olmayacak.

Diziyi bildirir ve tanımlarsanız ancak aşağıdaki gibi başlatmazsanız:

char buf [10];

tüm unsurlarda rastgele içeriğe sahip olacaksınız.


"Bir diziyi başlatmak için, onu tanım anında yapmanız gerekir ..." Bu ve aşağıdaki satır, bunu kabul edilen cevaptan daha iyi yapar.
Laurie Stearn

26
  1. Bunlar eşdeğerdir

    char buf[10] = "";
    char buf[10] = {0};
    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  2. Bunlar eşdeğerdir

    char buf[10] = " ";
    char buf[10] = {' '};
    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
  3. Bunlar eşdeğerdir

    char buf[10] = "a";
    char buf[10] = {'a'};
    char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};

8

C11 standart taslağı n1570 6.7.9'un başlatılmasının ilgili kısmı şunları söylüyor:

14 Bir karakter türü dizisi, isteğe bağlı olarak kaşlı ayraçlar içine alınmış bir karakter dizgisi veya UTF-8 dizesi ile başlatılabilir. Dize değişmezinin ardışık baytları (yer varsa veya dizi bilinmeyen boyuttaysa sonlandırıcı boş karakter dahil) dizinin öğelerini başlatır.

ve

21 Küme ayracı ile çevrili bir listede, bir toplamın öğeleri veya üyeleri olduğundan daha az başlatıcı varsa veya dizideki öğelerden, bilinen büyüklükte bir diziyi başlatmak için kullanılan bir dize değişmezinde daha az karakter varsa, toplamın geri kalanı Statik depolama süresi olan nesnelerle aynı şekilde başlatılmalıdır .

Böylece, yeterli alan varsa '\ 0' eklenir ve kalan karakterler, static char c;bir işlev içinde başlatılacak değerle başlatılır.

En sonunda,

10 Otomatik depolama süresi olan bir nesne açık bir şekilde başlatılmazsa, değeri belirsizdir. Statik veya iş parçacığı depolama süresi olan bir nesne açıkça başlatılmadıysa, o zaman:

[-]

  • aritmetik tipe sahipse, (pozitif veya işaretsiz) sıfır olarak başlatılır;

[-]

Böylece, chararitmetik bir tür olarak, dizinin geri kalanının da sıfırlarla başlatılması garanti edilir.


3

İlginçtir ki, programın herhangi bir anında herhangi bir şekilde dizileri başlatmak mümkündür, eğer a structveya union.

Örnek program:

#include <stdio.h>

struct ccont
{
  char array[32];
};

struct icont
{
  int array[32];
};

int main()
{
  int  cnt;
  char carray[32] = { 'A', 66, 6*11+1 };    // 'A', 'B', 'C', '\0', '\0', ...
  int  iarray[32] = { 67, 42, 25 };

  struct ccont cc = { 0 };
  struct icont ic = { 0 };

  /*  these don't work
  carray = { [0]=1 };           // expected expression before '{' token
  carray = { [0 ... 31]=1 };    // (likewise)
  carray = (char[32]){ [0]=3 }; // incompatible types when assigning to type 'char[32]' from type 'char *'
  iarray = (int[32]){ 1 };      // (likewise, but s/char/int/g)
  */

  // but these perfectly work...
  cc = (struct ccont){ .array='a' };        // 'a', '\0', '\0', '\0', ...
  // the following is a gcc extension, 
  cc = (struct ccont){ .array={ [0 ... 2]='a' } };  // 'a', 'a', 'a', '\0', '\0', ...
  ic = (struct icont){ .array={ 42,67 } };      // 42, 67, 0, 0, 0, ...
  // index ranges can overlap, the latter override the former
  // (no compiler warning with -Wall -Wextra)
  ic = (struct icont){ .array={ [0 ... 1]=42, [1 ... 2]=67 } }; // 42, 67, 67, 0, 0, ...

  for (cnt=0; cnt<5; cnt++)
    printf("%2d %c %2d %c\n",iarray[cnt], carray[cnt],ic.array[cnt],cc.array[cnt]);

  return 0;
}

1

Emin değilim ama genellikle bir diziyi "" olarak başlatırım, bu durumda dizenin boş sonu hakkında endişelenmeme gerek yok.

main() {
    void something(char[]);
    char s[100] = "";

    something(s);
    printf("%s", s);
}

void something(char s[]) {
    // ... do something, pass the output to s
    // no need to add s[i] = '\0'; because all unused slot is already set to '\0'
}

Örtük int kuralını gerçekten kullanmamalısınız . İçin bir tür belirtmelisiniz main()(ve ayrıca kullanmalısınız void, yani int main(void) { ... }. C99 bu kuraldan kurtulmuştur, bu nedenle bu kod C99 ve sonrası için derlenmeyecektir. Burada dikkat edilmesi gereken diğer bir şey , C99 ile başlamaktırreturn . ana, ana return 0;ekranın }sonuna otomatik olarak yerleştirilmiş / ima edilmiş bir var. Yalnızca C99'dan önce çalışan örtük int kuralı kullanıyorsunuz, returnancak yalnızca C99 ve sonrasında çalışan örtükten yararlanıyorsunuz ; bu ikisi açıkça çelişkili .
RastaJedi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.