Malloc'un sonucunu atar mıyım?


2408

Gelen bu soruya , birisi bir önerilen yorumun ı gerektiğini değil sonucunu döküm malloc, yani

int *sieve = malloc(sizeof(int) * length);

ziyade:

int *sieve = (int *) malloc(sizeof(int) * length);

Neden böyle olsun?


222
Ayrıca elek = malloc (elek * elek * uzunluk) yazmak daha sürdürülebilir;
William Pursell


3
Buradaki cevaplar tek taraflı bir mayın tarlası. Cevap, duruma bağlı". Programın çalışması için gerekli bir şey değildir. Bununla birlikte, bazı kodlama standartları bunu gerektirir ... Örneğin, bkz. CERT C Kodlama Standardı
Dr. Person Person II

Tuhaf bir şekilde, herkes oyuncu seçmediğinizi kabul eder NULL. (muhtemelen bu yüzden C ++ tanıtıldı nullptr: C ++ herhangi bir örtülü işaretçi yayınına izin vermez)
Sapphire_Brick

Yapabilirsin ama yapmana gerek yok. Ancak C ++ ile yapmanız gerekir.
Asadefa

Yanıtlar:


2217

Hayır ; Eğer yok çünkü sonuç dökme:

  • Bu durumda void *otomatik olarak ve güvenli bir şekilde diğer işaretçi türlerine yükseltildiği için gereksizdir .
  • Koda karmaşa ekler, dökümlerin okunması çok kolay değildir (özellikle işaretçi türü uzunsa).
  • Kendinizi tekrarlamanızı sağlar, bu genellikle kötüdür.
  • Eklemeyi unuttuysanız bir hatayı gizleyebilir <stdlib.h>. Bu, çökmelere neden olabilir (veya daha da kötüsü, kodun tamamen farklı bir bölümünde ileride bir çökmeye neden olmaz ). İşaretçiler ve tamsayılar farklı boyutlarda olursa ne olacağını düşünün; yayınlayarak bir uyarıyı gizlersiniz ve iade ettiğiniz adresin bitlerini kaybedebilirsiniz. Not: C99'dan itibaren örtük işlevler C'den gitmiştir ve kayıt dışı işlevlerin geri döndüğü otomatik varsayımı olmadığından bu nokta artık geçerli değildir int.

Bir açıklama olarak, not dedim, değil "sen yok "Eğer döküm yok" ihtiyaç döküm için". Bence, doğru anlasanız bile oyuncu kadrosunu dahil etmek bir başarısızlık. Bunu yapmanın hiçbir faydası yoktur, ancak bir dizi potansiyel risk vardır ve oyuncu kadrosu dahil olmak, riskler hakkında bilmediğinizi gösterir.

Ayrıca, yorumcuların belirttiği gibi, yukarıdaki C ++ değil düz C hakkında konuştuğuna dikkat edin. C ve C ++ 'a ayrı diller olarak inanıyorum.

Daha fazla eklemek için kodunuz, inthatalara neden olabilecek tür bilgilerini ( ) gereksiz yere tekrarlar . İkisini birlikte "kilitlemek" için dönüş değerini saklamak için kullanılan işaretçiye atıfta bulunmak daha iyidir:

int *sieve = malloc(length * sizeof *sieve);

Bu ayrıca lengthdaha fazla görünürlük için ön tarafa doğru hareket eder ve gereksiz parantezleri sizeof; onlar sadece ihtiyaç vardır argüman bir tür adı olduğunda. Birçok insan bunu bilmiyor gibi görünüyor (veya görmezden geliyor), bu da kodlarını daha ayrıntılı hale getiriyor. Unutmayın: sizeofbir işlev değildir! :)


Taşırken lengthöne olabilecek bazı nadir durumlarda görünürlüğünü artırmak, bir de genel durumda, olarak ifade yazmak daha iyi olması gerektiğini dikkat etmelidir:

int *sieve = malloc(sizeof *sieve * length);

İlkini tutmak, sizeofbu durumda, çarpma en azından size_tmatematik ile yapılmasını sağlar .

Karşılaştırma: malloc(sizeof *sieve * length * width)vs malloc(length * width * sizeof *sieve)ikinci taşabilir length * widthzaman widthve lengthdaha küçük türleridir size_t.


21
Lütfen cevabı güncelleyin. Oyuncular artık tehlikeli değil ve kendini tekrarlamak mutlaka kötü bir şey değil (fazlalık hataları yakalamaya yardımcı olabilir).
n. 'zamirler' m.

11
Derleyiciler değişti. Güncel bir derleyici, eksik malloc beyanı konusunda sizi uyaracaktır.
n. 'zamirler' m.

55
@nm Tamam. Burada okuyan herkesin belirli bir derleyiciye sahip olduğunu varsaymanın kötü olduğunu düşünüyorum. Ayrıca, C11'in tüm "örtük fonksiyon" kavramı ortadan kalktığı için bunu bilmiyordum. Yine de anlamsız bir oyuncu eklemenin amacını görmüyorum. int x = (int) 12;Sadece işleri netleştirmek için mi yapıyorsunuz ?
gevşeyin

22
@nm açıkça bir geçersiz işaretçi "bir hatayı çözmeye" yardımcı olursa, tanımlanamayan davranışla daha büyük bir olasılıkla karşılaştınız. Ve bir gün, soğuk bir kış akşamında, GitHub sayfanızı kullanıcıların burunlarından uçan şeytanlardan şikayet eden sorun raporları ile dolu bulmak için işten eve döneceksiniz
Braden Best

12
@ unwind Sana katılıyorum bile, (int)12karşılaştırılamaz. 12 olan bir int, döküm basitçe hiçbir şey yapmaz. Arasında dönüş_değeri malloc()IS void *değil, işaretçi tipi döküm. (Değilse void *. Benzetme So (int)12olacağını (void*)malloc(…)kimse tartışıyor ne.)
Amin Negm-Awad

376

C'de, dönüş değerini kullanmanıza gerek yoktur malloc. Tarafından döndürülen boşluk işaretçisi otomatik olarak mallocdoğru türe dönüştürülür. Ancak, kodunuzun bir C ++ derleyicisi ile derlenmesini istiyorsanız, bir döküm gerekir. Topluluk arasında tercih edilen bir alternatif aşağıdakileri kullanmaktır:

int *sieve = malloc(sizeof *sieve * length);

