foo (geçersiz) vs foo (geçersiz *)


9

Konuşan İşlevsel ve sözdizimsel, prototip bir fonksiyonu arasında bir fark yoktur int foo(void)ve int foo(void *)?

Örneğin, int bar(int)ve arasındaki farkları biliyorum int bar(int *)- bunlardan biri int arıyor, diğeri int işaretçisi arıyor. Does voidaynı şekilde davranır?


İlgili bir soruya cevap: stackoverflow.com/a/1043209/434551 .
R Sahu


Daha da ilginç olabilir arasındaki farktır foo(void)ve foo().
Maxim Egorushkin

Yanıtlar:


10

Gönderen Yazılım Mühendisliği Bu yanıt, void bu bilgilerin nasıl kullanıldıklarını özel olarak bağlı tedavi edilir. İçinde Cve C++, voidbelirtmek için kullanılır , bir veri türü yokluğunu ise void *bir işaret etmek için kullanılmaktadır bir türü olmayan bir bellek içinde bir veri / boşluk olan işaretçi. void *tek başına silinemez ve önce başka bir türe dökülmesi gerekir. Bu kadronun açık Colması gerekmez, ancak açık olması gerekir C++. (Bu yüzden malloc'un dönüş değerini kullanmıyoruz void *.)


Parametre olarak bir işlevle birlikte kullanıldığında void, herhangi bir parametrenin tamamen yokluğu anlamına gelir ve izin verilen tek parametredir. Void'i değişken türü gibi kullanmaya veya başka argümanlar eklemeye çalışmak derleyici hatasıyla sonuçlanır:

int foo(void, int);     //trying to use "void" as a parameter
int bar(void baz);      //trying to use "void" as an argument's type
main.c:1:8: error: 'void' must be the first and only parameter if specified
int foo(void, int);
       ^
main.c:2:14: error: argument may not have 'void' type
int bar(void baz);
             ^

Benzer şekilde, tipli bir değişken bildirmek de imkansızdır void:

int main(void) {
  void qux;         //trying to create a variable with type void
}
main.c:5:8: error: variable has incomplete type 'void'
  void qux;

voidçünkü işlev için bir dönüş değeri veri döndürülmeyeceğini gösterir. Bir değişken türünü bildirmek imkansız olduğu için, bir geçersiz işaretçi ile bilevoid bir voidişlevin dönüş değerini yakalamak imkansızdır .

void foo(int i) { return; }

int main(void) {
  void *j;
  j = foo(0);

  return 0;
}
main.c:5:5: error: assigning to 'void *' from
      incompatible type 'void'
  j = foo(0);
    ^ ~~~~~~

Tipik olmayan void *başka bir durum. Geçersiz işaretçi, bellekteki bir konuma bir işaretçi belirtir, ancak o işaretçideki veri türünü göstermez. (Bu, qsort () işlevinde olduğu gibi C'de polimorfizmi elde etmek için kullanılır .) Ancak, bu işaretçilerin kullanımı yanlışlıkla zor olabilir, çünkü bunları yanlışlıkla yanlış türe dökmek çok kolaydır. Aşağıdaki kod herhangi bir derleyici hatası atmaz, ancak tanımlanmamış davranışla sonuçlanır:C

#include <stdio.h>

int main(void) {
  double foo = 47.2;    //create a double
  void *bar = &foo;     //create a void pointer to that double
  char *baz = bar;      //create a char pointer from the void pointer, which
                        //is supposed to hold a double

  fprintf(stdout, "%s\n", baz);
}

Ancak aşağıdaki kod tamamen yasaldır; bir geçersiz işaretleyiciye ve işaretçi arasında yayın yapmak hiçbir zaman sahip olduğu değeri değiştirmez.

#include <stdio.h>

int main(void) {
  double foo = 47.2;
  void *bar = &foo;
  double *baz = bar;

  fprintf(stdout, "%f\n", *baz);
}

47.200000

Bir fonksiyon parametresi olarak, void *geçmekte olduğunuz işaretçideki veri türünün bilinmediğini ve o bellek konumundaki her şeyi doğru bir şekilde işlemek sizin programcıya bağlıdır. Dönüş değeri olarak, void *döndürülen verilerin türünün bilinmediğini veya türsüz olduğunu ve program tarafından işlenmesi gerektiğini belirtir.

int quux(void *);   //a function that receives a pointer to data whose type is not known, and returns an int.
void *quuz(int);    //a function that receives an int, and returns a pointer to data whose type is not known.

tl; dr void bir işlev prototipinde "veri yok" anlamına gelir ve dönüş değerini veya parametre olmadığını gösterir, void *işlev prototipinde "bu işlevin verildiği işaretçideki veriler bilinen bir türe sahip değildir" anlamına gelir ve bir parametre veya dönüş değerini gösterir işaretçideki veriler kullanılabilmesi için işaretçisi farklı bir türe dönüştürülmelidir.


void * ... must be cast to another type first, but may be done so without an explicit cast.C ++ 'da doğru değil. C ++ 'da dönüşüm formu void*açık olmalıdır. Oyuncular açık bir şekilde çağıran PS gereksizdir çünkü cast tanımı gereği açık bir dönüşümdür.
eerorika

C / C ++ farklılıklarını yansıtacak şekilde güncellendi, bana bildirdiğiniz için teşekkür ederiz!
Nick Reed

4

foo(void) - parametresiz fonksiyon

foo(void *)- tek void *parametreli fonksiyon

Nedir void *? Belirtilen türde olmayan verilerin göstergesidir. Başka herhangi bir işaretçi türüne dökülebilir

unsigned add(void *arr)
{
   unsigned *uarr = arr;
   return uarr[0] + uarr[1];
}

Temel cevap, bu yüzden en iyisi. Bunun (type) vs. (type *)çiftler evreninde nasıl bir istisna olduğunu anlatabilirim, çünkü boşluk aslında bir tür değildir.
Roberto Caboni

2

İşlevsel ve sözdizimsel olarak konuşursak, prototipi int foo (void) ve int foo (void *) olan bir işlev arasında fark var mıdır?

Bir fark var:

int foo(void) argüman kabul etmeyen bir işlevi bildirir.

int foo(void *)tek tür argümanını kabul eden bir işlev bildirir void*.

C ++ 'da, int foo(void)eşittir int foo().

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.