C ile aşırı fonksiyon yüklemesi nasıl yapılır?


240

C'de fonksiyon aşırı yüklemesi elde etmenin bir yolu var mı? Aşırı yüklenecek basit fonksiyonlara bakıyorum

foo (int a)  
foo (char b)  
foo (float c , int d)

Bence doğrudan bir yol yok; Varsa geçici çözümler arıyorum.


6
Bunu neden yapmak istiyorsun? C'nin polimorfik yetenekleri yoktur. Yani foo (rastgele tip) imkansız. Sadece gerçek funcs yapmak foo_i, foo_ch, foo_d, vb.
jmucchiello

4
Geçersiz işaretçiler ve yazım kimlikleri kullanarak kötü yoldan gidebilirsiniz.
alk

11
Yeni C standardıyla bu sorunun cevabının başlangıçta sorulduğundan beri değiştiğine dikkat etmeliyim .
Leushenko

Yanıtlar:


127

Birkaç olasılık vardır:

  1. printf stil işlevleri (bağımsız değişken olarak yazın)
  2. opengl stil işlevleri (işlev adını yazın)
  3. c ++ 'ın c alt kümesi (c ++ derleyicisi kullanabiliyorsanız)

1
opengl stil fonksiyonlarını açıklayabilir veya link verebilir misiniz?
FL4SOF

1
@Lazer: Burada biri basit, printf benzeri işlemlerin yerine getirilmesinde.
Alexey Frunze

12
Hayır. Printf işlev aşırı yüklenmesi değil. vararg kullanır !!! Ve C, Fonksiyon Aşırı Yüklemeyi desteklemez.
hqt

52
@hqt Cevap aşırı yükleme kelimesinden hiç bahsetmiyor.
kyrias

1
@kyrias Eğer cevap aşırı yükleme ile ilgili değilse bu yanlış soru üzerinde
Michael Mrozek

233

Evet!

Bu sorunun sorulmasından bu yana, standart C (uzantı yok ), anahtar kelimenin C11'e eklenmesi sayesinde işlev aşırı yüklemesi (operatörler değil) için etkili bir şekilde destek kazanmıştır_Generic . (4.9 sürümünden beri GCC'de desteklenmektedir)

(Aşırı yükleme, soruda gösterilen şekilde gerçekten "yerleşik" değildir, ancak böyle çalışan bir şeyi uygulamak çok kolaydır.)

_Genericaynı aile içinde bir derleme zamanı operatörüdür sizeofve _Alignof. Standart bölüm 6.5.1.1'de açıklanmaktadır. İki ana parametreyi kabul eder: bir ifade (çalışma zamanında değerlendirilmeyecektir) ve biraz switchblok gibi görünen bir tür / ifade ilişkilendirme listesi . _Genericifadenin genel türünü alır ve ardından türünün listesindeki son sonuç ifadesini seçmek için üzerinde "geçiş yapar":

_Generic(1, float: 2.0,
            char *: "2",
            int: 2,
            default: get_two_object());

Yukarıdaki ifade şu şekilde değerlendirilir 2- kontrol eden ifadenin türü int, yani intdeğer olarak ilişkili ifadeyi seçer . Bunların hiçbiri çalışma zamanında kalmaz. ( defaultCümle isteğe bağlıdır: kapalı bırakırsanız ve tür eşleşmezse, bir derleme hatasına neden olur.)

Bunun aşırı işlev yüklemesi için yararlı olması, C ön işlemcisi tarafından eklenebilmesi ve kontrol makrosuna iletilen argümanların türüne göre bir sonuç ifadesi seçebilmesidir. Yani (C standardından örnek):

#define cbrt(X) _Generic((X),                \
                         long double: cbrtl, \
                         default: cbrt,      \
                         float: cbrtf        \
                         )(X)

Bu makro cbrt, makroya argüman türünü göndererek, uygun bir uygulama işlevi seçip orijinal makro bağımsız değişkenini bu işleve geçirerek aşırı yüklenmiş bir işlem gerçekleştirir.

Orijinal örneğinizi uygulamak için bunu yapabiliriz:

foo_int (int a)  
foo_char (char b)  
foo_float_int (float c , int d)

#define foo(_1, ...) _Generic((_1),                                  \
                              int: foo_int,                          \
                              char: foo_char,                        \
                              float: _Generic((FIRST(__VA_ARGS__,)), \
                                     int: foo_float_int))(_1, __VA_ARGS__)