bu da türünü değiştirirseniz ifadenin sağ tarafını değiştirmek konusunda endişelenmenize gerek kalmaz sieve.

İnsanların işaret ettiği gibi, yayınlar kötüdür. Özellikle işaretçi atışları.


71
@MAKZ Bir değişken malloc(length * sizeof *sieve)gibi göründüğünü iddia ediyorum sizeof- bu yüzden malloc(length * sizeof(*sieve))daha okunabilir olduğunu düşünüyorum .
Michael Anderson

21
Ve malloc(length * (sizeof *sieve))daha okunabilir. BENİM NACİZANE FİKRİME GÖRE.
Toby Speight

19
@Michael Anderson ()sorunu bir kenara, önerilen stil sırayla değiştiğini unutmayın., Bu durumda ilk çarpım en az matematik ile yapılır sigorta tutarı gibi length*width, sayım hesaplanır zaman düşünün . Karşılaştırma VS. - 2 taşabilir zaman o küçük türleridir . sizeofsize_tmalloc(sizeof( *ptr) * length * width)malloc(length * width * sizeof (*ptr))length*widthwidth,lengthsize_t
chux - Monica

3
@chux belli değil, ancak cevabım yorumumun daha az ilgili olması için düzenlendi - orijinal önerimalloc(sizeof *sieve * length)
Michael Anderson

12
C C ++ değildir. Nihayetinde kafa karışıklığı ve üzüntüye yol açacaktır. C ++ kullanıyorsanız, C tarzı bir döküm de kötüdür (çok eski bir C ++ derleyicisi kullanmadığınız sürece). Ve static_cast>()(veya reinterpret_cast<>()) C'nin herhangi bir lehçesi ile uyumlu değildir
David C.

349

Sen yok , dökme, çünkü:

  • Kodunuzu C ve C ++ arasında daha taşınabilir hale getirir ve SO deneyiminin gösterdiği gibi, birçok programcı gerçekten C ++ (veya C artı yerel derleyici uzantıları) yazarken C'de yazdıklarını iddia eder.
  • Aksi halde bir hata gizleyebilirsiniz : notu yazmak için zaman kafa karıştırıcı tüm SO örnekleri type *karşı type **.
  • Sizi #includeuygun bir başlık dosyasında başarısız olduğunuzu fark etmenizi engellediği fikri , ağaçlar için ormanı özlüyor . "Derleyiciden prototipleri görmekten şikayet etmesini istemediğiniz için endişelenmeyin - bu sinir bozucu stdlib.h hatırlanması gereken GERÇEK önemli şey!"
  • Ekstra bilişsel bir çapraz kontrolü zorlar . İstenen (iddia edilen) türü, değişkenin ham boyutu için yaptığınız aritmetiğin hemen yanına koyar. Bahse girerim, malloc()bir döküm olduğunda hataların çok daha hızlı yakalandığını gösteren bir SO çalışması yapabilirsiniz . İddialarda olduğu gibi, niyeti ortaya çıkaran ek açıklamalar hataları azaltır.
  • Kendinizi makinenin kontrol edebileceği bir şekilde tekrarlamak genellikle harika bir fikirdir. Aslında, bir iddia budur ve bu döküm kullanımı bir iddiadır. İddialar hala kodları düzeltmek için sahip olduğumuz en genel tekniktir, çünkü Turing yıllarca önce bu fikri ortaya attı.

39
@ulidtko Bilmiyorsanız, hem C hem de C ++ olarak derlenen kod yazmak mümkündür. Aslında çoğu başlık dosyası bu şekildedir ve genellikle kod içerir (makrolar ve satır içi işlevler). Her ikisinde de derlenecek bir .c/ .cppdosyaya sahip olmak çok yararlı değildir, ancak bir örnek throwC ++ derleyicisiyle return -1;derlendiğinde (ancak C derleyicisi ile derlendiğinde veya başka bir şekilde) C ++ desteği ekler .
hyde

37
Birisi bir başlıkta satır içi malloc çağrıları olsaydı etkilenmezdim, #ifdef __cplusplus ve extern "C" {} bu iş içindi, fazladan kastlar eklemiyorlar.
paulm

15
! Eh, nokta 1 kullanırsanız C = C beri ++, diğer noktaları da önemsiz olduğu, alakasız değişkeni sizin de malloc: çağrı char **foo = malloc(3*sizeof(*foo));eğer oldukça dolu geçirmez: Char işaretçiler 3 işaretçileri. sonra döngü ve yapmak foo[i] = calloc(101, sizeof(*(foo[i])));. Düzgün sıfıra sıfırlanmış 101 karakter dizisini ayırın. Döküm gerekmez. bu konuda beyanı unsigned charveya başka bir türü değiştirin ve hala
iyisiniz

34
Ne zaman öğrendim anladım, işte geliyor! Harika bir cevap. Onun StackOverflow ilk kez ben iki zıt cevap +1 + 1! +1 Hayır, yayın yapmıyorsunuz ve +1 Evet, yayın yapıyorsunuz! LOL. Siz harikasınız. Ve ben ve öğrencilerim için, aklımı yaptım: Oyuncular yapıyorum. Öğrencilerin yaptıkları hatalar döküm yaparken daha kolay fark edilir.
Dr Beco

15
@Leushenko: Kendinizi makine veya yerel denetim tarafından onaylanamayacak şekilde tekrarlamak kötüdür. Kendinizi bu yollarla doğrulanabilecek şekilde tekrarlamak daha az kötüdür. Verilen struct Zebra *p; ... p=malloc(sizeof struct Zebra);, malloc, p'nin türü hakkında bilgi kopyalamaktan kaçınamaz, ancak bir tür değiştiğinde, diğeri değişmediğinde ne derleyici ne de yerel kod denetimi herhangi bir sorunu algılamaz. Kodu değiştirin p=(struct Zebra*)malloc(sizeof struct Zebra);ve döküm türü eşleşmezse derleyici p
gıcırdayacak

170

Diğerlerinin belirttiği gibi, C için değil C ++ için gereklidir. C kodunuzu bir C ++ derleyicisiyle derleyeceğinizi düşünüyorsanız, herhangi bir nedenle, bir makro kullanabilirsiniz, örneğin:

#ifdef __cplusplus
# define NEW(type, count) ((type *)calloc(count, sizeof(type)))
#else
# define NEW(type, count) (calloc(count, sizeof(type)))
#endif

