Variadic Function etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Variadic Function etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

23 Ekim 2017 Pazartesi

Variadic Function

Giriş
Variadic Function değişken sayıda parametre alabilen metod anlamına gelir. 

Variadic Function Tarihçesi
Açıklaması şöyle. İlginç bir şekilde C diline girmeden önce C++'ta kullanılmış.
To add to the other answers, the func(arg, ...) syntax first developed in C++, and then was incorporated into the ANSI C standard, sometime between 1984 and 1988.
Variadic Parametreler Nasıl Geçilirler
Bu konuda C++ standardı bir açıklama getirmiyor. Derleyiciler kendi çözümlerini üretmişler.  Cevapta stack kullanılması açıklanmış.

Non-POD Type
non-pod tiplerin - örneğin bir sınıf - variadic parametre olarak geçilmesi tanımsız davranış. Yani yapılmaması gerekir. Açıklaması şöyle
You cannot pass non-POD types to C-style variadic functions
Macrolar
va_list, va_start, va_end,va_arg macroları için  şu satırı dahil ederiz.
#include <stdarg.h>
va_list macrosu
Önce bir metod tanımlarız. Şöyle yaparız.
void setList(int count, ...) {
  ...
}
Metodun içinde parametreleri okumak için bir liste oluştururuz. Şöyle yaparız.
void setList( int count, ... ) {
  va_list numbers;
  va_start (numbers, count);
  ...
  va_end (numbers);
}
va_start macrosu va_list değişkenine yazdığı için va_list memset ile sıfırlamaya gerek yok. Şu kod fazladan iş yapıyor.
va_list args;
memset(&args, 0, sizeof(va_list));

va_start(args, xxx);
...
va_end(args);
va_start macrosu - va_list + int
İmzası şöyle
void va_start(va_list ap, last);
Açıklaması şöyle.
The va_start() macro initializes ap for subsequent use by va_arg() and va_end(), and must be called first.
Açıklaması şöyle.
2 The va_start macro shall be invoked before any access to the unnamed arguments.

3 The va_start macro initializes ap for subsequent use by the va_arg and va_end macros. Neither the va_start nor  va_copy macro shall be invoked to reinitialize ap without an intervening invocation of the va_end macro for the same ap .
Şöyle yaparız.
void setList(int count, ... ) {
  va_list numbers;
  va_start (numbers, count);
  ...
  va_end (numbers);
}
va_start macrosu - va_list + char *
Şöyle yaparız.
void debug(int msglevel, const char *fmt, ...)
{
  va_list va;
  va_start(va, fmt);
  vfprintf(stderr, fmt, va);
  va_end(va);
}
va_end macrosu
Aynı metod için listeyi temizlememiz gerekir. Açıklaması şöyle
Each invocation of va_start() must be matched by a corresponding invocation of va_end() in the same function.
va_arg macrosu - int
Parametreye va_arg ile şöyle erişiriz.
for(int n = 0; n < count; n++)
  int num = va_arg(numbers, int);
Bazı Önemli Variadic Metodlar
printf
printf yazısına taşıdım.

vsnprintf
vsnprintf yazısına taşıdım.

vfprintf
Şu satırı dahil ederiz.
#include <cstdio>
Şöyle yaparız.
void debug(int msglevel, const char *fmt, ...)
{  
  va_list va;
  va_start(va, fmt);
  vfprintf(stderr, fmt, va);
  va_end(va);
}
Array Geçmek
Variadic Function yerine array geçmek daha kolay olabilir.

C++
C++'ta Variadic Function'ların bence yeri yok. Artık kullanılmamalı. st::array, std::vector, std::initializer_list ve hatta variadic template bile kullanılabilir.