#define FIRST(A, ...) A

Bu durumda default:, üçüncü durum için bir ilişkilendirme kullanabilirdik, ancak bu prensibi birden çok argümana nasıl genişleteceğimizi göstermez. Sonuç olarak, foo(...)kodunuzda argümanlarının türü hakkında endişelenmeden (çok [1]) kullanabilirsiniz.


Daha karmaşık durumlar, örneğin daha fazla sayıda argümanı aşırı yükleyen işlevler veya değişen sayılar için, statik dağıtım yapılarını otomatik olarak oluşturmak için yardımcı program makrolarını kullanabilirsiniz:

void print_ii(int a, int b) { printf("int, int\n"); }
void print_di(double a, int b) { printf("double, int\n"); }
void print_iii(int a, int b, int c) { printf("int, int, int\n"); }
void print_default(void) { printf("unknown arguments\n"); }

#define print(...) OVERLOAD(print, (__VA_ARGS__), \
    (print_ii, (int, int)), \
    (print_di, (double, int)), \
    (print_iii, (int, int, int)) \
)

#define OVERLOAD_ARG_TYPES (int, double)
#define OVERLOAD_FUNCTIONS (print)
#include "activate-overloads.h"

int main(void) {
    print(44, 47);   // prints "int, int"
    print(4.4, 47);  // prints "double, int"
    print(1, 2, 3);  // prints "int, int, int"
    print("");       // prints "unknown arguments"
}

( Burada uygulama ) Yani biraz çabayla sen aşırı için doğal destek ile bir dil gibi hemen hemen seyir için Demirbaş miktarını azaltabilir.

Bir yana, C99'da argümanların sayısını (türü değil) aşırı yüklemek zaten mümkün olmuştu .


[1] C'nin türleri değerlendirme biçiminin sizi harekete geçirebileceğini unutmayın. Bu, foo_intörneğin bir karakter değişmezi iletmeyi denediğinizi seçecektir ve aşırı yüklerinizin dize değişmezlerini desteklemesini istiyorsanız biraz karışıklık yapmanız gerekir . Yine de genel olarak oldukça güzel.


Örneğinize göre aşırı yüklenmiş tek şey makro gibi işlev görüyor. Doğru anladığımı göreyim: İşlevleri aşırı yüklemek istiyorsanız, yalnızca ön işlemciyi, aktarılan veri türlerine göre işlev çağrısını yönlendirmek için kullanırsınız, değil mi?
Nick

Ne yazık ki, C11 yakalamaya başladığında, MISRA'nın değişken argüman listelerini yasaklayan aynı nedenlerle bu özelliği benimsemeyeceğini varsayıyorum. Dünyamda MISRA'ya çok yakın olmaya çalışıyorum.
Nick

9
@Nick tüm aşırı yükleme olduğunu. Sadece diğer dillerde örtük olarak ele alınır (örn. Aşırı yükleme herhangi bir dilde "aşırı yüklenmiş bir işleve bir işaretçi" alamazsınız, çünkü aşırı yükleme birden fazla gövdeyi ifade eder). Bu işlemin yalnızca önişlemci tarafından yapılamayacağını, bir tür yazma gerektirdiğini unutmayın; önişlemci sadece görünüşünü değiştirir.
Leushenko

1
C99'a oldukça aşina olan ve bunun nasıl yapılacağını öğrenmek isteyen biri için bu, C için bile aşırı derecede karmaşık görünüyor
Tyler Crompton

5
@TylerCrompton Derleme zamanında değerlendirilir.
JAB

75

Daha önce de belirtildiği gibi, demek istediğin aşırı yükleme C tarafından desteklenmiyor. Sorunu çözmek için ortak bir deyim, işlevin etiketli birliği kabul etmesini sağlamaktır . Bu, kendisinin a ve farklı değer türlerinden biri gibi bir tür tür göstergesinden oluştuğu bir structparametre tarafından uygulanır . Misal:structenumunion

#include <stdio.h>

typedef enum {
    T_INT,
    T_FLOAT,
    T_CHAR,
} my_type;

typedef struct {
    my_type type;
    union {
        int a; 
        float b; 
        char c;
    } my_union;
} my_struct;

void set_overload (my_struct *whatever) 
{
    switch (whatever->type) 
    {
        case T_INT:
            whatever->my_union.a = 1;
            break;
        case T_FLOAT:
            whatever->my_union.b = 2.0;
            break;
        case T_CHAR:
            whatever->my_union.c = '3';
    }
}