Bu şekilde yine de çok kompakt bir şekilde yazabilirsiniz:

int *sieve = NEW(int, 1);

ve C ve C ++ için derlenir.


17
Yine de bir makro kullandığınız için, neden newC ++ tanımında kullanmıyorsunuz ?
Hosam Aly

63
Çünkü bunu yapmak için bir sebep yok. Esas olarak bir C ++ derleyicisi ile derlenen C programları içindir. Eğer 'yeni' kullanacaksanız, elde ettiğiniz tek şey problemlerdir. Daha sonra ücretsiz bir makroya ihtiyacınız var. Ve bir diziyi serbest bırakmak için bir makroya, C'de bulunmayan bir farklılığa ihtiyacınız var.
quinmars

8
Hafızayı serbest bırakan siz değil, belki de kullandığınız bir C kütüphanesi, vb. Bahsetmiyorum. Herhangi bir kazanç olmadan birçok olası sorun.
quinmars

86
@Hosam: Evet, kesinlikle öyle. Eğer kullanırsanız newkullanmanız gerekir deleteve kullanmak eğer malloc()sen gerekir free(). Asla karıştırmayın.
Graeme Perrow

17
Eğer biri bu yaklaşımı benimseyecekse, NEWkaynak hiçbir zaman delete(veya DELETE) kullanılarak döndürülmediği için makroyu çağırmak muhtemelen kötü bir fikirdir, böylece kelime dağarcığınızı karıştırıyorsunuz. Bunun yerine, onu adlandırmak MALLOCveya daha doğrusu CALLOCbu durumda daha mantıklı olur.
mah

139

Gönderen Vikipedi :

Döküm avantajları

  • Dökümün dahil edilmesi bir C programının veya fonksiyonunun C ++ olarak derlenmesine izin verebilir.

  • Oyuncular, başlangıçta bir char * döndüren malloc'un 1989 öncesi sürümlerine izin veriyor.

  • Döküm, özellikle işaretçi malloc () çağrısından uzakta bildirilirse, hedef işaretçi türünün değişmesi durumunda geliştiricinin tür boyutlandırmasındaki tutarsızlıkları tanımlamasına yardımcı olabilir.

Döküm için dezavantajlar

  • ANSI C standardı altında, döküm yedeklidir.

  • Oyuncunun eklenmesi stdlib.h üstbilgisini ekleyememeyi maskeleyebilirmalloc için prototip bulunur. Malloc için bir prototip olmadığında standart, C derleyicisinin malloc'un bir int döndürdüğünü varsaymasını gerektirir. Yayın yoksa, işaretçiye bu tamsayı atandığında bir uyarı verilir; ancak, oyuncu kadrosunda bu uyarı üretilmez ve bir hata gizlenir. Belirli mimarilerde ve veri modellerinde (uzun ve işaretçilerin 64 bit ve int 32 bit olduğu 64 bit sistemlerde LP64 gibi), dolaylı olarak bildirilen malloc 32- döndürdüğü için bu hata aslında tanımsız davranışa neden olabilir. gerçekte tanımlanan işlev 64 bit değerini döndürür. Arama kurallarına ve bellek düzenine bağlı olarak, bu durum yığın parçalanmasına neden olabilir. Modern derleyicilerin bu sorunun fark edilmemesi daha az olasıdır, çünkü kayıt dışı bir işlevin kullanıldığına dair uyarılar düzenli olarak üretildiğinden, bir uyarı görüntülenmeye devam edecektir. Örneğin, GCC'nin varsayılan davranışı, kadronun mevcut olup olmadığına bakılmaksızın "yerleşik işlevin uyumsuz örtülü bildirimi" yazan bir uyarı göstermektir.

  • İşaretçinin türü bildiriminde değiştirilirse, malloc'un çağrıldığı ve yayınlandığı tüm satırların değiştirilmesi gerekebilir.

Her ne kadar döküm olmadan malloc tercih edilen yöntemdir ve en deneyimli programcılar seçmek , sen sorunların farkında olması gibi hangisi sizi kullanmalıdır.

yani: C programını C ++ olarak derlemeniz gerekiyorsa (her ne kadar ayrı bir dil olsa da) kullanım sonucunu vermelisiniz malloc.


1
" Yayıncı, özellikle işaretçi malloc()çağrıdan uzak olarak bildirilirse, hedef işaretçi türü değiştiğinde geliştiricinin tür boyutlandırmasındaki tutarsızlıkları tanımlamasına yardımcı olabilir " ne demektir? Bir örnek verebilir misiniz?
Spikatrix

3
@CoolGuy: Başka bir yanıtla ilgili daha önceki bir yoruma bakın . Ancak p = malloc(sizeof(*p) * count)deyimin türdeki değişiklikleri otomatik olarak aldığını unutmayın, bu nedenle uyarı almak ve herhangi bir şeyi değiştirmek zorunda kalmazsınız. Yani bu gerçek bir avantaj değil, döküm yapmamaya en iyi alternatif.
Peter Cordes

7
Bu doğru cevaptır: Artıları ve eksileri vardır ve bir zevk meselesine kadar kaynar (kod C ++ olarak derlenmediği sürece - o zaman döküm zorunludur).
Peter - Monica'yı yeniden

3
Nokta 3 tartışmalıdır, çünkü eğer işaretçi türü bildiriminde değiştirilirse, bu tür her malloc, realloc ve free inolving örneğini kontrol etmelidir. Döküm sizi tam da bunu yapmaya zorlayacaktır.
Michaël Roy

104

C'de bir voidişaretçiyi başka bir işaretçiye dolaylı olarak dönüştürebilirsiniz , bu nedenle bir döküm gerekli değildir. Birini kullanmak, sıradan gözlemciye, bir kişinin neden gerekli olduğuna dair yanıltıcı olabilecek bir neden olduğunu önerebilir.


100

Malloc'un sonucunu kullanmazsınız, çünkü bunu yapmak kodunuza anlamsız bir karmaşa ekler.

İnsanların malloc sonucunu kullanmasının en yaygın nedeni, C dilinin nasıl çalıştığından emin olmamalarıdır. Bu bir uyarı işareti: Belirli bir dil mekanizmasının nasıl çalıştığını bilmiyorsanız, tahmin etmeyin . Bakın ya da Stack Overflow'da sorun.

