четверг, 25 июня 2009 г.

нечто очевидное

typedef struct some_struct
{
int dummy;
unsigned long long some_field[];
} some_type;

int main() {
int buf;
buf = (int)&((some_type*)0)->some_field[0];
printf("buf = (int)&((some_type*)0)->some_field[0];\n");
printf("sizeof(unsigned long long): %d, sizeof(int): %d, \
sizeof(some_type): %d\n",
sizeof(unsigned long long), sizeof(int),
sizeof(some_type));
printf("buf: %d\n\n", buf);

buf = (int)&((some_type*)0)->some_field[1];
printf("buf = (int)&((some_type*)0)->some_field[1];\n");
printf("sizeof(unsigned long long): %d, sizeof(int): %d, \
sizeof(some_type): %d\n",
sizeof(unsigned long long), sizeof(int),
sizeof(some_type));
printf("buf: %d\n\n", buf);

}


1. (some_type*)0 создали на стеке некий объект и преобразовали его к типу "указатель на структуру some_type". Т.о. по адресу памяти, на который указывает (some_type*)0 будет находится некий мусор, но память будет выделена;

[#########################################################]
[|########################################################]

2. ((some_type*)0)->some_field[1] тут произошло смещение на 1 позицию размером в sizeof(typeof(some_field));

[#########################################################]
[#################################|#######################]

3. &((some_type*)0)->some_field[1] взяли адрес полученной ячейки памяти. Фактически, уже тут мы получаем искомое - объем занимаемой памяти;

4. (int)&((some_type*)0)->some_field[1] компилятор перестал ругаться;

Вуаля, в выражении
(int)&((some_type*)0)->some_field[0]
нам не нужно знать типы структур и полей, чтобы вычислить размер памяти.

понедельник, 22 июня 2009 г.

Использование pthread_create в C++

Часто возникает необходимо создать поток, программируя на C++, с помощью стандартного вызова pthread_create(). На вход он, кроме всего прочего, принимает указатель на функцию, которая и будет работать в потоке. Однако, если мы пишем на C++, то нам необходимо запускать в потоке метод класса. Напрямую метод класса отдать на вход вызову pthread_create не получится.
Вот пример конструкции, которая позволит обойти это:

/* pthr_tst.h */
#ifndef PTHR_TST_H
#define PTHR_TST_H

class PTHR_TST;

void *testThr(PTHR_TST * p);

class PTHR_TST {
    public:
       PTHR_TST();
       ~PTHR_TST();
       int createThreads();

    protected:
       friend void *testThr(PTHR_TST * p);

};

#endif

/* pthr_tst.cpp */
#include
#include "pthr_tst.h"

PTHR_TST::PTHR_TST() {}
PTHR_TST::~PTHR_TST() {}

void * testThr(PTHR_TST *p) {
    PTHR_TST * t = p;
    // t->someMethod();
    // someMethod() будет работать в потоке
    delete t;
    return 0;
}

int createThreads() {
    /* тоже хинт. g_tattr используется для задания
    максимального используемого объема памяти потоком */
    pthread_attr_t g_tattr;
    size_t ss=100*1024;
    pthread_attr_setstacksize(&g_tattr, ss);

    pthread_t testthr;
    pthread_create(&testthr, &g_tattr, (void *(*)(void*)) testThr, this);
}

понедельник, 1 июня 2009 г.

О размерности массива [C++]

Бывают случаи, когда необходимо узнать размерность массива. Делается это довольно просто:

int Mas[] = {4, 8, 15, 16, 23, 42};
int Size_Array = sizeof(Mas) / sizeof(int);

В памяти элементы массива располагаются последовательно, а объем памяти выделяемой под массив определяется как произведение всех размерностей массива (общее число элементов) умноженное на длину типа данных массива.