void printf_overload (my_struct *whatever) {
    switch (whatever->type) 
    {
        case T_INT:
            printf("%d\n", whatever->my_union.a);
            break;
        case T_FLOAT:
            printf("%f\n", whatever->my_union.b);
            break;
        case T_CHAR:
            printf("%c\n", whatever->my_union.c);
            break;
    }

}

int main (int argc, char* argv[])
{
    my_struct s;

    s.type=T_INT;
    set_overload(&s);
    printf_overload(&s);

    s.type=T_FLOAT;
    set_overload(&s);
    printf_overload(&s);

    s.type=T_CHAR;
    set_overload(&s);
    printf_overload(&s); 
}

22
Eğer sadece tüm yapmazdım Neden whatever(ayrı fonksiyonlara içine s set_int, set_floatvs.). Sonra "tür ile etiketleme" işlev adını "tür adını ekleyin" olur. Bu yanıtın sürümü, daha fazla yazım, daha fazla çalışma süresi maliyeti, derleme zamanında yakalanmayacak hataların şansını daha fazla içerir ... İşleri bu şekilde yapmak için hiçbir avantaj göremiyorum ! 16 upvotes ?!
Ben

20
Ben, bu cevabı iptal ettim çünkü sadece “bunu yapma” demek yerine soruyu cevaplıyor . C'de ayrı işlevler kullanmanın daha deyimsel olduğu doğrudur, ancak biri C'de polimorfizm istiyorsa, bunu yapmanın iyi bir yoludur. Ayrıca, bu yanıt, derleyici veya VM'de çalışma zamanı polimorfizmini nasıl uygulayacağınızı gösterir: değeri bir türle etiketleyin ve ardından buna göre gönderin. Bu nedenle orijinal soruya mükemmel bir cevaptır.
Nils von Barth

20

İşte C fonksiyon aşırı yüklemesi gösteren bulduğum en açık ve en kısa örnek:

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

int addi(int a, int b) {
    return a + b;
}

char *adds(char *a, char *b) {
    char *res = malloc(strlen(a) + strlen(b) + 1);
    strcpy(res, a);
    strcat(res, b);
    return res;
}

#define add(a, b) _Generic(a, int: addi, char*: adds)(a, b)

int main(void) {
    int a = 1, b = 2;
    printf("%d\n", add(a, b)); // 3

    char *c = "hello ", *d = "world";
    printf("%s\n", add(c, d)); // hello world

    return 0;
}

https://gist.github.com/barosl/e0af4a92b2b8cabd05a7


1
Bence bu ruhsal olarak stackoverflow.com/a/25026358/1240268 bir dupe (ama daha az açıklama ile).
Andy Hayden

1
Kesinlikle # 1240268 olan dilimleme ve küp şeklinde doğrayın tam ve çalıştırılabilir kod 1 tek sürekli blok tercih ederim. Her birine kendi.
Jay Taylor

1
Ne yaptıklarını ve neden çalıştıklarını açıklayan cevapları tercih ederim. Bu hiçbirini yapmaz. "Şimdiye kadar gördüğüm en iyi:" bir sergi değil.
underscore_d

19

Derleyiciniz gcc ise ve her yeni yük eklediğinizde el güncellemeleri yapmayı düşünmüyorsanız, biraz makro sihir yapabilir ve arayanlar açısından istediğiniz sonucu elde edebilirsiniz, yazmak iyi değildir ... ama mümkün

__builtin_types_compatible_p dosyasına bakın, ardından böyle bir şey yapan bir makro tanımlamak için kullanın