Bazı yorumlar:

  • Bir boş işaretçi, açık bir işaret (C11 6.3.2.3 ve 6.5.16.1) olmadan başka bir işaretçi türüne / bu işaretçi türünden dönüştürülebilir.

  • Ancak C ++ void*ile başka bir işaretçi türü arasında örtük bir yayınlamaya izin verilmez . Yani C ++ 'da oyuncu kadrosu doğru olurdu. Ancak C ++ 'da program yaparsanız newmalloc () kullanmamalısınız. Ve C kodunu asla C ++ derleyicisi kullanarak derlememelisiniz.

    Hem C hem de C ++ 'ı aynı kaynak kodla desteklemeniz gerekiyorsa, farklılıkları işaretlemek için derleyici anahtarlarını kullanın. Her iki dil standardını da aynı kodla doyurmaya çalışmayın, çünkü bunlar uyumlu değildir.

  • Üstbilgiyi eklemeyi unuttuğunuz için C derleyicisi bir işlev bulamazsa, bununla ilgili bir derleyici / bağlayıcı hatası alırsınız. Yani <stdlib.h>bu bir biggie eklemeyi unuttuysanız , programınızı oluşturamazsınız.

  • 25 yıldan daha eski olan standardın bir versiyonunu takip eden eski derleyicilerde, dahil <stdlib.h>etmeyi unutmak tehlikeli davranışlara neden olacaktır. Çünkü bu eski standartta, görünür bir prototip olmadan işlevler dolaylı olarak dönüş türünü dönüştürür int. Sonuç malloc'dan açıkça yayınlandığında bu hata gizlenir.

    Ama bu gerçekten bir sorun değil. 25 yaşında bir bilgisayar kullanmıyorsunuz, neden 25 yaşında bir derleyici kullanıyorsunuz?


9
"anlamsız dağınıklık" zaten sizinle aynı fikirde olmayan birini ikna etme olasılığını ortadan kaldıran küçümseyen abartıdır. Oyuncular kesinlikle anlamsız değildir; Ron Burk ve Kaz'ın cevapları, çok katılıyorum. Bu endişelerin, belirttiğiniz endişelerden daha ağır olup olmadığı sorulması makul bir sorudur. Bana göre, endişeleriniz onlarınkiyle karşılaştırıldığında nispeten küçük görünüyor.
Don Hatch

"Açık bir işaretçi, açık bir kadro olmadan başka bir işaretçi türüne / başka bir işaretçi türüne dönüştürülebilir" 6.3.2.3 tarafından desteklenmez. Belki "herhangi bir nesne türüne işaretçi" düşünüyorsunuz? "geçersiz işaretçi" ve "bir işleve işaretçi" o kadar kolay dönüştürülemez.
chux - Monica

Gerçekten de referans eksikti. "Örtüklük" için ilgili kısım, basit atama kuralı 6.5.16.1'dir. msgstr "bir işlenen bir nesne tipinin göstergesidir, diğeri ise geçersiz veya niteliksiz bir geçersiz sürümüne işaret eder". Bu referansı eksiksizlik cevabına ekledim.
Lundin

91

C de void *diğer (veri) imlecinden örtük bir dönüşüm elde edersiniz .


6
@Jens: Tamam, belki daha doğru bir ifade "örtük dönüşüm" dür. Kayan nokta ifadesinde integral değişken kullanımı gibi.
EFraim

@EFraim Bu aslında bir oyuncu kadrosuyla ve dolaylı olarak bir oyuncu kadrosuyla sonuçlanır.
Mad Physicist

71

Tarafından döndürülen değeri yayınlama malloc() artık gerekli değil, ancak kimsenin işaret etmediği bir nokta eklemek istiyorum:

Önce eski günlerde olduğunu, ANSI C sağlar void *işaretçiler jenerik türü olarak, char *bu tür bir kullanım için türüdür. Bu durumda, oyuncu derleyici uyarılarını kapatabilir.

Referans: C SSS


2
Derleyici uyarılarını kapatmak kötü bir fikirdir.
Albert van der Horst

8
@AlbertvanderHorst Eğer bunu tam olarak çözerek problemi çözmüyorsanız uyarı sizi uyaracak.
Dan Bechard

@Dan. Kesin problemi çözerek char * yerine modern ANSI C tiplerini döndürmek için bir altyordamın yeniden yazılması anlamına geliyorsa, katılıyorum. Derleyiciyi kapatmayı çağırmam. Her derleme tarafından olası sorunları bulmak için kullanmak yerine, derleyici uyarıları olmadığı konusunda ısrar eden yöneticilere vermeyin. Groetjes Albert
Albert van der Horst

53

Sadece deneyimlerimi ekleyerek, bilgisayar mühendisliği okuduğumda, C'de yazarken gördüğüm iki veya üç profesörün her zaman malloc oluşturduğunu görüyorum, ancak sorduğum (muazzam bir CV ve C anlayışı ile) bunun kesinlikle gereksiz olduğunu söyledi ama sadece mutlak olarak spesifikti ve öğrencileri mutlak özgüllük anlayışına soktu. Aslında döküm, nasıl çalıştığında hiçbir şeyi değiştirmez, tam olarak söylediği şeyi yapar, bellek ayırır ve döküm onu ​​etkilemez, aynı belleği alırsınız ve yanlışlıkla başka bir şeye dökseniz bile (ve bir şekilde derleyiciden kaçarsanız) C) buna aynı şekilde erişecektir.

Edit: Döküm belirli bir noktaya sahiptir. Dizi gösterimini kullandığınızda, oluşturulan kod bir sonraki öğenin başlangıcına ulaşmak için kaç bellek yeri ilerletmek zorunda olduğunu bilmek zorundadır, bu döküm yoluyla elde edilir. Bu şekilde bir çift için 8 bayt ileri giderken bir int için 4, vb. Bu nedenle işaretçi gösterimi kullanırsanız bir etkisi olmaz, dizi gösterimlerinde gerekli olur.


3
Daha önce belirtildiği gibi, döküm hataları gizleyebilir ve derleyici veya statik analizör için analizi zorlaştırabilir.
Lundin

2
"Aslında döküm nasıl çalıştığında hiçbir şeyi değiştirmeyecek". Eşleşen türe döküm hiçbir şeyi değiştirmemelidir, ancak var'ın türü değişmeli ve kadro artık eşleşmemeli, sorunlar ortaya çıkabilir mi? IWO'lar, döküm ve var tipi, bakım işinin iki katı olarak senkronize tutulmalıdır.
chux - Monica'yı geri yükle

