Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.137.220.120] |
|
Страницы: (12) 1 2 [3] 4 5 ... 11 12 все ( Перейти к последнему сообщению ) |
Сообщ.
#31
,
|
|
|
Цитата OpenGL @ Попробуй ответить на этот вопрос самостоятельно. Тебе для этого надо знать только то, что я не пишу на Си - остальную информацию для ответа ты можешь получить из моих постов этой темы. Ну то есть никогда. К слову - когда я писал на Си, после С++ - да было больно, с непревычки, но и там - я как то обходился без goto. А значит такие "паттерны" просто говорят о том, что автору было лень придумывать что то другое и умное(ну бывает такое), либо он обычный быдлокодер, пишет на отвали. Цитата OpenGL @ Киля, перечитай внимательней. Простейший паттерн: 1) сложная инициализация локальных переменных 2) главные действия, которые могут прерваться из разных мест, после чего надо перейти в 3) 3) очистка того, что создали в 1) Ты сейчас просто сформулировал некий алгоритм, куда наложил некие ограничение, из которых как то следует, что самый простой способ реализовать именно этот алгоритм, путем использования goto. Но ведь у тебя не возникает ведь такой алгоритм на том языке на которым ты пишешь? Что, в Си нет средств обойти это без использования goto ? Хорошо, пусть бьет каждую сущность на отдельные функции какие то, блоки. Вот я беру пример с МСДНа с кучкой goto, это при том, что он тамписан на С++, т.к. юзаются классы/COM/еще какая нибудь фигня, и переписываю это все без goto. Вы же сейчас или специально или я не пойму, выдумываете какие то ограничения, которыми в реальной жизни вы не ограничены. Добавлено Цитата OpenGL @ твоим паттерном do..while более читабельным не сделать, если в 2 у тебя есть циклы, из которых ты можешь выходить сразу в 3) Так в данном случае намеренно усложняется задача. Т.е. вместо того, чтобы посидеть подумать как всего этого избежать, и сделать код более удобочитаемым и расширяемым, вы решили юзать goto. А что ты будешь делать(ну или Qraizer, cppasm, кто там еще топил? Fester) если дальше добавятся еще 10 вложенных циклов, и из каждого при определенном условии нужно выпрыгнуть на очистку ресурсов? Я так полагаю вы будете заводить 10 разный меток, и прыгать? Да? Судя по всему да. Отличный подход, и во что превратится этот код? Это будет все еще паттерн? Цитата OpenGL @ Ну и до кучи могу напомнить эту тему - в ней был пример, когда с помощью goto вообще заходят внутрь тройного цикла, и более читабельный вариант того примера, но без goto, никто, включая тебя, так и не родил. А пример найти можешь? Я помню там Qraizer его приводил, но я не помню смысл примера. Если на пример не накладываются ограничения - значит это исключительная ситуация. И ты сам прекрасно должен понимать, что запрыгивание внутрь тройного цикла - больше смахивает на какой то грязный хак или даже костыль в перемешку с говнокодом, чем на паттерн или обычный подход в программировании. Так что с этим примером так же мимо я думаю. Искать мне его лень. |
Сообщ.
#32
,
|
|
|
Цитата KILLER @ К слову - когда я писал на Си, после С++ - да было больно, с непревычки, но и там - я как то обходился без goto. А значит такие "паттерны" просто говорят о том, что автору было лень придумывать что то другое и умное(ну бывает такое), либо он обычный быдлокодер, пишет на отвали. Когда я писал на Си - тоже не возникало. Вот только писал я на нём программы в сотню-другую строк максимум. Если же заглянуть в любой крупный проект на нём (например,вот тебе первый попавшийся файл из nginx-а), то goto там - сплошь и рядом, и при этом куда переходит выполнение кода - прекрасно видно. Цитата KILLER @ Но ведь у тебя не возникает ведь такой алгоритм на том языке на которым ты пишешь? Такой алгоритм? Возникает постоянно, но см. выше - на си я не пишу, поэтому данный случай прекрасно разрруливается другими средствами. Цитата KILLER @ Что, в Си нет средств обойти это без использования goto ? Раз он там используется повсеместно - видимо, нет Цитата KILLER @ А пример найти можешь? Я уже тему нашёл. Если тебе лень перечитывать 18 страниц, то мне тем более лень это делать Суть примера простая - есть тройной цикл со сложной логикой счётчиков (не просто for i,j,k = 0..n), он длинный, поэтому его можно прерывать. Но если он прервался - надо прочитать значения счётчиков, на которых мы остановились, после чего как ни в чём не бывало зайти внутрь циклов - всё просто и понятно. Структурный вариант в той теме был, но с goto он мог соревноваться только с краткостью записи, но никак не с понятностью (там сложная логика в условиях выхода из циклов, и неочевидный инкремент были). |
Сообщ.
#33
,
|
|
|
Цитата А что ты будешь делать(ну или Qraizer, cppasm, кто там еще топил? Fester) если... Я тебе уже много раз говорил, что если использование goto делает код более понятным, то момно и нужно использовать goto. Если ты дописываешь какие-то конструкции только ради того, чтобы избавиться от goto, то ты пишешь говнокод. |
Сообщ.
#34
,
|
|
|
Цитата KILLER @ Я так полагаю вы будете заводить 10 разный меток, и прыгать? Да? Нет. У меня деструкторы есть для этого. И зачем 10 меток? Метка очистки обычно одна. Если их нужно больше, то я, если бы писал на си, подумал бы об упрощении, наверное. |
Сообщ.
#35
,
|
|
|
Цитата OpenGL @ Вот только писал я на нём программы в сотню-другую строк максимум. Если же заглянуть в любой крупный проект на нём (например,вот тебе первый попавшийся файл из nginx-а), то goto там - сплошь и рядом, и при этом куда переходит выполнение кода - прекрасно видно. То есть если это файл из nginx - значит там автоматом не может быть говнокода? Я его начал мотать по твоей ссылке, не выдержал нажал поиск, первый же встретившийся goto - посмотри на саму функцию, ее по хорошему уже можно было только разбить на 3-4 функций. Зачем такие большие функции писать? Может быть от этого и юзают там goto? Кто то пишет крупные проекты в одной функции main, и считает что это норма. Я видел функцию длинной в 5 тысяч строк кода. Это что нормально? Если бы автор перепроектировал свой код, думаю можно было сделать его более удобочитаемым. Сам файл 5 тыс строк кода. Это нормально? Ты так же бы это все написал? В таком стиле? Я не знаю, я не курил этот код, но думается мне, возможно один этот *.с файл превратился в 10 файлов или даже в подпроект. Я лично считаю это плохим подходом, когда у тебя файл в 5 тыс строк, там же черт ногу сломит. Потому что такой код потом сопровождать очень сложно. Если это автор писал для себя, и будет сам лично его сопровождать, то я тут спорить не буду, пусть хоть все 5 тыс строк кода пишет на одних goto в одной функции. Его право. Цитата OpenGL @ Такой алгоритм? Возникает постоянно, но см. выше - на си я не пишу, поэтому данный случай прекрасно разрруливается другими средствами. Тот, который ты придумал. Ну вот выше я переписал код cppasm, там похожая проблема. Мне мой подход нравится больше. При этом я вроде переписал в С стиле, не прибегая к средствам С++. Что я сделал не так? Может вы сейчас придеретесь к количеству строчек? Типа у него 10, а у меня 20 ? Цитата OpenGL @ Раз он там используется повсеместно - видимо, нет Где там? В С? Нет, не повсеместно. Но, изначально речь зашла про майкрософт, а у них не только в Си коде goto, открой ATL/MFC исходники посмотри. Что используя С++ нельзя обойтись без goto? Цитата OpenGL @ Я уже тему нашёл. Если тебе лень перечитывать 18 страниц, то мне тем более лень это делать Суть примера простая - есть тройной цикл со сложной логикой счётчиков (не просто for i,j,k = 0..n), он длинный, поэтому его можно прерывать. Но если он прервался - надо прочитать значения счётчиков, на которых мы остановились, после чего как ни в чём не бывало зайти внутрь циклов - всё просто и понятно. Структурный вариант в той теме был, но с goto он мог соревноваться только с краткостью записи, но никак не с понятностью (там сложная логика в условиях выхода из циклов, и неочевидный инкремент были). Понимаешь, лично я не ограничен каким либо одним средством и костылем. Возможно задачу стоило переписать на другом языке, возможно стоило вообще по другому ее сформулировать и решать совершенно с другим подходом. Там лишь обсуждалась, на сколько я помню, конкретная реализация, которую предлагалось переписать без goto. но ведь так можно написать абсолютно любой грязный хак, сказать вот есть вот именно вот такое условие - на перепиши без грязного хака. И ты скажешь - да, при такой постановке задачи, и при таких условиях - это решается только грязным хаком. Но это ведь не означает, что это единственно верное решение задачи в целом? Цитата Fester @ Я тебе уже много раз говорил, что если использование goto делает код более понятным, то момно и нужно использовать goto Так приведи мне хоть один пример, когда goto делает код более понятным? Цитата OpenGL @ Нет. У меня деструкторы есть для этого. И зачем 10 меток? Ну как зачем. Разные условия потому что, разное поведение должно быть в разных подциклах. Можно ведь сформулировать задачу по разному, и ты скажешь - а что вообще требуется? И почему задача сформулирована именно вот так, а не вот эдак. И ты будешь абсолютно прав. И вот это я вам и пишу, а вы рассказываете о каких то мифических вещах, приводя условяи с ограничениями. Вот есть вот у меня 5 вложенных циклов с тремя goto - перепеши чтоб 5 вложенных циклов осталось ,а goto исчез. А зачем так делать? Может быть проще вообще каждый подцикл вынести в отдельную функцию? Почему я должен переписывать именно вот так, а не кардинально менять алгоритм? Я вот это не понимаю. Добавлено К слову, вот пост https://forum.sources.ru/next/index.php?sho...dpost&p=3190250 Qraizer Вот код: #include <windows.h> #include <io.h> #include <conio.h> #include <fstream> #include <iostream> int main() { int i, j, k, l; if (_access("savedstate.dat", 4) == 0) // Проверить, нет ли сохранённого состояния от предыдущего запуска { // Если есть, восстановить и продолжиться std::ifstream inFile("savedstate.dat"); bool ok = true; ok = ok && inFile.read(reinterpret_cast<char*>(&i), sizeof(i)).gcount() == sizeof(i); ok = ok && inFile.read(reinterpret_cast<char*>(&j), sizeof(j)).gcount() == sizeof(j); ok = ok && inFile.read(reinterpret_cast<char*>(&k), sizeof(k)).gcount() == sizeof(k); ok = ok && inFile.read(reinterpret_cast<char*>(&l), sizeof(l)).gcount() == sizeof(l); if (ok && (inFile.good() || inFile.eof())) { std::cout << "The saved state is successfully restored." << std::endl; goto resume; } else return std::cerr << "The saved state restoring error. State file is wrong." << std::endl, 1; } for (i=0; i<10; ++i) { for (j=i; j<10; ++j) { for (k=j; k<10; ++k) { for (l=k; l<10; ++l) { resume: if (kbhit() && getch() == '\x1B') // Проверить, не просят ли нас ESCпом прерваться { // Если да, сохранить состояние и выйти if (_access("savedstate.dat", 2) == 0) remove("savedstate.dat"); std::ofstream outFile("savedstate.dat"); bool ok = true; ok = ok && outFile.write(reinterpret_cast<char*>(&i), sizeof(i)).good(); ok = ok && outFile.write(reinterpret_cast<char*>(&j), sizeof(j)).good(); ok = ok && outFile.write(reinterpret_cast<char*>(&k), sizeof(k)).good(); ok = ok && outFile.write(reinterpret_cast<char*>(&l), sizeof(l)).good(); if (!(ok && (outFile.good() || outFile.eof()))) return std::cerr << "The state saving error." << std::endl, 1; return std::cout << "The state successfully saved." << std::endl, 2; } /* ... */ std::cout << "i = " << i << ", j = " << j << ", k = " << k << ", l = " << l << std::endl; Sleep(1); } } } } if (_access("savedstate.dat", 2) == 0) remove("savedstate.dat"); return 0; } Действительно, что тут не понятного. Без goto переписать ну просто не реально. Добавлено Причем это не Сишный код, а самый что ни на есть С++сный. Добавлено Прод код майкрософта из atlmfc: inline HRESULT CSecurityDescriptor::SetPrivilege( _In_z_ LPCTSTR privilege, _In_ BOOL bEnable, _In_ HANDLE hToken) { TOKEN_PRIVILEGES tpPrevious; TOKEN_PRIVILEGES tp; DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); LUID luid; HANDLE hTokenUsed; if (!LookupPrivilegeValue(NULL, privilege, &luid )) goto _Error; // if no token specified open process token if (hToken != 0) hTokenUsed = hToken; else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenUsed)) goto _Error; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = 0; memset(&tpPrevious, 0, sizeof(tpPrevious)); if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious)) goto _Error_CloseHandle; tpPrevious.PrivilegeCount = 1; tpPrevious.Privileges[0].Luid = luid; if (bEnable) tpPrevious.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED; else tpPrevious.Privileges[0].Attributes &= ~SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tpPrevious, cbPrevious, NULL, NULL)) goto _Error_CloseHandle; if(hToken == 0) CloseHandle(hTokenUsed); return S_OK; HRESULT hr; _Error: hr = AtlHresultFromLastError(); return hr; _Error_CloseHandle: hr = AtlHresultFromLastError(); if (hToken == 0) CloseHandle(hTokenUsed); return hr; } Еще один продакшн код майкрософта из atlmfc inline BOOL Parse(_In_z_ LPCTSTR lpszUrl) { ATLENSURE(lpszUrl != NULL); TCHAR ch; BOOL bGotScheme = FALSE; BOOL bGotUserName = FALSE; BOOL bGotHostName = FALSE; BOOL bGotPortNumber = FALSE; CAtlString strCurrentUrl; TCHAR* szCurrentUrl = strCurrentUrl.GetBuffer(ATL_URL_MAX_URL_LENGTH+6); TCHAR* pszCurrentUrl = szCurrentUrl; size_t nUrlSize = 0; BOOL bInsideSquareBrackets = FALSE; //parse lpszUrl using szCurrentUrl to store temporary data //this loop will get the following if it exists: //<protocol>://user:pass@server:port while ((ch = *lpszUrl) != '\0') { if (nUrlSize >= ATL_URL_MAX_URL_LENGTH+5) goto error; if (ch == ':' && !bInsideSquareBrackets) { //3 cases: //(1) Just encountered a scheme //(2) Port number follows //(3) Form of username:password@ // Check to see if we've just encountered a scheme *pszCurrentUrl = '\0'; if (!bGotScheme) { if (!SetSchemeName(szCurrentUrl)) goto error; //Set a flag to avoid checking for //schemes everytime we encounter a : bGotScheme = TRUE; if (*(lpszUrl+1) == '/') { if (*(lpszUrl+2) == '/') { //the mailto scheme cannot have a '/' following the "mailto:" portion if (bGotScheme && m_nScheme == ATL_URL_SCHEME_MAILTO) goto error; //Skip these characters and continue lpszUrl+= 2; } else { //it is an absolute path //no domain name, port, username, or password is allowed in this case //break to loop that gets path lpszUrl++; pszCurrentUrl = szCurrentUrl; nUrlSize = 0; break; } } //reset pszCurrentUrl pszCurrentUrl = szCurrentUrl; nUrlSize = 0; lpszUrl++; //if the scheme is file, skip to getting the path information if (m_nScheme == ATL_URL_SCHEME_FILE) break; continue; } else if (!bGotUserName || !bGotPortNumber) { //It must be a username:password or a port number *pszCurrentUrl = '\0'; pszCurrentUrl = szCurrentUrl; nUrlSize = 0; TCHAR tmpBuf[ATL_URL_MAX_PASSWORD_LENGTH+1]; TCHAR* pTmpBuf = tmpBuf; int nCnt = 0; //get the user or portnumber (break on either '/', '@', or '\0' while (((ch = *(++lpszUrl)) != '/') && (ch != '@') && (ch != '\0')) { if (nCnt >= ATL_URL_MAX_PASSWORD_LENGTH) goto error; *pTmpBuf++ = ch; nCnt++; } *pTmpBuf = '\0'; //if we broke on a '/' or a '\0', it must be a port number if (!bGotPortNumber && (ch == '/' || ch == '\0')) { //the host name must immediately preced the port number if (!SetHostName(szCurrentUrl)) goto error; //get the port number m_nPortNumber = (ATL_URL_PORT) _ttoi(tmpBuf); bGotPortNumber = bGotHostName = TRUE; } else if (!bGotUserName && ch=='@') { //otherwise it must be a username:password if (!SetUserName(szCurrentUrl) || !SetPassword(tmpBuf)) goto error; bGotUserName = TRUE; lpszUrl++; } else { goto error; } } } else if (ch == '@') { if (bGotUserName) goto error; //type is userinfo@ *pszCurrentUrl = '\0'; if (!SetUserName(szCurrentUrl)) goto error; bInsideSquareBrackets = FALSE; bGotUserName = TRUE; lpszUrl++; pszCurrentUrl = szCurrentUrl; nUrlSize = 0; } else if (ch == '/' || ch == '?' || (!*(lpszUrl+1))) { //we're at the end of this loop //set the domain name and break if (!*(lpszUrl+1) && ch != '/' && ch != '?') { if (nUrlSize >= ATL_URL_MAX_URL_LENGTH+4) goto error; *pszCurrentUrl++ = ch; nUrlSize++; lpszUrl++; } *pszCurrentUrl = '\0'; if (!bGotHostName) { if (!SetHostName(szCurrentUrl)) goto error; } pszCurrentUrl = szCurrentUrl; nUrlSize = 0; break; } else { if (ch == '[' && bGotScheme && !bGotHostName) bInsideSquareBrackets = TRUE; else if (ch == ']') bInsideSquareBrackets = FALSE; *pszCurrentUrl++ = ch; lpszUrl++; nUrlSize++; } } if (!bGotScheme) goto error; //Now build the path while ((ch = *lpszUrl) != '\0') { if (nUrlSize >= ATL_URL_MAX_URL_LENGTH+5) goto error; //break on a '#' or a '?', which delimit "extra information" if (m_nScheme != ATL_URL_SCHEME_FILE && (ch == '#' || ch == '?')) { break; } *pszCurrentUrl++ = ch; nUrlSize++; lpszUrl++; } *pszCurrentUrl = '\0'; if (*szCurrentUrl != '\0' && !SetUrlPath(szCurrentUrl)) goto error; pszCurrentUrl = szCurrentUrl; nUrlSize = 0; while ((ch = *lpszUrl++) != '\0') { if (nUrlSize >= ATL_URL_MAX_URL_LENGTH+5) goto error; *pszCurrentUrl++ = ch; nUrlSize++; } *pszCurrentUrl = '\0'; if (*szCurrentUrl != '\0' && !SetExtraInfo(szCurrentUrl)) goto error; switch(m_nScheme) { case ATL_URL_SCHEME_FILE: m_nPortNumber = ATL_URL_INVALID_PORT_NUMBER; break; case ATL_URL_SCHEME_NEWS: m_nPortNumber = ATL_URL_INVALID_PORT_NUMBER; break; case ATL_URL_SCHEME_MAILTO: m_nPortNumber = ATL_URL_INVALID_PORT_NUMBER; break; default: if (!bGotPortNumber) m_nPortNumber = (unsigned short)AtlGetDefaultUrlPort(m_nScheme); } return TRUE; error: InitFields(); return FALSE; } Ну конечно, это ведь все писалось в 80-ые года, когда кроме goto никто ничего не знал. Ну и для обратной совместимости осталось. Это продакшн код!!! Не примеры, не SDK и не MSDN, если вы мне не верите, посмотрите у себя. Конечно, как тут без goto переписать то по другому? Ну просто нереально сложно. Проще ведь goto впихнуть. А это! Это просто шедевр!!! cppasm, помнишь обвинял меня в том, что я бла бла бла, просто вчера я был реально занят, и не было у меня времени смотреть, а вот сейчас нашел немножко времени. Оцени, бла бла бла: BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) { LRESULT lResult = 0; union MessageMapFunctions mmf; mmf.pfn = 0; CInternalGlobalLock winMsgLock; // special case for commands if (message == WM_COMMAND) { if (OnCommand(wParam, lParam)) { lResult = 1; goto LReturnTrue; } return FALSE; } if (message == WM_CREATE && m_pDynamicLayout != NULL) { ASSERT_VALID(m_pDynamicLayout); if (!m_pDynamicLayout->Create(this)) { delete m_pDynamicLayout; m_pDynamicLayout = NULL; } else { InitDynamicLayout(); } } // special case for notifies if (message == WM_NOTIFY) { NMHDR* pNMHDR = (NMHDR*)lParam; if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult)) goto LReturnTrue; return FALSE; } // special case for activation if (message == WM_ACTIVATE) _AfxHandleActivate(this, wParam, CWnd::FromHandle((HWND)lParam)); // special case for set cursor HTERROR if (message == WM_SETCURSOR && _AfxHandleSetCursor(this, (short)LOWORD(lParam), HIWORD(lParam))) { lResult = 1; goto LReturnTrue; } // special case for windows that contain windowless ActiveX controls BOOL bHandled; bHandled = FALSE; if ((m_pCtrlCont != NULL) && (m_pCtrlCont->m_nWindowlessControls > 0)) { if (((message >= WM_MOUSEFIRST) && (message <= AFX_WM_MOUSELAST)) || ((message >= WM_KEYFIRST) && (message <= WM_IME_KEYLAST)) || ((message >= WM_IME_SETCONTEXT) && (message <= WM_IME_KEYUP))) { bHandled = m_pCtrlCont->HandleWindowlessMessage(message, wParam, lParam, &lResult); } } if (bHandled) { goto LReturnTrue; } switch (message) { case WM_SIZE: { ResizeDynamicLayout(); CHwndRenderTarget* pRenderTarget = GetRenderTarget(); if (pRenderTarget != NULL && pRenderTarget->IsValid()) { pRenderTarget->Resize(CD2DSizeU(UINT32(LOWORD(lParam)), UINT32(HIWORD(lParam)))); RedrawWindow(); } } break; case WM_PAINT: if (DoD2DPaint()) { lResult = 1; goto LReturnTrue; } break; case WM_ERASEBKGND: if (m_pRenderTarget != NULL && m_pRenderTarget->IsValid()) { lResult = 1; goto LReturnTrue; } break; } const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap(); UINT iHash; iHash = (LOWORD((DWORD_PTR)pMessageMap) ^ message) & (iHashMax-1); winMsgLock.Lock(CRIT_WINMSGCACHE); AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash]; const AFX_MSGMAP_ENTRY* lpEntry; if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap) { // cache hit lpEntry = pMsgCache->lpEntry; winMsgLock.Unlock(); if (lpEntry == NULL) return FALSE; // cache hit, and it needs to be handled if (message < 0xC000) goto LDispatch; else goto LDispatchRegistered; } else { // not in cache, look for it pMsgCache->nMsg = message; pMsgCache->pMessageMap = pMessageMap; for (/* pMessageMap already init'ed */; pMessageMap->pfnGetBaseMap != NULL; pMessageMap = (*pMessageMap->pfnGetBaseMap)()) { // Note: catch not so common but fatal mistake!! // BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd) ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)()); if (message < 0xC000) { // constant window message if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries, message, 0, 0)) != NULL) { pMsgCache->lpEntry = lpEntry; winMsgLock.Unlock(); goto LDispatch; } } else { // registered windows message lpEntry = pMessageMap->lpEntries; while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL) { UINT* pnID = (UINT*)(lpEntry->nSig); ASSERT(*pnID >= 0xC000 || *pnID == 0); // must be successfully registered if (*pnID == message) { pMsgCache->lpEntry = lpEntry; winMsgLock.Unlock(); goto LDispatchRegistered; } lpEntry++; // keep looking past this one } } } pMsgCache->lpEntry = NULL; winMsgLock.Unlock(); return FALSE; } LDispatch: ASSERT(message < 0xC000); mmf.pfn = lpEntry->pfn; switch (lpEntry->nSig) { default: ASSERT(FALSE); break; case AfxSig_l_p: { CPoint point(lParam); lResult = (this->*mmf.pfn_l_p)(point); break; } case AfxSig_b_D_v: lResult = (this->*mmf.pfn_b_D)(CDC::FromHandle(reinterpret_cast<HDC>(wParam))); break; case AfxSig_l_D_u: lResult = (this->*mmf.pfn_l_D_u)(CDC::FromHandle(reinterpret_cast<HDC>(wParam)), (UINT)lParam); break; case AfxSig_b_b_v: lResult = (this->*mmf.pfn_b_b)(static_cast<BOOL>(wParam)); break; case AfxSig_b_u_v: lResult = (this->*mmf.pfn_b_u)(static_cast<UINT>(wParam)); break; case AfxSig_b_h_v: lResult = (this->*mmf.pfn_b_h)(reinterpret_cast<HANDLE>(wParam)); break; case AfxSig_i_u_v: lResult = (this->*mmf.pfn_i_u)(static_cast<UINT>(wParam)); break; case AfxSig_C_v_v: lResult = reinterpret_cast<LRESULT>((this->*mmf.pfn_C_v)()); break; case AfxSig_v_u_W: (this->*mmf.pfn_v_u_W)(static_cast<UINT>(wParam), CWnd::FromHandle(reinterpret_cast<HWND>(lParam))); break; case AfxSig_u_u_v: lResult = (this->*mmf.pfn_u_u)(static_cast<UINT>(wParam)); break; case AfxSig_b_v_v: lResult = (this->*mmf.pfn_b_v)(); break; case AfxSig_b_W_uu: lResult = (this->*mmf.pfn_b_W_u_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), LOWORD(lParam), HIWORD(lParam)); break; case AfxSig_b_W_COPYDATASTRUCT: lResult = (this->*mmf.pfn_b_W_COPYDATASTRUCT)( CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), reinterpret_cast<COPYDATASTRUCT*>(lParam)); break; case AfxSig_b_v_HELPINFO: lResult = (this->*mmf.pfn_b_HELPINFO)(reinterpret_cast<LPHELPINFO>(lParam)); break; case AfxSig_CTLCOLOR: { // special case for OnCtlColor to avoid too many temporary objects ASSERT(message == WM_CTLCOLOR); AFX_CTLCOLOR* pCtl = reinterpret_cast<AFX_CTLCOLOR*>(lParam); CDC dcTemp; dcTemp.m_hDC = pCtl->hDC; CWnd wndTemp; wndTemp.m_hWnd = pCtl->hWnd; UINT nCtlType = pCtl->nCtlType; // if not coming from a permanent window, use stack temporary CWnd* pWnd = CWnd::FromHandlePermanent(wndTemp.m_hWnd); if (pWnd == NULL) { // determine the site of the OLE control if it is one COleControlSite* pSite; if (m_pCtrlCont != NULL && (pSite = (COleControlSite*) m_pCtrlCont->m_siteMap.GetValueAt(wndTemp.m_hWnd)) != NULL) { wndTemp.m_pCtrlSite = pSite; } pWnd = &wndTemp; } HBRUSH hbr = (this->*mmf.pfn_B_D_W_u)(&dcTemp, pWnd, nCtlType); // fast detach of temporary objects dcTemp.m_hDC = NULL; wndTemp.m_hWnd = NULL; lResult = reinterpret_cast<LRESULT>(hbr); } break; case AfxSig_CTLCOLOR_REFLECT: { // special case for CtlColor to avoid too many temporary objects ASSERT(message == WM_REFLECT_BASE+WM_CTLCOLOR); AFX_CTLCOLOR* pCtl = reinterpret_cast<AFX_CTLCOLOR*>(lParam); CDC dcTemp; dcTemp.m_hDC = pCtl->hDC; UINT nCtlType = pCtl->nCtlType; HBRUSH hbr = (this->*mmf.pfn_B_D_u)(&dcTemp, nCtlType); // fast detach of temporary objects dcTemp.m_hDC = NULL; lResult = reinterpret_cast<LRESULT>(hbr); } break; case AfxSig_i_u_W_u: lResult = (this->*mmf.pfn_i_u_W_u)(LOWORD(wParam), CWnd::FromHandle(reinterpret_cast<HWND>(lParam)), HIWORD(wParam)); break; case AfxSig_i_uu_v: lResult = (this->*mmf.pfn_i_u_u)(LOWORD(wParam), HIWORD(wParam)); break; case AfxSig_i_W_uu: lResult = (this->*mmf.pfn_i_W_u_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), LOWORD(lParam), HIWORD(lParam)); break; case AfxSig_i_v_s: lResult = (this->*mmf.pfn_i_s)(reinterpret_cast<LPTSTR>(lParam)); break; case AfxSig_i_v_S: lResult = (this->*mmf.pfn_i_S)(reinterpret_cast<LPCTSTR>(lParam)); break; case AfxSig_v_F_b: (this->*mmf.pfn_v_F_b)(CFont::FromHandle(reinterpret_cast<HFONT>(wParam)), (BOOL)LOWORD(lParam)); break; case AfxSig_h_v_v: { HANDLE handle = (this->*mmf.pfn_h_v)(); lResult = reinterpret_cast<LRESULT>(handle); } break; case AfxSig_h_b_h: { HANDLE handle = (this->*mmf.pfn_h_b_h)(static_cast<BOOL>(wParam), reinterpret_cast<HANDLE>(lParam)); lResult = reinterpret_cast<LRESULT>(handle); } break; case AfxSig_h_h_h: { HANDLE handle = (this->*mmf.pfn_h_h_h)(reinterpret_cast<HANDLE>(wParam), reinterpret_cast<HANDLE>(lParam)); lResult = reinterpret_cast<LRESULT>(handle); } break; case AfxSig_l_w_l: lResult = (this->*mmf.pfn_l_w_l)(wParam, lParam); break; case AfxSig_l_uu_M: lResult = (this->*mmf.pfn_l_u_u_M)(LOWORD(wParam), HIWORD(wParam), CMenu::FromHandle(reinterpret_cast<HMENU>(lParam))); break; case AfxSig_v_b_h: (this->*mmf.pfn_v_b_h)(static_cast<BOOL>(wParam), reinterpret_cast<HANDLE>(lParam)); break; case AfxSig_v_h_v: (this->*mmf.pfn_v_h)(reinterpret_cast<HANDLE>(wParam)); break; case AfxSig_v_h_h: (this->*mmf.pfn_v_h_h)(reinterpret_cast<HANDLE>(wParam), reinterpret_cast<HANDLE>(lParam)); break; case AfxSig_v_v_v: (this->*mmf.pfn_v_v)(); break; case AfxSig_v_u_v: (this->*mmf.pfn_v_u)(static_cast<UINT>(wParam)); break; case AfxSig_v_up_v: (this->*mmf.pfn_v_up)(static_cast<UINT_PTR>(wParam)); break; case AfxSig_v_u_u: (this->*mmf.pfn_v_u_u)(static_cast<UINT>(wParam), static_cast<UINT>(lParam)); break; case AfxSig_v_uu_v: (this->*mmf.pfn_v_u_u)(LOWORD(wParam), HIWORD(wParam)); break; case AfxSig_v_v_ii: (this->*mmf.pfn_v_i_i)(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break; case AfxSig_v_u_uu: (this->*mmf.pfn_v_u_u_u)(static_cast<UINT>(wParam), LOWORD(lParam), HIWORD(lParam)); break; case AfxSig_v_u_ii: (this->*mmf.pfn_v_u_i_i)(static_cast<UINT>(wParam), LOWORD(lParam), HIWORD(lParam)); break; case AfxSig_v_w_l: (this->*mmf.pfn_v_w_l)(wParam, lParam); break; case AfxSig_MDIACTIVATE: (this->*mmf.pfn_v_b_W_W)(m_hWnd == reinterpret_cast<HWND>(lParam), CWnd::FromHandle(reinterpret_cast<HWND>(lParam)), CWnd::FromHandle(reinterpret_cast<HWND>(wParam))); break; case AfxSig_MDINext: (this->*mmf.pfn_v_W_b)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), static_cast<BOOL>(lParam)); break; case AfxSig_v_D_v: (this->*mmf.pfn_v_D)(CDC::FromHandle(reinterpret_cast<HDC>(wParam))); break; case AfxSig_v_M_v: (this->*mmf.pfn_v_M)(CMenu::FromHandle(reinterpret_cast<HMENU>(wParam))); break; case AfxSig_v_M_ub: (this->*mmf.pfn_v_M_u_b)(CMenu::FromHandle(reinterpret_cast<HMENU>(wParam)), GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break; case AfxSig_v_W_v: (this->*mmf.pfn_v_W)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam))); break; case AfxSig_v_v_W: (this->*mmf.pfn_v_W)(CWnd::FromHandle(reinterpret_cast<HWND>(lParam))); break; case AfxSig_v_W_uu: (this->*mmf.pfn_v_W_u_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), LOWORD(lParam), HIWORD(lParam)); break; case AfxSig_v_W_p: { CPoint point(lParam); (this->*mmf.pfn_v_W_p)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), point); } break; case AfxSig_v_W_h: (this->*mmf.pfn_v_W_h)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), reinterpret_cast<HANDLE>(lParam)); break; case AfxSig_ACTIVATE: (this->*mmf.pfn_v_u_W_b)(LOWORD(wParam), CWnd::FromHandle(reinterpret_cast<HWND>(lParam)), HIWORD(wParam)); break; case AfxSig_SCROLL: case AfxSig_SCROLL_REFLECT: { // special case for WM_VSCROLL and WM_HSCROLL ASSERT(message == WM_VSCROLL || message == WM_HSCROLL || message == WM_VSCROLL+WM_REFLECT_BASE || message == WM_HSCROLL+WM_REFLECT_BASE); int nScrollCode = (short)LOWORD(wParam); int nPos = (short)HIWORD(wParam); if (lpEntry->nSig == AfxSig_SCROLL) (this->*mmf.pfn_v_u_u_W)(nScrollCode, nPos, CWnd::FromHandle(reinterpret_cast<HWND>(lParam))); else (this->*mmf.pfn_v_u_u)(nScrollCode, nPos); } break; case AfxSig_v_v_s: (this->*mmf.pfn_v_s)(reinterpret_cast<LPTSTR>(lParam)); break; case AfxSig_v_u_cs: (this->*mmf.pfn_v_u_cs)(static_cast<UINT>(wParam), reinterpret_cast<LPCTSTR>(lParam)); break; case AfxSig_OWNERDRAW: (this->*mmf.pfn_v_i_s)(static_cast<int>(wParam), reinterpret_cast<LPTSTR>(lParam)); lResult = TRUE; break; case AfxSig_i_i_s: lResult = (this->*mmf.pfn_i_i_s)(static_cast<int>(wParam), reinterpret_cast<LPTSTR>(lParam)); break; case AfxSig_u_v_p: { CPoint point(lParam); lResult = (this->*mmf.pfn_u_p)(point); } break; case AfxSig_u_v_v: lResult = (this->*mmf.pfn_u_v)(); break; case AfxSig_v_b_NCCALCSIZEPARAMS: (this->*mmf.pfn_v_b_NCCALCSIZEPARAMS)(static_cast<BOOL>(wParam), reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam)); break; case AfxSig_v_v_WINDOWPOS: (this->*mmf.pfn_v_v_WINDOWPOS)(reinterpret_cast<WINDOWPOS*>(lParam)); break; case AfxSig_v_uu_M: (this->*mmf.pfn_v_u_u_M)(LOWORD(wParam), HIWORD(wParam), reinterpret_cast<HMENU>(lParam)); break; case AfxSig_v_u_p: { CPoint point(lParam); (this->*mmf.pfn_v_u_p)(static_cast<UINT>(wParam), point); } break; case AfxSig_SIZING: (this->*mmf.pfn_v_u_pr)(static_cast<UINT>(wParam), reinterpret_cast<LPRECT>(lParam)); lResult = TRUE; break; case AfxSig_MOUSEWHEEL: lResult = (this->*mmf.pfn_b_u_s_p)(LOWORD(wParam), (short)HIWORD(wParam), CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); if (!lResult) return FALSE; break; case AfxSig_MOUSEHWHEEL: (this->*mmf.pfn_MOUSEHWHEEL)(LOWORD(wParam), (short)HIWORD(wParam), CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); break; case AfxSig_l: lResult = (this->*mmf.pfn_l_v)(); if (lResult != 0) return FALSE; break; case AfxSig_u_W_u: lResult = (this->*mmf.pfn_u_W_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), static_cast<UINT>(lParam)); break; case AfxSig_v_u_M: (this->*mmf.pfn_v_u_M)(static_cast<UINT>(wParam), CMenu::FromHandle(reinterpret_cast<HMENU>(lParam))); break; case AfxSig_u_u_M: lResult = (this->*mmf.pfn_u_u_M)(static_cast<UINT>(wParam), CMenu::FromHandle(reinterpret_cast<HMENU>(lParam))); break; case AfxSig_u_v_MENUGETOBJECTINFO: lResult = (this->*mmf.pfn_u_v_MENUGETOBJECTINFO)(reinterpret_cast<MENUGETOBJECTINFO*>(lParam)); break; case AfxSig_v_M_u: (this->*mmf.pfn_v_M_u)(CMenu::FromHandle(reinterpret_cast<HMENU>(wParam)), static_cast<UINT>(lParam)); break; case AfxSig_v_u_LPMDINEXTMENU: (this->*mmf.pfn_v_u_LPMDINEXTMENU)(static_cast<UINT>(wParam), reinterpret_cast<LPMDINEXTMENU>(lParam)); break; case AfxSig_APPCOMMAND: (this->*mmf.pfn_APPCOMMAND)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), static_cast<UINT>(GET_APPCOMMAND_LPARAM(lParam)), static_cast<UINT>(GET_DEVICE_LPARAM(lParam)), static_cast<UINT>(GET_KEYSTATE_LPARAM(lParam))); lResult = TRUE; break; case AfxSig_RAWINPUT: (this->*mmf.pfn_RAWINPUT)(static_cast<UINT>(GET_RAWINPUT_CODE_WPARAM(wParam)), reinterpret_cast<HRAWINPUT>(lParam)); break; case AfxSig_u_u_u: lResult = (this->*mmf.pfn_u_u_u)(static_cast<UINT>(wParam), static_cast<UINT>(lParam)); break; case AfxSig_u_u_l: lResult = (this->*mmf.pfn_u_u_l)(static_cast<UINT>(wParam), lParam); break; case AfxSig_MOUSE_XBUTTON: (this->*mmf.pfn_MOUSE_XBUTTON)(static_cast<UINT>(GET_KEYSTATE_WPARAM(wParam)), static_cast<UINT>(GET_XBUTTON_WPARAM(wParam)), CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); lResult = TRUE; break; case AfxSig_MOUSE_NCXBUTTON: (this->*mmf.pfn_MOUSE_NCXBUTTON)(static_cast<short>(GET_NCHITTEST_WPARAM(wParam)), static_cast<UINT>(GET_XBUTTON_WPARAM(wParam)), CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); lResult = TRUE; break; case AfxSig_INPUTLANGCHANGE: (this->*mmf.pfn_INPUTLANGCHANGE)(static_cast<UINT>(wParam), static_cast<UINT>(lParam)); lResult = TRUE; break; case AfxSig_INPUTDEVICECHANGE: (this->*mmf.pfn_INPUTDEVICECHANGE)(LOWORD(wParam), reinterpret_cast<HANDLE>(lParam)); break; case AfxSig_v_u_hkl: (this->*mmf.pfn_v_u_h)(static_cast<UINT>(wParam), reinterpret_cast<HKL>(lParam)); break; case AfxSig_b_v_ii: lResult = (this->*mmf.pfn_b_v_ii)(GET_Y_LPARAM(lParam), GET_X_LPARAM(lParam)); break; } goto LReturnTrue; LDispatchRegistered: // for registered windows messages ASSERT(message >= 0xC000); ASSERT(sizeof(mmf) == sizeof(mmf.pfn)); mmf.pfn = lpEntry->pfn; lResult = (this->*mmf.pfn_l_w_l)(wParam, lParam); LReturnTrue: if (pResult != NULL) *pResult = lResult; return TRUE; } Как тебе? Любишь такой код сопровождать? Или сам такой код и пишешь? Ну и вишенка на тортик: C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\com\administration\spy\comspyctl\Adminwrap.Cpp #include "stdafx.h" #include "Adminwrap.h" #include <comadmin.h> #include <assert.h> #define if_failed_exit(HR) do { if FAILED(HR) goto exit; } while (false) #define exit_with_result(HR) do { hr = HR; goto exit; } while (false) |
Сообщ.
#36
,
|
|
|
И нафига ты проверку дублируешь? Так понятней читать что-ли, для тех кто с первого раза не понимает? От того что ты кусок кода в функцию вынес как-то лучше не стало. Цитата KILLER @ Он не в тему тем, что ты пришел, тему не читал, зато начал что то писать. Я тебе говорю - твой пример не в тему, и не привожу почему - чтоб ты взял и сам перечитал. Это называется съехал. Понятно. Добавлено Цитата KILLER @ А это! Это просто шедевр!!! cppasm, помнишь обвинял меня в том, что я бла бла бла И где тут анонсированное: Цитата KILLER @ goto вхерачен в макрос, который представляет из себя часть какой то то ли функции, то ли проверки, и потом таким же макросом расставлены метки? Кривой тут только последний пример, остальное нормально читается. |
Сообщ.
#37
,
|
|
|
Цитата Так приведи мне хоть один пример, когда goto делает код более понятным? Ты сам привел такой пример: Цитата inline HRESULT CSecurityDescriptor::SetPrivilege Вариант с goto читаем. Использование do{...}while(false); сделало бы этот код хуже читаемым. |
Сообщ.
#38
,
|
|
|
К слову - действительно причём здесь SDK?
Это не SDK, это сэмплы из SDK. Я их например вообще не ставлю никогда, и что? И почему SDK v7.0 а не v7.1, чтоб другим проверить сложнее было? |
Сообщ.
#39
,
|
|
|
Цитата cppasm @ И нафига ты проверку дублируешь? Чтоб выйти из внешнего цикла, я ведь даже подход к решению задачи не менял. Можно переписать и мой код по другому. Я тебе его написал на коленке, чтобы показать идею, как можно переписать твой код без goto, примерно так же как и ты мне его написал на коленке. Возможно там вообще можно было обойтись еще проще. Я не знаю, мне пока не интересно придумывать 100500 разных вариантов решения твоей задачи. Цитата cppasm @ Так понятней читать что-ли, для тех кто с первого раза не понимает? У тебя выход по goto идет из вложенного цикла за внешний цикл. Поэтому я сделал там вторую проверку, просто твой вложенный цикл обернул в отдельную функцию. Цитата cppasm @ От того что ты кусок кода в функцию вынес как-то лучше не стало. Стало. Код стал намного понятнее, так как там уже не двойной цикл не пойми зачем идет, а появилась какая то логика происходящего + мы избавились от goto и вырвиглазного кода. Цитата cppasm @ Это называется съехал. Понятно. Хорошо, на держи бла бла бла: Цитата KILLER @ Возможно в каких то там исключительных случаях - когда тебе нужно выйти из 4-ого по вложенности цикла - оно и упрощает понимание кода, но в тех примерах где они его используют, там и без goto обойтись не составляет проблем, без нарушения структуры исполнения программы. Ты теперь понял - почему ты свой пример привел не в тему? И то - этот мой коментарий, если еще не понятно с оговоркой - "Если вот уже вот так все спроектировано, и другие решения подразумевают слишком много телодвижений или будут слишком сложные". Потому как я вообще стараюсь не писать больше двух вложенных циклов. Цитата cppasm @ И где тут анонсированное: Повылазило? Ну хорошо еще раз: #include "stdafx.h" #include "Adminwrap.h" #include <comadmin.h> #include <assert.h> #define if_failed_exit(HR) do { if FAILED(HR) goto exit; } while (false) //<<<<<<<<<<<<<<<< goto вхерачен в макрос, который представляет из себя часть какой то то ли функции, то ли проверки #define exit_with_result(HR) do { hr = HR; goto exit; } while (false) //<<<<<<<<<<<<<<<< goto вхерачен в макрос, который представляет из себя часть какой то то ли функции, то ли проверки Цитата cppasm @ Кривой тут только последний пример, остальное нормально читается. Нормально читается? А что имея под рукой классы, кучу идиом и паттернов - по другому нельзя нормально переписать? А с использованием лямбд из нового стандарта, так даже можно и классы не применять, функции очистки и RAII можно клепать прямо на лету, где тебе нужно, без написания всяких оберток. Например из последнего, то что было с goto и я переписывал без goto: Мой код: DWORD COMUtility::SetAccountRights(const std::wstring& sUser, const std::wstring& sPrivilege) { auto LSAHandleDeleter = [](LSA_HANDLE* hPolicy) { if (hPolicy && *hPolicy) LsaClose(*hPolicy); }; std::unique_ptr<LSA_HANDLE, decltype(LSAHandleDeleter)> smartLSAHandle(nullptr, LSAHandleDeleter); LSA_HANDLE rawLSAHandle = nullptr; LSA_OBJECT_ATTRIBUTES objectAttributes = { 0 }; std::unique_ptr<SID> psidPrincipal; LSA_UNICODE_STRING lsaPrivilegeString = { 0 }; WCHAR wszPrivilege[256] = { 0 }; DWORD dwReturnValue = ERROR_SUCCESS; StringCchCopy(wszPrivilege, (sPrivilege.size() * sizeof(wchar_t)) + 1, sPrivilege.c_str()); dwReturnValue = LsaOpenPolicy(NULL, &objectAttributes, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &rawLSAHandle); dwReturnValue = LsaNtStatusToWinError(dwReturnValue); smartLSAHandle.reset(std::move(&rawLSAHandle)); if (dwReturnValue != ERROR_SUCCESS) return dwReturnValue; psidPrincipal = GetPrincipalSID(sUser, dwReturnValue); if (dwReturnValue != ERROR_SUCCESS) return dwReturnValue; lsaPrivilegeString.Length = (USHORT)(wcslen(wszPrivilege) * sizeof(WCHAR)); lsaPrivilegeString.MaximumLength = (USHORT)(lsaPrivilegeString.Length + sizeof(WCHAR)); lsaPrivilegeString.Buffer = wszPrivilege; dwReturnValue = LsaAddAccountRights(*smartLSAHandle, psidPrincipal.get(), &lsaPrivilegeString, 1); dwReturnValue = LsaNtStatusToWinError(dwReturnValue); return dwReturnValue; } Оригинал от майкрософта: * NAME: SetAccountRights * * --------------------------------------------------------------------------* * DESCRIPTION: Sets the account right for a given user. * \*---------------------------------------------------------------------------*/ DWORD SetAccountRights ( LPTSTR tszUser, LPTSTR tszPrivilege ) { LSA_HANDLE hPolicy = NULL; LSA_OBJECT_ATTRIBUTES objectAttributes = {0}; PSID psidPrincipal = NULL; LSA_UNICODE_STRING lsaPrivilegeString = {0}; WCHAR wszPrivilege [256] = {0}; DWORD dwReturnValue = ERROR_SUCCESS; #ifdef _UNICODE StringCchCopy (wszPrivilege, RTL_NUMBER_OF(wszPrivilege),tszPrivilege); #else STR2UNI (wszPrivilege, tszPrivilege); #endif dwReturnValue = LsaOpenPolicy (NULL, &objectAttributes, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &hPolicy); dwReturnValue = LsaNtStatusToWinError(dwReturnValue); if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP; dwReturnValue = GetPrincipalSID (tszUser, &psidPrincipal); if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP; lsaPrivilegeString.Length = (USHORT) (wcslen (wszPrivilege) * sizeof (WCHAR)); lsaPrivilegeString.MaximumLength = (USHORT) (lsaPrivilegeString.Length + sizeof (WCHAR)); lsaPrivilegeString.Buffer = wszPrivilege; dwReturnValue = LsaAddAccountRights (hPolicy, psidPrincipal, &lsaPrivilegeString, 1); dwReturnValue = LsaNtStatusToWinError(dwReturnValue); if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP; CLEANUP: if(psidPrincipal) free (psidPrincipal); if(hPolicy) LsaClose (hPolicy); return dwReturnValue; } И я сейчас не упрекаю их за то, что они там лямбды не повпихивали, или что они там std::wstring не использовали. Я тебе просто показываю как можно переписать без goto. Пусть этот код у них Сишный, но ведь С++сный код , что я привел выше - написан в том же стиле. Ты считаешь это нормальным? А для меня это не нормально. Для меня более понятно и привычно то, как переписал я. Хотя возможно, и я не отрицаю у меня вырвиглазный код и его можно переписать еще лучше и круче. У меня не было цели рефакторить все, я избавился от goto и от ручного выделения/освобождения памяти. Цитата Fester @ Вариант с goto читаем. Использование do{...}while(false); сделало бы этот код хуже читаемым. Зачем переписывать на do while? Я вот по другому переписал. Мне мой подход - более понятен, чем этот оцтой. Добавлено Цитата cppasm @ К слову - действительно причём здесь SDK? Это не SDK, это сэмплы из SDK. Я их например вообще не ставлю никогда, и что? И почему SDK v7.0 а не v7.1, чтоб другим проверить сложнее было? Посмотри другие версии. Если человек так пишет в семплах - то он так же будет писать в проде. Ну не можешь ты в проде писать вот так, а в семплах вот так. Это уже какой то троллинг получается. |
Сообщ.
#40
,
|
|
|
Цитата Я вот по другому переписал. Мне мой подход - более понятен, чем этот оцтой. Во-первых, твой вариант - не эквивалентен варианту от MS. У них в клинапе есть еще if(psidPrincipal) free (psidPrincipal); Во-вторых, лямбды появились не так давно. Или ты полагаешь, что как только появилась новая цаца, так сразу МС должны переписать все библиотеки? |
Сообщ.
#41
,
|
|
|
Цитата KILLER @ Повылазило? Ну хорошо еще раз Ты попроще общаться не пробовал? Вот покажи конкретно где там В противном случае у кого повылазило станет очевидно. |
Сообщ.
#42
,
|
|
|
Цитата Fester @ Во-первых, твой вариант - не эквивалентен варианту от MS. У них в клинапе есть еще CollapsedWrap disabledLine numbers off if(psidPrincipal) free (psidPrincipal); а ты про это почему-то забыл Нет не забыл. Просто ты видимо С++ не знаешь. Цитата Fester @ Во-вторых, лямбды появились не так давно. Или ты полагаешь, что как только появилась новая цаца, так сразу МС должны переписать все библиотеки? А ты не читатель? До лямбд уже 100 лет как успешно применяется идиома RAII. Почему MFC/ATL изначально не спроектировать на основе этой идиомы? Зачем там пихать goto ? Цитата cppasm @ Ты попроще общаться не пробовал? Если ты не читатель - как еще обращаться? Меня бесит когда человек не читает, но мнение имеет. Цитата cppasm @ В противном случае у кого повылазило станет очевидно. А тебе не очевидно зачем там этот макрос написан? Добавлено Еще один треш от майкрософта: #define __LONGSTRING(string) L##string #define LONGSTRING(string) __LONGSTRING(string) //Goes to CLEANUP on Failure #define CHECK_HR(hr) \ if(FAILED(hr)) \ goto CLEANUP //Goes to CLEANUP on Failure, and displays any ErrorInfo #define XCHECK_HR(hr) \ { \ if( g_dwFlags & DISPLAY_METHODCALLS ) \ fwprintf(stderr, LONGSTRING(#hr) L"\n"); \ if(FAILED(myHandleResult(hr, LONGSTRING(__FILE__), __LINE__))) \ goto CLEANUP; \ } #define CHECK_MEMORY(hr, pv) \ { \ if(!pv) \ { \ hr = E_OUTOFMEMORY; \ CHECK_HR(hr); \ } \ } |
Сообщ.
#43
,
|
|
|
Ну вот и говнокоду прибыло. KILLER, ты в натуре считаешь, что код от такой переделки выиграл? В чём? Наглядности? Скорости? Объёму? Ото ж, ради галочки. Попробуй теперь вот тут:
int copyFile(const char* src, const char* dst) { void *buf = NULL; FILE *inF = NULL; FILE *ouF = NULL; size_t readed, written; int res = 0; buf = malloc(BUF_SIZE); inF = fopen(src, "rb"); ouF = fopen(dst, "wb"); if (buf == NULL) goto cleanup; if (inF == NULL) goto cleanup; if (ouF == NULL) goto cleanup; readed = fread(buf, 1, BUF_SIZE, inF); while (!feof(inF) || readed != 0) { written = fwrite(buf, 1, readed, ouF); if (written != readed) goto cleanup; readed = fread(buf, 1, BUF_SIZE, inF); } res = 1; cleanup: if (ouF != NULL) fclose(ouF); if (inF != NULL) fclose(inF); if (buf != NULL) free(buf); return res; } Керниган, Ричи. Язык C, раздел "3.9. Оператор GOTO и метки" Не стоит. Хотя для слабеньких встроенных систем он и сегодня полезен, фактически за пределамиы POSIX, в котором отсутствует SEH или его аналог, он уже не применяется. Да-да-да, но смирись, что примеры в MSDN никто переписывать не будет. Добавлено Цитата KILLER @ А вот и нет. См. код выше. Ты ж не заводишь 10 finally... или заводишь? Я так полагаю вы будете заводить 10 разный меток, и прыгать? Да? Судя по всему да. |
Сообщ.
#44
,
|
|
|
Цитата Qraizer @ Ну вот и говнокоду прибыло. KILLER, ты в натуре считаешь, что код от такой переделки выиграл? В восприятии - да выиграл. Его стало проще воспринимать. Искать глазами метку - это треш, особенно если код не из 4 строчек, как привел cppasm. Цитата Qraizer @ Керниган, Ричи. Язык C, раздел "3.9. Оператор GOTO и метки" Цитата В языке "C" предусмотрен и оператор GOTO, которым беско- нечно злоупотребляют, и метки для ветвления. С формальной точки зрения оператор GOTO никогда не является необходимым, и на практике почти всегда можно обойтись без него. Дальше читать не стал. Даже K&R считают что в Си им злоупотребляют, и практически всегда можно обойтись без него. ЧТД. Цитата Qraizer @ Да-да-да, но смирись, что примеры в MSDN никто переписывать не будет. Так я не прошу чтоб они их переписывали, они новые клепают на том же goto. Я тут уже привел достаточно кода из ATL/MFC что писалось исключительно на С++, для демонстрации их подхода. Цитата Qraizer @ int copyFile(const char* src, const char* dst) { void *buf = NULL; FILE *inF = NULL; FILE *ouF = NULL; size_t readed, written; buf = malloc(BUF_SIZE); inF = fopen(src, "rb"); ouF = fopen(dst, "wb"); if (buf == NULL) goto cleanup; if (inF == NULL) goto cleanup; if (ouF == NULL) goto cleanup; readed = fread(buf, 1, BUF_SIZE, inF); while (!feof(inF) || readed != 0) { written = fwrite(buf, 1, readed, ouF); if (written != readed) goto cleanup; readed = fread(buf, 1, BUF_SIZE, inF); } return 1; cleanup: if (ouF != NULL) fclose(ouF); if (inF != NULL) fclose(inF); if (buf != NULL) free(buf); return 0; } Выше ведь приводил уже: auto LSAHandleDeleter = [](LSA_HANDLE* hPolicy) { if (hPolicy && *hPolicy) LsaClose(*hPolicy); }; Поменяй название LSA_HANDLE на FILE и все перепишется на ура. На крайний случай это все легко переписывается с помощью идиомы RAII. И не нужно следить забыл я закрыть файл или удалить буфер. |
Сообщ.
#45
,
|
|
|
Цитата OpenGL @ Ещё он писался в несколько приёмов и отлаживался. С goto написалось с первого раза и заработало без отладки. Структурный вариант в той теме был, но с goto он мог соревноваться только с краткостью записи, но никак не с понятностью (там сложная логика в условиях выхода из циклов, и неочевидный инкремент были). |