#define foo(a) \
((__builtin_types_compatible_p(int, a)?foo(a):(__builtin_types_compatible_p(float, a)?foo(a):)

ama evet, sadece yapma

EDIT: C1X, şöyle göründükleri tür genel ifadeler için destek alacak:

#define cbrt(X) _Generic((X), long double: cbrtl, \
                              default: cbrt, \
                              float: cbrtf)(X)

13

Evet, bir çeşit.

İşte size örnek:

void printA(int a){
printf("Hello world from printA : %d\n",a);
}

void printB(const char *buff){
printf("Hello world from printB : %s\n",buff);
}

#define Max_ITEMS() 6, 5, 4, 3, 2, 1, 0 
#define __VA_ARG_N(_1, _2, _3, _4, _5, _6, N, ...) N
#define _Num_ARGS_(...) __VA_ARG_N(__VA_ARGS__) 
#define NUM_ARGS(...) (_Num_ARGS_(_0, ## __VA_ARGS__, Max_ITEMS()) - 1) 
#define CHECK_ARGS_MAX_LIMIT(t) if(NUM_ARGS(args)>t)
#define CHECK_ARGS_MIN_LIMIT(t) if(NUM_ARGS(args) 
#define print(x , args ...) \
CHECK_ARGS_MIN_LIMIT(1) printf("error");fflush(stdout); \
CHECK_ARGS_MAX_LIMIT(4) printf("error");fflush(stdout); \
({ \
if (__builtin_types_compatible_p (typeof (x), int)) \
printA(x, ##args); \
else \
printB (x,##args); \
})

int main(int argc, char** argv) {
    int a=0;
    print(a);
    print("hello");
    return (EXIT_SUCCESS);
}

PrintA ve printB'den 0 ve merhaba .. çıktılar.


2
int main (int argc, char ** argv) {int a = 0; (a) yazdırır; ( "Merhaba") yazdırmak; dönüş (EXIT_SUCCESS); } printA ve printB'den 0 ve merhaba çıktı ...
Kaptan Barbossa

1
__builtin_types_compatible_p, bu GCC derleyicisine özgü değil mi?
Sogartar

11

Aşağıdaki yaklaşım a2800276'nınkine benzer , ancak bazı C99 makro sihirleri eklendi:

// we need `size_t`
#include <stddef.h>

// argument types to accept
enum sum_arg_types { SUM_LONG, SUM_ULONG, SUM_DOUBLE };

// a structure to hold an argument
struct sum_arg
{
    enum sum_arg_types type;
    union
    {
        long as_long;
        unsigned long as_ulong;
        double as_double;
    } value;
};

// determine an array's size
#define count(ARRAY) ((sizeof (ARRAY))/(sizeof *(ARRAY)))

// this is how our function will be called
#define sum(...) _sum(count(sum_args(__VA_ARGS__)), sum_args(__VA_ARGS__))

// create an array of `struct sum_arg`
#define sum_args(...) ((struct sum_arg []){ __VA_ARGS__ })

// create initializers for the arguments
#define sum_long(VALUE) { SUM_LONG, { .as_long = (VALUE) } }
#define sum_ulong(VALUE) { SUM_ULONG, { .as_ulong = (VALUE) } }
#define sum_double(VALUE) { SUM_DOUBLE, { .as_double = (VALUE) } }

// our polymorphic function
long double _sum(size_t count, struct sum_arg * args)
{
    long double value = 0;

    for(size_t i = 0; i < count; ++i)
    {
        switch(args[i].type)
        {
            case SUM_LONG:
            value += args[i].value.as_long;
            break;

            case SUM_ULONG:
            value += args[i].value.as_ulong;
            break;

            case SUM_DOUBLE:
            value += args[i].value.as_double;
            break;
        }
    }

    return value;
}

// let's see if it works

#include <stdio.h>

int main()
{
    unsigned long foo = -1;
    long double value = sum(sum_long(42), sum_ulong(foo), sum_double(1e10));
    printf("%Le\n", value);
    return 0;
}

11

Bu hiç yardımcı olmayabilir, ancak clang kullanıyorsanız yüklenebilir özniteliğini kullanabilirsiniz - Bu, C olarak derlenirken bile çalışır

http://clang.llvm.org/docs/AttributeReference.html#overloadable

Başlık

extern void DecodeImageNow(CGImageRef image, CGContextRef usingContext) __attribute__((overloadable));
extern void DecodeImageNow(CGImageRef image) __attribute__((overloadable));

uygulama

void __attribute__((overloadable)) DecodeImageNow(CGImageRef image, CGContextRef usingContext { ... }
void __attribute__((overloadable)) DecodeImageNow(CGImageRef image) { ... }

10

Yani demek istediğin - hayır, yapamazsın.

Gibi bir va_argişlev bildirebilirsiniz

void my_func(char* format, ...);

, ancak ilk bağımsız değişken gibi değişken sayısı ve türleri hakkında bir tür bilgi iletmeniz gerekir printf().


6

Normalde, tipin isme eklendiğini veya ismin başına eklendiğini gösteren bir siğil. Makrolarla kaçabileceğiniz bazı örneklerdir, ancak ne yapmaya çalıştığınıza bağlıdır. C'de polimorfizm yoktur, sadece baskı vardır.

Basit genel işlemler makrolarla yapılabilir:

#define max(x,y) ((x)>(y)?(x):(y))

Derleyiciniz typeof'i destekliyorsa , makroya daha karmaşık işlemler eklenebilir. Daha sonra aynı işlemi farklı türleri desteklemek için foo (x) sembolüne sahip olabilirsiniz, ancak farklı aşırı yükler arasındaki davranışı değiştiremezsiniz. Makrolar yerine gerçek işlevler istiyorsanız, adı ada yapıştırabilir ve erişmek için ikinci bir yapıştırma kullanabilirsiniz (denemedim).


Makro tabanlı yaklaşım hakkında biraz daha bilgi verebilir misiniz?
FL4SOF

4

Leushenko'nun cevabı gerçekten havalı - sadece: fooörnek foo(7), FIRSTmakro ve gerçek işlev çağrısında tökezleyen ( (_1, __VA_ARGS__)fazla virgülle kalan GCC) ile derlenmiyor . gibi foo(double).

Bu yüzden cevabı biraz aşırı yüklemeye izin vermek de dahil olmak üzere biraz daha ayrıntılandırmaya karar verdim ( foo(void)- bu biraz sorun yarattı ...).

Şimdi fikir: Farklı makrolarda birden fazla genel tanımlayın ve bağımsız değişkenlerin sayısına göre doğru olanı seçelim!

Bu cevaba dayanarak argüman sayısı oldukça kolaydır :

#define foo(...) SELECT(__VA_ARGS__)(__VA_ARGS__)

#define SELECT(...) CONCAT(SELECT_, NARG(__VA_ARGS__))(__VA_ARGS__)
#define CONCAT(X, Y) CONCAT_(X, Y)
#define CONCAT_(X, Y) X ## Y

Bu güzel, ya biz ya SELECT_1da SELECT_2(ya da eğer isterseniz / ihtiyacınız varsa daha fazla argüman) çözüyoruz, bu yüzden sadece uygun tanımlara ihtiyacımız var:

#define SELECT_0() foo_void
#define SELECT_1(_1) _Generic ((_1),    \
        int: foo_int,                   \
        char: foo_char,                 \
        double: foo_double              \
)
#define SELECT_2(_1, _2) _Generic((_1), \
        double: _Generic((_2),          \
                int: foo_double_int     \
        )                               \
)

Tamam, zaten boşluk yükünü ekledim - ancak, bu aslında C standardı tarafından kapsanmıyor, bu da boş varyasyon argümanlarına izin vermiyor, yani derleyici uzantılarına güveniyoruz !

İlk başta, boş bir makro çağrısı ( foo()) hala bir belirteç üretir, ancak boş bir belirteç üretir. Böylece, sayım makrosu, boş makro çağrısında bile 0 yerine 1 döndürür. Listenin boş olmasına bağlı olarak __VA_ARGS__ koşullu olarak virgül koyarsak, bu sorunu "kolayca" ortadan kaldırabiliriz :

#define NARG(...) ARG4_(__VA_ARGS__ COMMA(__VA_ARGS__) 4, 3, 2, 1, 0)

Bu kolay görünüyordu , ancak COMMAmakro oldukça ağırdır; Neyse ki, konu zaten bir Jens Gustedt bloğunda yer alıyor (teşekkürler, Jens). Temel hile, fonksiyon makrolarının parantez tarafından takip edilmezse genişletilmemesidir, daha fazla açıklama için Jens'in bloguna bir göz atın ... Makroları biraz ihtiyaçlarımıza göre değiştirmeliyiz (daha kısa isimler kullanacağım) ve kısalık için daha az argüman).

#define ARGN(...) ARGN_(__VA_ARGS__)
#define ARGN_(_0, _1, _2, _3, N, ...) N
#define HAS_COMMA(...) ARGN(__VA_ARGS__, 1, 1, 1, 0)

#define SET_COMMA(...) ,

#define COMMA(...) SELECT_COMMA             \
(                                           \
        HAS_COMMA(__VA_ARGS__),             \
        HAS_COMMA(__VA_ARGS__ ()),          \
        HAS_COMMA(SET_COMMA __VA_ARGS__),   \
        HAS_COMMA(SET_COMMA __VA_ARGS__ ()) \
)

#define SELECT_COMMA(_0, _1, _2, _3) SELECT_COMMA_(_0, _1, _2, _3)
#define SELECT_COMMA_(_0, _1, _2, _3) COMMA_ ## _0 ## _1 ## _2 ## _3

#define COMMA_0000 ,
#define COMMA_0001
#define COMMA_0010 ,
// ... (all others with comma)
#define COMMA_1111 ,

Ve şimdi iyiyiz ...

Tek bir blokta tam kod:

/*
 * demo.c
 *
 *  Created on: 2017-09-14
 *      Author: sboehler
 */

#include <stdio.h>

void foo_void(void)
{
    puts("void");
}
void foo_int(int c)
{
    printf("int: %d\n", c);
}
void foo_char(char c)
{
    printf("char: %c\n", c);
}
void foo_double(double c)
{
    printf("double: %.2f\n", c);
}
void foo_double_int(double c, int d)
{
    printf("double: %.2f, int: %d\n", c, d);
}

#define foo(...) SELECT(__VA_ARGS__)(__VA_ARGS__)

#define SELECT(...) CONCAT(SELECT_, NARG(__VA_ARGS__))(__VA_ARGS__)
#define CONCAT(X, Y) CONCAT_(X, Y)
#define CONCAT_(X, Y) X ## Y

#define SELECT_0() foo_void
#define SELECT_1(_1) _Generic ((_1), \
        int: foo_int,                \
        char: foo_char,              \
        double: foo_double           \
)
#define SELECT_2(_1, _2) _Generic((_1), \
        double: _Generic((_2),          \
                int: foo_double_int     \
        )                               \
)