Profs'in neden döküm yapmayı tercih ettiğini anlayabiliyorum. Döküm, eğitmen bilgisine ilettiği ve öğrenci kodunun sürdürülmesine gerek olmadığı bir eğitim açısından yararlı olabilir - atma kodu. Ancak kodlama, hakemlik ve bakım bakış açısından, p = malloc(sizeof *p * n);çok basit ve daha iyidir.
chux - Monica adlı kişiyi geri yükle

53

Sonuçlarının yayınlanması zorunlu değildir malloc, çünkü geri döner void*ve void*herhangi bir veri tipine işaret edilebilir.


34

Bir geçersiz işaretçi, genel bir nesne işaretleyicisidir ve C, bir boş işaretçi türünden diğer türlere örtük dönüştürmeyi destekler, bu nedenle açıkça yazımına gerek yoktur.

Ancak, aynı kodun örtülü dönüşümü desteklemeyen bir C ++ platformunda mükemmel uyumlu çalışmasını istiyorsanız, dakikayı yapmanız gerekir, bu nedenle her şey kullanılabilirliğe bağlıdır.


2
Tek bir kaynağı hem C hem de C ++ olarak derlemek normal bir kullanım durumu değildir (aksine, C ve C ++ kodunu birbirine bağlamak için bildirimler içeren bir başlık dosyası kullanmak yerine). mallocC ++ 'da ve arkadaşlarınızı kullanmak , özel ilgiyi (veya C'de yeniden yazmayı) hak ettiğini gösteren iyi bir uyarı işaretidir.
Toby Speight

1
"Boş işaretçi genel bir işaretçi" -> "Boş işaretçi genel bir nesne işaretçisi". İşlev işaretçisi boyutları aşılabilir void *, bu nedenle void *bir işlev işaretçisini iyi saklamak için yetersizdir.
chux - Monica adlı kullanıcıdan

o hattın niyetim aynıydı ama neyse öneri için @chux teşekkürler.
Endeavour

33

Bu nedir GNU C Kütüphanesi Başvuru kılavuzu diyor ki:

mallocISO C, türü void *gerektiğinde otomatik olarak başka bir işaretçi türüne dönüştürdüğü için , sonucu herhangi bir işaretçi değişkeni içinde herhangi bir işaretçi olmadan saklayabilirsiniz . Ancak, atama işleçleri dışındaki bağlamlarda veya kodunuzun geleneksel C'de çalışmasını istiyorsanız, oyuncu kadrosu gereklidir.

Ve gerçekten de ISO C11 standardı (p347) şöyle diyor:

Ayırma başarılı olursa döndürülen işaretçi, temel hizalama gereksinimi olan herhangi bir nesne türüne bir işaretçiye atanabilmesi için uygun şekilde hizalanır ve sonra ayrılan alandaki bu tür bir nesneye veya bu tür nesnelerden oluşan bir diziye erişmek için kullanılır ( boşluk açıkça yer değiştirmiştir)


31

Döndürülen tür geçersizdir *, kayıttan çıkarılabilir olması için istenen veri işaretçisine dönüştürülebilir.


1
void* olabilir istenen tipine cast olmak, ancak otomatik olarak çevrilecektir şekilde yapmaya gerek yoktur. Bu nedenle, oyuncu kadrosu gerekli değildir ve aslında yüksek puanlı cevaplarda belirtilen nedenlerden dolayı istenmeyen bir durumdur.
Toby Speight

ancak yalnızca "anında" kullanmanız gerekiyorsa, bunun yerine bir değişken oluşturursanız, değişken olmadan güvenli ve otomatik olarak değişkenin etkin türüne dönüştürülür (C cinsinden).
Ferrarezi

28

C dilinde, herhangi bir işaretçiye bir geçersiz işaretçi atanabilir, bu nedenle bir tür döküm kullanmamalısınız. "Güvenli yaz" ayırması istiyorsanız, C projelerimde her zaman kullandığım aşağıdaki makro işlevlerini önerebilirim:

#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof *(ptr))
#define NEW(ptr) NEW_ARRAY((ptr), 1)

Bunlar yerinde olduğunda şunu söyleyebilirsiniz:

NEW_ARRAY(sieve, length);

Dinamik olmayan diziler için, üçüncü olması gereken işlev makrosu

#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])

dizi döngülerini daha güvenli ve kullanışlı hale getirir:

int i, a[100];

for (i = 0; i < LEN(a); i++) {
   ...
}

"herhangi bir nesne işaretçisine geçersiz bir işaretçi atanabilir " İşlev işaretçileri, bir malloc()tane olmasa da başka bir sorundur .
chux - Monica adlı kişiyi geri yükle

void*Bir işlev işaretçisine / işaretinden bir atamak bilgi kaybına neden olabilir, böylece "herhangi bir işaretçiye geçersiz bir işaretçi atanabilir" bu durumlarda bir sorundur. Ancak void*, malloc() herhangi bir nesne işaretçisine bir , atamak sorun değildir.
chux - Monica

doUzakta başlık sorudan merak ediyor henüz bir döngü içeren makrolar ilgili döngü yorumu. Bu yorum kaldırılıyor. Bunu daha sonra da indirecek.
chux - Monica'yı

27

Programlama diline ve derleyiciye bağlıdır. mallocC dilinde kullanırsanız , otomatik olarak cast yazacağından cast yazmaya gerek yoktur. Ancak, C ++ kullanıyorsanız, mallocbir void*tür döndüreceği için cast yazmalısınız .


1
Fonksiyon Malloc ++ sıra C bir boşluk gösterici ile döner, ancak dilin kuralları C farklıdır.
Ağustos Karlstrom

16

GCC ve Clang için kullanılan insanlar şımarık. Dışarıda o kadar iyi değil.

Kullandığım şaşırtıcı derecede yaşlı derleyiciler tarafından yıllar boyunca oldukça dehşete düştüm. Genellikle şirketler ve yöneticiler, derleyicileri değiştirmek için ultra muhafazakar bir yaklaşım benimser ve hatta test etmezler. yeni bir derleyicinin (daha iyi standartlara uygunluk ve kod optimizasyonu ile) sistemlerinde çalışıp çalışmayacağını . Çalışan geliştiriciler için pratik gerçeklik, kodlama yaparken üslerinizi örtmeniz gerektiğidir ve ne yazık ki, kodunuza hangi derleyicinin uygulanabileceğini kontrol edemiyorsanız mallokları dökmek iyi bir alışkanlıktır.

