Örnek ver
16 Eylül 2020 Çarşamba
std::midpoint - C++20 ile geliyor
11 Eylül 2020 Cuma
std::remove_pointer
Örnek
Tip tipteki pointer sayısını bulmak için özyinelemeli (recursive) olarak Şöyle yaparız
Tip tipteki pointer sayısını bulmak için özyinelemeli (recursive) olarak Şöyle yaparız
#include <type_traits>
template<typename T, int N = 0>
consteval int deref_level()
{
if constexpr (std::is_pointer<T>::value) {
typedef typename std::remove_pointer<T>::type U;
return deref_level<U, N + 1>();
} else {
return N;
}
}
int main() {
return deref_level<int****>(); // Returns 4
}10 Eylül 2020 Perşembe
GNU Runtime - Main'den Önce Çağrılabilecek Metodlar
Giriş
Main'den önce bir sürü metod çağrılır. Açıklaması şöyle.
main'den daha önce çağrılır. Açıklaması şöyle.
__attribute__((constructor) işaretli metodlar
Gcc ile __attribute__((constructor) olarak işaretli bir metod main'den önce veya sonra çağrılabilir.
Yukarıdaki şekilde constructors1...n ile gösterilen kutucukta bu çağrıların main'den önce olduğu görülebilir.
Main'den önce çağırma örneği:
Main'den önce argc vve argv parametrelerine erişebiliriz. Şöyle yapalır.
Main'den önce bir sürü metod çağrılır. Açıklaması şöyle.
Main is usually a programmer-defined entry point, while entry is defined by the compiler, it's doing many other operations such as libc initializations, heap allocation, and so on, and eventually, call the user-defined main entry point. You can see main as a callback function that defined by the user and eventually called by entry._start metodu
main'den daha önce çağrılır. Açıklaması şöyle.
With the GNU C library, on x86-64, execution starts at the _start entry point, which calls __libc_start_main to set things up, and the latter ends up calling main. But before calling main, it calls a number of other functions, which causes various pieces of data to be written to the stack. The stack’s contents aren’t cleared in between function calls, so when you get into main, your stack contains leftovers from the previous function calls.shell veya gui'den yapılan execve() çağrısı ile tetiklenen loader önce argc, argv, envp değişkenlerini stack'a doldurur. Daha sonra uygulamamın _start() metodunu çağırır. Şeklen şöyledir.
// Compile it with gcc -nostartfiles
void _start(){
int ret = my_main();
exit(ret);
}
int my_main()
{
puts("This is a program without main!\n");
return 0;
}
__libc_start_main metodu
Örnek
Açıklaması şöyle. Burada amaç dynamic loader bazı metodları çalıştırmadan araya girmek.
A trick you can use on all platforms is to LD_PRELOAD a small library which overides __libc_start_main() and does a pointless system call like write(-1, "IT_STARTS_HERE", 14) before calling the original __libc_start_main().
Şöyle yaparız
#define _GNU_SOURCE#include <dlfcn.h>#include <unistd.h>#include <errno.h>#include <err.h>int __libc_start_main(int (*main)(int,char**,char**), int ac, char **av,int (*init)(int,char**,char**), void (*fini)(void),void (*rtld_fini)(void), void *stack_end){typeof(__libc_start_main) *next = dlsym(RTLD_NEXT, "__libc_start_main");write(-1, "IT_STARTS_HERE", 14); errno = 0;return next(main, ac, av, init, fini, rtld_fini, stack_end);}
Gcc ile __attribute__((constructor) olarak işaretli bir metod main'den önce veya sonra çağrılabilir.
Yukarıdaki şekilde constructors1...n ile gösterilen kutucukta bu çağrıların main'den önce olduğu görülebilir.
Main'den önce çağırma örneği:
#include <stdio.h>
void beforeMain (void) __attribute__((constructor));
void beforeMain (void)
{
printf ("\nThis is before main\n");
}
int main ()
{
printf ("\nThis is my main \n");
return 0;
}
Main'den sonra çağırma örneğistatic void before_main(void) __attribute__((constructor));
static void after_main(void) __attribute__((destructor));
static void before_main(void)
{
/* This is run before main() */
}
static void after_main(void)
{
/* This is run after main() returns (or exit() is called) */
}
.init_arrayMain'den önce argc vve argv parametrelerine erişebiliriz. Şöyle yapalır.
#include <stdio.h>
static int printargs(int argc, char** argv, char** env) {
puts("In printargs:");
for (int i = 0; i < argc; ++i)
printf(" Arg %d (%p) '%s'\n", i, (void*)argv[i], argv[i]);
return 0;
}
/* Put the function into the init_array */
__attribute__((section(".init_array"))) static void *ctr = &printargs;
Bu kodu bir .so dosyasında kullanırsak sonucu şöyle görürüz.$ gcc -o printargs.so -std=c11 -shared -fpic printargs.c
$ LD_PRELOAD=./printargs.so /bin/echo Hello, world.
In printargs:
Arg 0 (0x7ffc7617102f) '/bin/echo'
Arg 1 (0x7ffc76171039) 'Hello,'
Arg 2 (0x7ffc76171040) 'world.'
Hello, world.
7 Eylül 2020 Pazartesi
Generic Lambda
Giriş
C++14 ile yapılabilir. Eğer C++14 kullanamıyorsak lambda yerine aynı işlevi gören basit functor'lar da kullanılabilir.
Generic metod kullanarak şöyle yaparız
Şöyle yaparız.
İstersek auto şeklinde parametre de geçebiliriz. Şöyle yaparız.
C++14 ile yapılabilir. Eğer C++14 kullanamıyorsak lambda yerine aynı işlevi gören basit functor'lar da kullanılabilir.
Generic metod kullanarak şöyle yaparız
// effectively the same as (1)
template <typename T>
void l() {
T x;
}
Generic struct kullanarak şöyle yaparız.template<typename T>
struct Functor
{
void operator () () { T var; ... }
}
Örnek
// (1)
template <typename T>
auto l = [] () {
T x;
};
int main() {
l<int>();
}
Örnekİstersek auto şeklinde parametre de geçebiliriz. Şöyle yaparız.
template <typename T>
auto l = [] (auto y) {
T x = 42;
std::cout << x + y << std::endl;
};
Tek sıkıntı lambda'nın çağrıldığı namespace içinde olması gerekmesi.Örnek
Şöyle yaparız
auto gl = [](auto a, auto b) { return a < b; };
std::cout << std::boolalpha
<< gl(1, 2) << " " // true ("<int, int>")
<< gl(3.4, 2.2) << " " // false ("<double, double>")
<< gl(98, 'a'); // false ("<int, char>")
Gcc Extension
Lambda tanımı şöyledir.
lambda introducer [capture param1, capture param2] şeklindedir.lambda-introducer lambda-declaratoropt compound-statement
lambda declartor ise parametre alıyorsa (param1,param2) şeklindedir ve isteğe bağlıdır.
gcc bir extension ile şöyle kullanabilmemizi sağlar.
[]<typename>(){}
Örnek 1Şöyle yaparız.
int main() {
auto l = []<typename>(){};
l.operator()<void>();
}
Örnek 2Şöyle yaparız.
auto l = []<typename T>(T const& x){
std::cout << __PRETTY_FUNCTION__ << " " << x << std::endl;
};
l(42);
l("Hello world");
Çıktı olarak şunu alırız.main()::<lambda(const T&)> [with T = int] 42
main()::<lambda(const T&)> [with T = char [12]] Hello world
Kaydol:
Kayıtlar (Atom)