#define ARGN(...) ARGN_(__VA_ARGS__)
#define ARGN_(_0, _1, _2, N, ...) N

#define NARG(...) ARGN(__VA_ARGS__ COMMA(__VA_ARGS__) 3, 2, 1, 0)
#define HAS_COMMA(...) ARGN(__VA_ARGS__, 1, 1, 0)

#define SET_COMMA(...) ,

#define COMMA(...) SELECT_COMMA             \
(                                           \
        HAS_COMMA(__VA_ARGS__),             \
        HAS_COMMA(__VA_ARGS__ ()),          \
        HAS_COMMA(SET_COMMA __VA_ARGS__),   \
        HAS_COMMA(SET_COMMA __VA_ARGS__ ()) \
)

#define SELECT_COMMA(_0, _1, _2, _3) SELECT_COMMA_(_0, _1, _2, _3)
#define SELECT_COMMA_(_0, _1, _2, _3) COMMA_ ## _0 ## _1 ## _2 ## _3

#define COMMA_0000 ,
#define COMMA_0001
#define COMMA_0010 ,
#define COMMA_0011 ,
#define COMMA_0100 ,
#define COMMA_0101 ,
#define COMMA_0110 ,
#define COMMA_0111 ,
#define COMMA_1000 ,
#define COMMA_1001 ,
#define COMMA_1010 ,
#define COMMA_1011 ,
#define COMMA_1100 ,
#define COMMA_1101 ,
#define COMMA_1110 ,
#define COMMA_1111 ,

