LINUX.ORG.RU

Сообщения osox

 

linux/list.h

Форум — Development

Всем привет как правильно считать требуемый размер ?

struct item
{
	list_head hdr;
	char cookie[];
};

LIST_HEAD(my_list);

item* p = malloc(sizeof(item) + strlen(str) + 1); ??
vs 
item* p = malloc(sizeof(item.hdr) + strlen(str) + 1); ??
vs
????????????????????????????????

strcpy(p->cookie, str);
list_add_tail(&p->hdr, &my_list);

osox
()

[C++] Incompatible type conversion

Форум — Development

Всех приветствую. в C удобно когда указатель void* неявно преобразуется к не void* указателю в C++ приходится писать явный каст Что бы такого поломалось в системе типов C++ если бы было разрешено неявное преобразование void* в нужный тип как в C ?

 

osox
()

functional object

Форум — Development

всех приветствую в исходниках STL функтор передается по значению

template<class _InIt,
	class _Fn1> inline
	_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
	{	// perform function for each element
	for (; _ChkFirst != _ChkLast; ++_ChkFirst)
		_Func(*_ChkFirst);
	return (_Func);
	}

можно исправить

_Func(*_ChkFirst); на (*_Func)(*_ChkFirst);
перегрузить еще одну операцию в функторе
class type{
	... buff[VERY_BIG_SIZE];
public:
	type& operator*(){return *this;}
	void operator()(... e){}
};
и можно передавать и по значению и по указателю эффективней ?

template<class _InIt,
	class _Fn1> inline
	_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
	{	// perform function for each element
	for (; _ChkFirst != _ChkLast; ++_ChkFirst)
		(*_Func)(*_ChkFirst);
	return (_Func);
	}

например

type obj; for_each(..., ..., &obj);
          for_each(..., ...., obj);

osox
()

list_for_each

Форум — Development

вот интересно в linux/list.h есть такой код

#define list_for_each(pos, head) \
        for (pos = (head)->next; prefetch(pos->next), pos != (head); \
                pos = pos->next)
если написать такой код
 
struct list_head *head, *pos, **ppos = &pos;
list_for_each(*ppos, head)
{
        //...
}
пишет ошибку из за неправильного приоритета *ppos->next а если так (pos)->next макрос поправить то ок вот как ниже
#define list_for_each(pos, head) \
      for (pos = (head)->next; prefetch((pos)->next), pos != (head); \
                pos = (pos)->next)
то ок ... зачем было запрещать *pos выражение в аргументе макроса ? оно же корректное можно конечно перед вызовом в скобки взять
list_for_each((*ppos), head)
{
        //...
}
но это семантически абсолютно неочевидно

osox
()

Всем! Всем! Всем!

Форум — Development

Приветствую Всех заглянувших надеюсь вам будет интересно похоливарить ))) у меня есть вопрос к знатокам Си утром после бессонной ночи попивая кофе и затягиваясь смачно сигаретой я наткнулся на такую врезку из книги Искусство программирования на С авторы Ричард Хэзфилд Лоуренс Кирби предупреждаю первый сабж у меня хватило лени не компилировать порассуждаем логически (уже скомпилил) а вот второй сабж я скомпилил и обломался но обо всем по порядку и так врезка

/* 
 *  Если уж мы говорим о sprintf может быть стоит заметить что следующая обычная конструкция
 *  sprintf(mystring, "%s%d%s%f", mystring, j, otherstring, d);
 *  приводит к неопределенному поведению программы поскольку компилятор 
 *  может проводить запись в mystring в таком порядке в каком хочет возможно начиная с конца выражения
 *  а может сделать и по другому
 *  Если вы дейсвительно хотите сделать это то в качестве области для временного хранения
 *  используйте другую строку
 *  sprintf(thirdstring, "%s%d%s%f", mystring, j, otherstring, d);
 *  strcpy(mystring, thirdstring);
 */

и как всегда на этом объяснения закончились какой бред подумал я начал и обдумывать что вообще он имел ввиду непонятно ясно что аргументы он вычислит рандомно в худшем случае но у нас в аргументах нет побочных эффектов на стеке (поcле двух обязательных аргументов) в кадре предыдущей функции первым будет копия указателя mystring выше копия j выше копия othersttring выше копия d я все пониманию вычисления рандомно аргументов может быть но все побочные эффеты заканчиваются при вызове функции ладно sprintf начнет парсить строку первый найдет %s и возмет из стека указатель на mystring потом на j и так далее где тут неопределенное поведение я не пониманию все законно несколько смущает что из mystring будет читатся байт и писаться сразу же в нее тоесть мы проосто получим копию mystring а остальные аргументы вообще в примере ни о чем не говорят что имел автор ввиду говоря эту фразу

«поскольку компилятор может проводить запись в mystring в таком порядке в каком хочет возможно начиная с конца выражения а может сделать и по другому»

жути нагоняет ))) при чем тут компилятор вообще ? это какой то бред или я чего то непонимаю если уж автор пишет что это баг надо показать баг людям будет неинтересно почему плохо что думаете по этому поводу и почему это плохо вообщем после этой врезки я решил набросать маленькую функцию и проверить в каком порядке мой компилятор будет вычислять аргументы она имеет такой вид

/*
 * int main(void)
 * {
 *   int dec = 0;
 *   int a, b, c, d;
 *         
 *   show((++dec,a=dec), (++dec,b=dec), (++dec,c=dec), (++dec,d=dec));
 * }
 */