Birçok kuruluş kendilerine ait bir kodlama standardı geçerli olduğunu ben de öneririm ve o bu o tanımlanmışsa yöntem insanların takip olmalıdır. Açık rehberliğin yokluğunda, bir standarda körü körüne bağlı kalmak yerine, her yerde derleme eğilimindeyim.

Mevcut standartlar altında gerekli olmadığı iddiası oldukça geçerlidir. Ancak bu argüman gerçek dünyanın pratikliklerini atlıyor. Biz sadece günün standardı tarafından yönetilen bir dünyada değil, "yerel yönetimin gerçeklik alanı" olarak adlandırmayı sevdiğim şeylerin pratiklikleri ile kod yazıyoruz. Ve bu, uzay zamanından daha fazla bükülmüş ve bükülmüş. :-)

YMMV.

Malloc dökümünü savunma operasyonu olarak düşünmeye meyilliyim. Hoş değil, mükemmel değil, ama genellikle güvenli. (Sonra stdlib.h dahil değildir verdiyseniz Dürüstçe, ettik yolu malloc döküm daha fazla probleme!).


15

Ben sadece kötü dönüşüm getirmek için hiçbir döküm kullanılmasa bile, aşağıdaki snippet gibi kodun tanı olmadan derlemek için izin verir, tür sistemindeki çirkin deliğin onaylanmamış göstermek için döküm koymak:

double d;
void *p = &d;
int *q = p;

Keşke var olmasaydı (ve C ++ 'da yok) ve bu yüzden yaptım. Zevkimi ve programlama politikamı temsil ediyor. Sadece bir işaretçi değil, etkili bir şekilde, bir oy pusulası ve aptallık şeytanlarını atıyorum . Eğer gerçekten aptallık yapamıyorsam , en azından bunu bir protesto hareketiyle dile getirmeme izin ver.

Aslında, iyi bir uygulama, malloc(ve arkadaşlarınızı) geri dönen işlevlerle unsigned char *sarmaktır ve temelde asla void *kodunuzda kullanılmaz. Herhangi bir nesneye genel bir işaretçi gerekiyorsa, bir char *veya kullanın unsigned char *ve her iki yönde de yayınlar yapın. Şımartılabilecek bir rahatlama, belki de, döküm gibi memsetve memcpyolmadan işlevler kullanmaktır .

Bunu kodunuzu yazarsanız döküm ve C ++ uyumluluğu konusunda, o C ve C hem ++ (bu durumda siz derler zorunda dönüş değer dağıtmak mallocdışında bir şeye atarken void *), çok yararlı yapabilirsiniz kendiniz için bir şey: C ++ olarak derlenirken C ++ stil dökümlerine dönüşen ancak C olarak derlerken C dökümüne indirgeyen döküm için makrolar kullanabilirsiniz:

/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif

Bu makrolara bağlı kalırsanız, grepbu tanımlayıcılar için kod tabanınızda yapılan basit bir arama size tüm yayınlarınızın nerede olduğunu gösterir, böylece bunlardan herhangi birinin yanlış olup olmadığını inceleyebilirsiniz.

Daha sonra, kodu düzenli olarak C ++ ile derlerseniz, uygun bir dökümün kullanımını zorlar. Örneğin, strip_qualyalnızca bir constveya öğesini kaldırmak için kullanırsanız volatile, ancak program şimdi bir tür dönüştürmenin yer alacağı şekilde değişirse, bir tanı alırsınız ve istenen dönüşümü elde etmek için bir dizi kombinasyonu kullanmanız gerekir.

Bu makrolara uymanıza yardımcı olmak için, GNU C ++ (C! Değil) derleyicisinin güzel bir özelliği vardır: C stili yayınların tüm oluşumları için üretilen isteğe bağlı bir tanılama.

     -Wold stili döküm (yalnızca C ++ ve Objective-C ++)
         Boş olmayan bir türe dökülen eski bir stil (C stili) kullanılıyorsa uyar
         C ++ programında. Yeni stil yayınları (dynamic_cast,
         static_cast, reinterpret_cast ve const_cast) daha az savunmasız
         istenmeyen etkileri ve aramak çok daha kolay.

C kodunuz C ++ olarak derleniyorsa, bu -Wold-style-castseçeneği (type), kodun içine girebilecek döküm sözdiziminin tüm örneklerini bulmak ve yukarıdaki makrolar (veya bir gerekirse kombinasyon).

Dönüşümlerin bu tedavisi, bir "Temiz C" de çalışmak için tek ve en büyük bağımsız teknik gerekçedir: kombine C ve C ++ lehçesi, bu da teknik olarak dönüş değerinin dökülmesini haklı çıkarır malloc.


Diğer belirtildiği gibi, genellikle C ve C ++ kodunu karıştırmamanızı tavsiye ederim. Bununla birlikte, bunu yapmak için iyi bir nedeniniz varsa, makrolar yararlı olabilir.
Phil1970

@ Phil1970 Hepsi C ve C ++ derleyicilerine taşınabilir olan ve C ++ 'ın bazı özelliklerinden yararlanan tek bir uyumlu lehçede yazılmıştır. Hepsi C ++ olarak derlenmelidir, aksi takdirde C olarak derlenmelidir.
Kaz

Yani önceki yorumda söylemeye çalıştığım şey, C ve C ++ 'ın bir karışımı olmadığı. Amaç, kodun tümü C olarak derlenmiş veya tümü C ++ olarak derlenmiş.
Kaz

15

Mümkün olduğunda C dilinde programlama yaparken yapılacak en iyi şey:

  1. Programınızın tüm uyarılar açıkken bir C derleyicisi aracılığıyla derlenmesini sağlayın -Wallve tüm hataları ve uyarıları düzeltin
  2. Olarak tanımlanmış değişken olmadığından emin olun auto
  3. Sonra -Wallve ile bir C ++ derleyicisi kullanarak derleyin -std=c++11. Tüm hataları ve uyarıları düzeltin.
  4. Şimdi C derleyicisini kullanarak tekrar derleyin. Programınız artık herhangi bir uyarı yapmadan derlenmeli ve daha az hata içermelidir.

Bu prosedür, C ++ katı tip kontrolünden yararlanmanızı sağlar, böylece hata sayısını azaltır. Özellikle, bu prosedür sizi dahil etmeye zorlar stdlib.hveya alırsınız

malloc bu kapsamda beyan edilmedi

ve ayrıca sonucunu yayınlamanız için sizi zorlar mallocveya

Geçersiz dönüşüm void*içinT*

veya hedef türünüz ne olursa olsun.

Bulabildiğim C ++ yerine C ile yazmanın tek faydası

  1. C iyi belirlenmiş bir ABI'ye sahiptir
  2. C ++ daha fazla kod oluşturabilir [istisnalar, RTTI, şablonlar, çalışma zamanı polimorfizmi]

Statik polimorfik özellik ile birlikte C için ortak alt kümeyi kullanırken ikinci eksilerin ideal durumda kaybolması gerektiğine dikkat edin .

C ++ katı kurallarını uygunsuz bulanlar için, C ++ 11 özelliğini çıkarım türüyle kullanabiliriz

auto memblock=static_cast<T*>(malloc(n*sizeof(T))); //Mult may overflow...

18
C kodu için bir C derleyicisi kullanın. C ++ kodu için bir C ++ derleyicisi kullanın. Hayır ifs, hayır buts. C kodunuzu C ++ ile yeniden yazmak tamamen başka bir şeydir ve zaman ve risklere değer olabilir veya olmayabilir.
Toby Speight

2
@TobySpeight tavsiyesine eklemek istiyorum: C kodunu bir C ++ projesinde kullanmanız gerekiyorsa, genellikle C kodunu C (örneğin gcc -c c_code.c), C ++ kodunu C ++ (örn. g++ -c cpp_code.cpp) Olarak derleyebilir ve sonra birbirine bağlayabilirsiniz. (örneğin gcc c_code.o cpp_code.oveya proje bağımlılıklarına bağlı olarak tersi). Şimdi kendinizi her iki dilden herhangi bir güzel özellikten mahrum etmek için hiçbir neden olmamalıdır ...
otistik

1
@ user877329 Sadece "C ++ uyumlu" olma uğruna kodun okunabilirliğini azaltan koda titizlikle dökümler eklemeye daha mantıklı bir alternatif.
otistik

1
Muhtemelen bu bağlamdaki ana avantaj, C'nin yazmanıza izin vermesidir p = malloc(sizeof(*p));, bu da pfarklı bir tür isminde değişiklik yapılması durumunda ilk etapta değiştirilmesi gerekmez . Dökümün önerilen "avantajı" p, yanlış tür ise derleme hatası almanızdır , ancak Just Works ise daha da iyidir.
Peter Cordes

1
Uygun C ++ derleyicileri olmayan platformları hedeflerken C dilinde yazmanın gerekli olabileceğini belirtmek isterim. İstisnalar ve şablonlar, genellikle C ++ 'ın daha küçük ve / veya daha verimli kod üretmesine yardımcı olurken, C ++' da çalışma zamanı polimorfizmi çoğunlukla C'ye eşdeğerdir
user7860670

15

Hayır, sonucunu yayınlamıyorsunuz malloc().

Genel olarak, yayın yapamaz veya yayın yapamazsınızvoid * .

Bunu yapmamak için verilen tipik bir sebep, başarısızlığın #include <stdlib.h>fark edilmeyebilmesidir. C99, örtük işlev bildirimlerini yasadışı hale getirdiğinden , bu uzun bir süredir sorun değil , bu nedenle derleyiciniz en az C99'a uyuyorsa, bir tanı mesajı alırsınız.

Ancak gereksiz işaretçi atımlarını tanıtmamak için çok daha güçlü bir neden var :

C'de bir işaretçi kadrosu neredeyse her zaman bir hatadır . Bunun nedeni aşağıdaki kuraldır ( C11 için son taslak olan N1570'te §6.5 p7 ):