int main(int argc, char** argv)
{
    foo();
    foo(7);
    foo(10.12);
    foo(12.10, 7);
    foo((char)'s');

    return 0;
}

1

Sadece C ++ kullanamaz ve bunun dışındaki tüm C ++ özelliklerini kullanamaz mısınız?

Hala sadece sıkı C değilse, bunun yerine varyasyon fonksiyonları tavsiye ederim .


3
Kodladığı işletim sistemi için bir C ++ derleyicisi yoksa değil.
Brian

2
sadece bu da değil, içinde isim adı olmayan bir C ABI isteyebilir.
Spudd86


-4

Umarım aşağıdaki kod aşırı yük fonksiyonunu anlamanıza yardımcı olur

#include <stdio.h>
#include<stdarg.h>

int fun(int a, ...);
int main(int argc, char *argv[]){
   fun(1,10);
   fun(2,"cquestionbank");
   return 0;
}
int fun(int a, ...){
  va_list vl;
  va_start(vl,a);

  if(a==1)
      printf("%d",va_arg(vl,int));
   else
      printf("\n%s",va_arg(vl,char *));
}

2
Bir cevap ne yaptığını ve neden çalıştığını açıklamalıdır. Değilse, herhangi bir şeyi anlamasına nasıl yardımcı olabilir?
underscore_d

Burada aşırı yükleme yok.
Melpomene

va_end hiç çağrılmadı
user2262111
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.