как можно заметить я хотел в вызываемой функции посмотреть какой аргумент каким по счету вызывался но как же я удивился когда увидел следующую картину 4 4 4 4 снова куча вопросов я всегда считал что оператор запятая устанавливает порядок вычисленния строго слева направо с вычислением всех побочных эффетов но только в тех местах где запятая не играет другую роль например вызов функций и инициализация поэтому я каждый аргумент заключил в скобки сразу перед компиляцией в этом случае запятая задает порядок вычисления получилось каждый аргумент это первичное выражение в котором сначало делается инкремент со всеми побочными эфыектами а потом аргумент который и пойдет в стек получает значение типом и значением этого выражения является тип и значение операнда слева от знака присваивания тоесть я должен был получить номера в каком порядке вычислялись аргументы но получилась на выходе в точности до наоборот посмотрел код сгенерированный компилятором вот он
00401030 >/$ 55             PUSH EBP /* сохраняем стэковый кадр предыдущей функции */
00401031  |. 8BEC           MOV EBP,ESP /* настраиваем на новый */
00401033  |. 83EC 14        SUB ESP,14 *. ./* выделяем немного стека */
00401036  |. C745 FC 000000>MOV DWORD PTR SS:[EBP-4],0 /* инициализируем dec *.
0040103D  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]  /*
00401040  |. 83C0 01        ADD EAX,1                                        *
00401043  |. 8945 FC        MOV DWORD PTR SS:[EBP-4],EAX   *
00401046  |. 8B4D FC        MOV ECX,DWORD PTR SS:[EBP-4]  *
00401049  |. 83C1 01        ADD ECX,1                                        *
0040104C  |. 894D FC        MOV DWORD PTR SS:[EBP-4],ECX  * прибавляем к dec 4
0040104F  |. 8B55 FC        MOV EDX,DWORD PTR SS:[EBP-4]  *
00401052  |. 83C2 01        ADD EDX,1                                        *
00401055  |. 8955 FC        MOV DWORD PTR SS:[EBP-4],EDX   *
00401058  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]  *
0040105B  |. 83C0 01        ADD EAX,1                                       *
0040105E  |. 8945 FC        MOV DWORD PTR SS:[EBP-4],EAX  */
00401061  |. 8B4D FC        MOV ECX,DWORD PTR SS:[EBP-4]  
00401064  |. 894D F0        MOV DWORD PTR SS:[EBP-10],ECX  /* инициализиуем a *.
00401067  |. 8B55 FC        MOV EDX,DWORD PTR SS:[EBP-4]
0040106A  |. 8955 EC        MOV DWORD PTR SS:[EBP-14],EDX /* инициализируем b */
0040106D  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00401070  |. 8945 F4        MOV DWORD PTR SS:[EBP-C],EAX   /* инициализируем c */
00401073  |. 8B4D FC        MOV ECX,DWORD PTR SS:[EBP-4]
00401076  |. 894D F8        MOV DWORD PTR SS:[EBP-8],ECX   /* инициализируем d */
00401079  |. 8B55 F0        MOV EDX,DWORD PTR SS:[EBP-10]
0040107C  |. 52             PUSH EDX                                 ; /Arg4   /* пушим a */
0040107D  |. 8B45 EC        MOV EAX,DWORD PTR SS:[EBP-14]            ; |
00401080  |. 50             PUSH EAX                                 ; |Arg3   /* пушим b */
00401081  |. 8B4D F4        MOV ECX,DWORD PTR SS:[EBP-C]             ; |
00401084  |. 51             PUSH ECX                                 ; |Arg2  /* пушим c */
00401085  |. 8B55 F8        MOV EDX,DWORD PTR SS:[EBP-8]             ; |
00401088  |. 52             PUSH EDX                                 ; |Arg1 /* пушим d */
00401089  |. E8 72FFFFFF    CALL move.show                           ; \show
0040108E  |. 83C4 10        ADD ESP,10 /* прибавляем к указателю 16 байт занятые копиями локальных переменных */
00401091  |. 33C0           XOR EAX,EAX /* устанавливаем код возврата функции */
00401093  |. 8BE5           MOV ESP,EBP ./* настраиваем указатель что бы он указывал на адрес с адресом предыдущего кадра */
00401095  |. 5D             POP EBP        /* восстанавливаем предыдущий кадр */
00401096  \. C3             RETN ./* снимаем адрес возврата и выходим /*
что мы видим ?

приведу вызов функции чтоб не терять ниточки рассуждения show((++dec,a=dec), (++dec,b=dec), (++dec,c=dec), (++dec,d=dec)); он сначало увеличил четыре раза значение dec потом скопировал 4 в каждый аргумент который и запушил в стэк теперь вопрос почему это так я себе видел это так выбирается рандомно(рандомно не в прямом смысле))) первичное выражение делается инкремент а потом присваивание и так для всех аргументов потому что запятая в первичном выражениии задает порядок жесткий на вычисление в итоге вызываемая функция должна была получить номера кто в каком порядке вычилялся а не четыре 4 но все с точностью до наоборот получилось он сначало выдрал из каждого выражения dec увеличив его на 4 а потом всем скопом присвоил значение 4 вообщем загадка если есть люди знающие расскажите все подробно по первому и по второму сабжу чтоб заполнить этот пробел в знаниях тем кто дочитал до конца респект )))

osox
()

RSS подписка на новые темы