Bir nesnenin depolanmış değerine yalnızca aşağıdaki türlerden birine sahip bir değer değeri ifadesiyle erişilir:
- nesnenin
etkili türüyle uyumlu bir tür,
- nesnenin etkili türüyle uyumlu bir türün nitelikli bir sürümü, - nesnenin etkili türüne karşılık gelen
imzalı veya imzasız tür olan bir tür,
- nesnenin etkili türünün nitelikli bir sürümüne karşılık gelen imzalı veya imzasız tür olan bir tür, üyeleri arasında yukarıda belirtilen türlerin (özyinelemeli olarak bir alt küme veya içerdiği birliğin bir üyesi dahil) veya
- bir karakter türü.

Bu aynı zamanda katı takma adlandırma kuralı olarak da bilinir . Yani aşağıdaki kod tanımsız davranış :

long x = 5;
double *p = (double *)&x;
double y = *p;

Ve bazen şaşırtıcı bir şekilde aşağıdakiler de geçerlidir:

struct foo { int x; };
struct bar { int x; int y; };
struct bar b = { 1, 2};
struct foo *p = (struct foo *)&b;
int z = p->x;

Bazen, do dökme işaretçiler gerekir, ancak verilen sıkı örtüşme kuralı , onunla çok dikkatli olmak zorunda. Bu nedenle, kodunuzda bir işaretçi kademesi oluşması , geçerliliğini iki kez kontrol etmeniz gereken bir yerdir . Bu nedenle, asla gereksiz bir işaretçi kadrosu yazmazsınız.

tl; Dr.

Özetle: C'de, bir işaretçi kadrosunun herhangi bir oluşumu, özel dikkat gerektiren kod için kırmızı bir bayrak kaldırmalıdır, asla gereksiz işaretçi atmaları yazmamalısınız.


Yan notlar:

  • Aslında durumlar vardır gerek bir döküm yapılmasını void *Eğer bir işaretçi yazdırmak istiyorsanız, örneğin:

    int x = 5;
    printf("%p\n", (void *)&x);

    Oyuncular burada gereklidir, çünkü printf()değişken bir işlevdir, bu nedenle örtük dönüşümler işe yaramaz.

  • C ++ 'da durum farklıdır. İşaretçi türlerinin seçilmesi, türetilmiş sınıfların nesneleriyle uğraşırken biraz yaygındır (ve doğrudur). Bu nedenle, C ++, ve dönüştürme mantıklı void *olduğunu değil örtük. C ++, farklı döküm lezzetlerine sahiptir.


1
Örneklerinizde boşluktan * kaçınmalısınız. double * 'dan int *' ye cast ve bunun tersi arasında bir fark vardır. malloc, en büyük standart tipe hizalanmış noktaya döner, böylece birisi bu hizalanmış işaretçiyi başka bir türe dönüştürse bile kırılmış hiçbir örtüşme kuralı yoktur.
P__J__

Takma adın hizalama ve yorumunuzun geri kalanı ile hiçbir ilgisi yoktur - açıkçası bu noktaya gelmediniz.

@PeterJ: her ihtimale karşı, gereksiz bir işaretçi kadrosundan kaçınmaktır , bu yüzden özel dikkat etmeniz gereken bir kod parçası gibi görünmüyor .

Katı takma adının geçersiz işaretçilerle bir ilgisi yoktur. Sıkı takma ad ihlallerinden kaynaklanan hataları elde etmek için sivri uçlu verilere atıfta bulunmalısınız. Ve bir geçersiz işaretleyicinin referansını kaldıramayacağınız için, bu tür hatalar her tanım için geçersiz işaretçi ile ilgili değil, başka bir şeyle ilgilidir.
Lundin

Aksine, tüm işaretçi atmalarını yasaklamak için bir kural koymanız gerekir. Ama sonra serileştirme rutinleri ve donanımla ilgili programlama gibi şeyleri nasıl yazardınız? C'nin gücü olan şeyler. Ne yaptığınızı biliyorsanız, bu tür oyuncular iyidir.
Lundin

15

Oyuncu kadrosunu yapmayı tercih ederim, ama elle yapmamayı En sevdiğim glib'den g_newve g_new0makroları kullanmak . Eğer glib kullanılmazsa, benzer makrolar eklerdim. Bu makrolar, tür güvenliğinden ödün vermeden kod çoğaltmayı azaltır. Türü yanlış alırsanız, bir uyarı (C ++ hata) hataya neden olmayan geçersiz işaretçiler arasında örtülü bir döküm alırsınız. Tanımlayan üstbilgiyi eklemeyi unutursanız g_newve g_new0bir hata alırsınız. g_newve g_new0her ikisi de aynı argümanları mallocalır , aksine bu daha az argüman alır calloc. 0Sıfır başlangıçlı bellek almak için ekleyin . Kod değişiklik yapılmadan bir C ++ derleyicisi ile derlenebilir.


12

Döküm sadece C ++ değil C içindir.


9

Geçersiz işaretçinin arkasındaki kavram, herhangi bir veri türüne dökülebilmesidir, bu nedenle malloc geçersizdir. Ayrıca otomatik tiplemenin de farkında olmalısınız. Bu yüzden işaretçiyi yapmak zorunda olmanız şart değildir. Kodun temiz tutulmasına yardımcı olur ve hata ayıklamaya yardımcı olur


11
" Zorunlu değil - bunu yapmak zorundasın " - Sanırım orada bir çelişki var!
Toby Speight

5
Sanırım bu yazıyı birine okumalı ve ne söylemeye çalıştığınızı anlayıp anlamadıklarını görmelisiniz. Sonra tekrar yazmak, ne söylemek istediğinizi netleştirmek için. Cevabınızın ne olduğunu gerçekten anlayamıyorum.
Bill Woodger

9

Bir geçersiz işaretçi genel bir işaretleyicidir ve C, bir boş işaretçi türünden diğer türlere örtük dönüştürmeyi destekler, bu nedenle açıkça yazımına gerek yoktur.

Ancak, aynı kodun örtülü dönüşümü desteklemeyen bir C ++ platformunda mükemmel uyumlu çalışmasını istiyorsanız, dakikayı yapmanız gerekir, bu nedenle her şey kullanılabilirliğe bağlıdır.


9
  1. Diğer belirtildiği gibi, C için değil, C ++ için gereklidir.

  2. Dökümün dahil edilmesi bir C programının veya fonksiyonunun C ++ olarak derlenmesine izin verebilir.

  3. C'de gereksizdir, çünkü void * otomatik olarak ve diğer herhangi bir işaretçi türüne güvenli bir şekilde yükseltilir.

  4. Ancak o zaman yayın yaparsanız, stdlib.h dosyasını eklemeyi unuttuysanız bir hatayı gizleyebilir . Bu, çökmelere neden olabilir (veya daha da kötüsü, kodun tamamen farklı bir bölümünde ileride bir çökmeye neden olmaz).

    Çünkü stdlib.h malloc için prototip içeriyor. Malloc için bir prototip olmadığında standart, C derleyicisinin malloc'un bir int döndürdüğünü varsaymasını gerektirir. Yayın yoksa, işaretçiye bu tamsayı atandığında bir uyarı verilir; ancak, oyuncu kadrosunda bu uyarı üretilmez ve bir hata gizlenir.


7

Mallocun dökümü C'de gereksiz, ancak C ++ 'da zorunludur.

C'de döküm yapmak gereksizdir:

  • void * C durumunda otomatik olarak ve güvenli bir şekilde diğer işaretçi türlerine yükseltilir.
  • Eklemeyi unuttuysanız bir hatayı gizleyebilir <stdlib.h>. Bu çökmelere neden olabilir.
  • İşaretçiler ve tamsayılar farklı boyutlara sahipse, bir uyarıyı yayınlayarak gizlersiniz ve iade ettiğiniz adresin bitlerini kaybedebilirsiniz.
  • İşaretçinin türü bildiriminde değiştirilirse malloc, çağrılan ve yayınlanan tüm satırları da değiştirmeniz gerekebilir .

Öte yandan, döküm programınızın taşınabilirliğini artırabilir. yani, bir C programının veya fonksiyonunun C ++ olarak derlenmesini sağlar.


0

Benim için, eve götürmek ve sonuç malloc, C'de dökümün tamamen gerekli DEĞİLDİR, ancak eğer yayınlarsanız , yine de size talep edilen kutsanmış hafıza alanınızı tahsis edeceği mallocgibi etkilemeyecektir malloc. Başka bir eve götürmek, insanların döküm yapmasının nedeni veya nedenlerinden biridir ve bu, aynı programı C veya C ++ 'da derlemelerini sağlamaktır.

Başka nedenler olabilir, ancak diğer nedenler, kesinlikle, er ya da geç ciddi bir belaya neden olur.


0

Yapabilirsiniz, ancak C'ye basmanız gerekmez. Bu kod C ++ olarak derlenmişse yayınlamanız gerekir.

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.