- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
UINT32 GetHostName(char *hostName, UINT32 hostNameBufSize)
{
if (hostName == NULL ){
OSALTRACE(OSAL_ERROR, ("Error: Input parameter hostName(null)."));
return -1;
}
FILE *fp = NULL;
static char buffer[512];
char tag[64];
// hope this size will be OK for one line to read from the fileOB
char line[1000];
char *linep=line;
int buffSize = sizeof(buffer);
int found = 0;
fp = fopen("/etc/resolv.conf", "r");
if ( fp == NULL)
{
OSALTRACE(OSAL_ERROR, ("failed to open resolver config file."));
return -1;
}
while ( ((*linep=getc(fp)) != EOF) && !found )
{
if (*linep++ == '\n')
{
*linep = '\0';
sscanf(line, "%s %s", tag, buffer);
if (tag[0] && (!strcmp(tag, "search") || !strcmp(tag, "domain") ) ) {
found = 1;
break;
}
linep = line;
}
}
fclose(fp);
if ( found )
{
strcpy(hostName,buffer);
OSALTRACE(OSAL_DEBUG, ("DHCP domain is %s.", buffer));
}
else
{
OSALTRACE(OSAL_ERROR, ("Could not find dhcp domain in resolv.conf."));
return -1;
}
return !found;
}
Intel WiMAX Network Service, не какая-то пионерская поделка...
TheCalligrapher 13.09.2010 02:28 # +2
Но чем объяснить вот это: буфер `line` объявлен автоматическим, в то время как буфер `buffer` - статическим. Зачем? Почему? Какой логикой, пусть даже и извращенной, можно руководствоваться при принятии такого решения?
Я бы еще мог уловить какой-то намек на логику, если бы массив большего размера был объявлен статически - мол, негоже большие буфера в стеке выделять. Но тут-то наоборот!
Могу лишь предположить, что писало два разных человека... В пользу этого предроложения также свидетельствует манера по разному оформлять условия в `if`.
Altravert 13.09.2010 05:03 # 0
А так, возможно не два разных человека, а один человек который спиздил код другого человек(а/ов).
Но все равно, не думаю, что из-за использования статика это становится говнокодом.
TheCalligrapher 13.09.2010 05:08 # 0
Altravert 13.09.2010 05:10 # 0
> негоже большие буфера в стеке
TheCalligrapher 13.09.2010 05:21 # 0
А вот когда мы говорим о типах памяти (статическая, автоматическая, динамическая), лезть в детали реализаци совсем не обязательно.
Altravert 13.09.2010 05:26 # 0
TheCalligrapher 13.09.2010 06:09 # 0
Altravert 13.09.2010 06:21 # −2
TheCalligrapher 13.09.2010 06:29 # +1
Altravert 13.09.2010 07:00 # 0
TheCalligrapher 13.09.2010 02:31 # 0
Умиляет еще проверка условия `!found` в условии повторения цикла, в то время как при установке `found` в 1 сразу делается `break` :) Опять же наводит на мысль, что писали два человека - один сторонник "структурного программирования", другой - явных выходов из цикла по `break`.
Altravert 13.09.2010 05:04 # 0
TheCalligrapher 13.09.2010 05:09 # −4
Altravert 13.09.2010 05:09 # −3
TheCalligrapher 13.09.2010 05:18 # 0
Altravert 13.09.2010 05:27 # 0
TheCalligrapher 13.09.2010 06:05 # +3
В языке С есть три типа группы `char`: `signed char`, `char` и `unsigned char`. Все эти типы являются самостоятельными отдельными типами. (В отличие, например, от `int`, где `signed int` и `int` - один и тот же тип).
Так вот, тип `char` является самостоятельным типом, который по внутреннему предствлению совпадает либо с `signed char`, либо с `unsigned char`. С каким конкретно - определяется реализацией. Т.е. с точки зрения языка тип `char` может быть беззнаковым. (При этом он по-прежнему остается отдельным типом, отличным от `unsigned char`.)
Altravert 13.09.2010 06:20 # 0
TheCalligrapher 13.09.2010 06:32 # +6
Что имеется в виду под "не застал" мне не ясно. Такими свойствами тип `char` обладает как в современном С, так и в современном С++.
Altravert 13.09.2010 06:52 # −3
TheCalligrapher 13.09.2010 07:08 # +2
Наличия такой опции, разумеется, никто не гарантирует. В каком-нибудь другом компиляторе `char` может быть жестко прошит как всегда знаковый. Или как всегда беззнаковый.
Altravert 13.09.2010 07:29 # −4
TheCalligrapher 13.09.2010 08:03 # +4
Это во-первых. А во-вторых, ты упускаешь из виду тот факт, что вышенаписанный код является говнокодом потому, что будет работать криво к любом случае: что со знаковым `char`, что с беззнаковым. Пусть даже `char` у нас знаковый. И пусть во входном потоке встретился байт со значением 255. На традиционной машине байт 255 силой засунутый в знаковый `char` превратится в значение `-1`. А константа `EOF` во многих реализациях определена именно как `-1`. В результате вышеприведенная программа, наткнувшись на 255 в файле, решит что файл закончился, когда на самом деле он не заканчивался.
В данном случае байта 255 в файле, наверное, встретиться не должно, но я лишь иллюстрирую общую проблему. Возврат функции `getc` надо читать в переменную типа `int`, сравнивать с `EOF` именно как `int`, и только потом пихать в `char`. Это, вообще то, классика C FAQ.
Altravert 13.09.2010 08:48 # −2
Код написан под определенные цели -> 255 в тексте не встретится. Хотя, даже если найдется идиот, который запихнет это в текстовый файл, пусть программа решит, что файл закончился -- она должна проверить валидность считанного.
Код будет скомпилирован автором -> он сам решит знаковый char или нет (думаю, догадается выбрать верный вариант).
Ты давно видел компилятор соответствующий стандарту?
К тому же, это очень хуевый стандарт, раз говорит "делайте как хотите". И все равно, даже с такими раскладами большинство приложений компилится и работает нормально, пусть даже благодаря неофициальным, но общепринятым правилам.
Дело, в общем, Ваше. Я всё равно не буду использовать getc, когда можно прочитать raw-данные в тип, который мне нужен, а не зависимый от положения звезд. Тогда я смогу учесть все выебоны компилятора, в т.ч. и знаковость.
Ну, и еще один аспект: я не C-программист))
TheCalligrapher 13.09.2010 09:16 # +2
В мире С практически все компиляторы соответствуют стандарту (хотя бы стандарту C89/90). Да и в С++ с этим сейчас дела обстоят очень неплохо.
Altravert 13.09.2010 09:54 # −7
Конечно, по-хорошему этой константы вообще, наверно, быть не должно. А для простого текста и 0 сканает. Хотя звучит бредово. Мозг замерзает. Пальцы обледенели. Сопли стекают по клаве на пол. Апокалипсис бля какой-то.
А о компиляторах. Имхо, если почти все компиляторы абсолютно соответствуют стандарту, то это слишком расплывчатый стандарт. Если бы он регламентировал всё четко, то почти все компиляторы бы стремились к соблюдению. Однако, с каждым продуктом, строящим воркэраунды к воркэраундам, шансов конкретизировать эту всю шнягу становится все меньше. Самый простой пример -- винапи. Это пиздец, хаос и каша. И чем больше там сказано "может зависеть от реализации" тем больше непоняток будет. Но это всё имхо. Эх, лирика.
TheCalligrapher 13.09.2010 16:07 # +6
По этой простой причине индикатор конца файла надо делать таковым, чтобы он не совпадал ни с одним значением прочитанным из файла. Чтобы ты мог отличить, что же ты получил от `getc` - что-то только что прочитанное из файла, или `EOF`.
Если у тебя платформа с безззнаковым `char` (0-225), то `EOF = -1` - хорошая идея. Если же у тебя платформа со знаковым `char` (-128 - + 127), то `EOF = -1` - плохая идея, ибо невозможно будет отличить честно прочитанный из файла `-1` от `EOF`. В такой ситуации надо брать `EOF` за пределами диапазона -128 - + 127. Хоть `-400`, хоть `+328`, но не `-1`. Именно для того функции `getc` сделали тип возврата `int`, а не `char`. Я уже черт знает сколько это твержу.
Altravert 14.09.2010 06:44 # −1
Я заебался повторять, что речь идет о конкретном коде.
Я прекрасно понимаю, в чем разница между знаковыми и беззнаковыми и как они конвертятся. Я знаю, что "байта конца файла" нет. Однако я также на 95% уверен, каких кодов символов не будет в "/etc/resolv.conf".
Мы обсуждали конкретный случай, текстовый файл, конкретную уебанскую функцию getc, которую я не юзал и не буду. Он блять не бинарный. И знАком по умолчанию, как ты писал выше, управляет тот, кто компилирует.
Ты меня не слушаешь -> ничему не научишь. А я тебя тем более. Ветка в тупике половину времени её существования.
absolut 14.09.2010 07:31 # +2
"дать возможность пользователям получать советы, а не только быть обкладеными говнокоментами к накладенному ими говнокодом" ещё пока только ЗАПЛАНИРОВАНО.
Altravert 14.09.2010 07:53 # 0
TheCalligrapher 14.09.2010 07:34 # +2
Чтобы этот код "работал", необходимо соблюдение следующего условия: входной файл некогда не будет содержать байтового значения, которое при приведении к типу `char` данной платформы даст величину `EOF` данной платформы. В этом условии фигурируют три "переменных": содержимое входного файла, знаковость `char` и фактическое значение `EOF`.
Ты будешь утверждать, что в данном случае все эти три переменных сложатся так, что "все будет хорошо"? Прекрасно, пусть сложатся. Я охотно верю, что такое сочетание обстоятельств вполне возможно. Тем не менее завязка в коде на подобные сочетания всегда было и будет для меня классическим говнокодом. Тем более что написать правильно (т.е. портабельно, без завязок на какие-то посторонние обстоятельства) - легко и просто.
Altravert 14.09.2010 08:04 # 0
Все файлы бинарные. На POSIX и non-POSIX. Для них не существует константы EOF. Вообще. Однако, если ты пишешь код, предполагая, что этот поток байт является текстовыми данными в однобайтной кодировке, то для такой интерпретации данных есть как минимум одно значение байта, не являющегося валидными текстовыми данными. Если ты читаешь данные как бинарные, то ты должен явно указать, куда ты их читаешь, и по-моему это должен быть unsigned char. Явно указать.
Я говорю, что использовать EOF нельзя, ты говоришь, что использовать EOF нельзя, не заметил? Пиздос, спорим.
TheCalligrapher 14.09.2010 21:09 # +1
Во-первых, константа `EOF` есть всегда, что для POSIX, что для не-POSIX. Константе `EOF` плевать на POSIX. Константа `EOF` есть специальный код возврата функции `getc` (и аналогичных), означающий, что файл закончился. Никакой прямой связи с содержимым байтов в файле этот код возврата не имеет. Бинарный это файл или не бинарный, есть ли в этом файле спец. символ конца файла или нет и чему он равен - никакой роли не играет и на значение `EOF` никак не влияет. Любой файл рано или поздно заканчивается - это факт, и когда он заканчивается, функция `getc` возвращает `EOF`. Вот и все.
(Например, `EOF` как правило практически во всех реализациях равен просто `-1`, в то время как символ конца текстового файла на Windows-системах - 26 (0x1A). Улавливаешь связь, точнее полное ее отсутствие?)
Во-вторых, я никогда не говорил, что использовать `EOF` нельзя. Это фигня какая-то. Использовать `EOF` можно и нужно. Обязательно. Без вариантов. Вот чего делать нельзя, так это сразу безусловно пихать результат `getc` в переменную типа `char`. Потому что тем самым мы потенциально уничтожаем значение `EOF` и делаем его неотличимым от обычного байта прочитанного из файла. Всегда сначала надо прверить результат на `EOF` (еще в типе `int`), и только потом пихать его в `char`.
Это все, что я хотел сказать.
Опять же, в этом примере кода может быть "все будет работать". Но это не повод писать такой код, тем более что нормальный корректный вариант будет всего на 10-15 символов длиннее.
absolut 14.09.2010 22:07 # +2
Бывают нюансы, а-ля /dev/zero.
Altravert 15.09.2010 05:13 # 0
TheCalligrapher 15.09.2010 00:25 # 0
Altravert 15.09.2010 05:12 # 0
Докажи, пожалуйста.
TheCalligrapher 15.09.2010 05:45 # 0
Функция `getc` эквивалентна функции `fgetc`, как сказано в той же спецификации (идея в том, что `getc` может быть макросом, а `fgetc` - всегда функция).
P.S. Педантично настроенный оппонент может заметить, что на какой-нибудь экзотической платформе с sizeof(unsigned char) == sizeof(int) вполне возможно, что функция `fgetc` будет возвращать отрцательные значения даже при успешном чтении. Это так, но я не хочу переусложнять обсуждение.
Altravert 15.09.2010 06:06 # 0
ЗЫ: Представляю себе эту платформу. (sizeof(char) <= sizeof(short) <= sizeof(int)) и все это =1.
TheCalligrapher 13.09.2010 08:10 # +1
http://c-faq.com/stdio/getcharc.html
Altravert 13.09.2010 05:21 # 0
TheCalligrapher 13.09.2010 06:08 # +1
Пусть возвращают. Но я лично использование таких функций в условных выражениях как `if (!some_function(...))` для определения успеха буду называть индусокодом. Правильно: `if (some_function(...) == Success)` - и становится соврешенно не важно, что за значение они там используют для обозначения успеха.
Altravert 13.09.2010 06:19 # 0
bugmenot 13.09.2010 12:35 # −2
вообще-то бОльшая часть возвращает NULL как признак облома
absolut 13.09.2010 10:55 # +4
Я бы назвал это "обратное именование величины". Логичнее было бы сделать так:
ну, или вариант с #define если const для Си не прокатит.
С другой стороны, buffSize вообще дальше в коде не используется.
Ещё последние ветвления:
Если уж возвращаемый тип UINT32, то и возвращать надо целое.
А тут какая-то мешанина из -1 и !found. В имеющемся раскладе функция возвращает либо 0, либо -1.
Третьего не дано.
P.S. код действительно похож на сборную солянку. Тыренные куски из разных мест собраны в одной функции.
Altravert 13.09.2010 11:09 # 0
Кстати, возможно, возврат 0 при хорошем исходе по той же логике, что и strcmp() и подобные. Стайл увиден и повторяем.
А еще, кстати, учитываем три формы вывода ошибки и смешанные пробелы вокруг скобок if и выдаем вердикт: тру солянко.
Стремно видеть это у интела, но до говнокода не дотягивает все таки.. Мелковаты наши претензии.
absolut 13.09.2010 11:28 # +1
Хотелось бы убедиться насколько это является истиной.
А говно бывает разное. От сформированного до поноса с кровью.
raorn 13.09.2010 12:53 # +1
Да пожалуйста - http://git.kernel.org/?p=linux/networking/wimax/wimax-network-service.git;a=blob;f=InfraStack/OSDependent/Linux/OSAL/Services/wimax_osal_services.c#l421
absolut 13.09.2010 13:17 # +5
И ещё разнообразные "дефулты" :)
da4ever 13.09.2010 16:25 # 0
это заслуживает отдельного поста!
Govnoeb 13.09.2010 13:33 # 0
во2 не знаю "дотягивает" ли до говнокода сия поделка, но три ляпа налицо:
1) авторов не беспокоет, что char tag[] может переполнится
2) вместо выражения надежды что char line[] не переполнится, почему бы не запихнуть linep - line < 1000 в while()?
3) вообще-то еще hostName может переполнится если strlen(buffer) > hostNameBufSize
Govnoeb 13.09.2010 13:10 # 0
const int buffSize - константа выполнения
потом -1 - тоже целое, и для uint32_t будет равно 0xffffffff
далее, функция может вернуть одно из трех: 0, !0, 0xffffffff
absolut 13.09.2010 13:20 # +1
Кто сказал ?
>функция может вернуть одно из трех: 0, !0, 0xffffffff
!0 - в каком месте ?
Govnoeb 13.09.2010 14:17 # 0
не заметил return в else. функция не может вернуть !0. мой косяк
absolut 13.09.2010 15:22 # 0
Могут быть всякие нюансы относительно взятия адреса от такой константы, и настроек компилятора на этот счет.
Но в большинстве случаев const int buffSize = 512 будет именно константой времени компиляции.
TheCalligrapher 13.09.2010 15:58 # +3
В С `const int` - это не константа вообще никогда. Термин "константа" в С обозначает только литеральные константы - 5, 10, 2.5, 0xFF - и т.п. Поэтому использовать `const int` объект для обозначания размера массива в С не получится.
В С99 ввели Variable Length Arrays и разрешили использовать неконстантный размер для объявления локальных массивов (GCC разрешал это и раньше в качестве нестандартного расширения). Но в любом случае, если массив не локальный, то такой номер не пройдет.
absolut 13.09.2010 16:08 # 0
Именно поэтому было сказано "ну, или вариант с #define если const для Си не прокатит."
Насчет С/С++ согласен.
Govnoeb 13.09.2010 22:48 # 0
TheCalligrapher 13.09.2010 15:51 # +1
В язке С `const int buffSize` - это вообще никогда не константа, а условно выражаясь "константная переменная". В классическом С (C89/90) такой `buffSize` не может быть использован для задания размера массива. В C99 такой `buffSize` может быть использован только для задания размера локального массива (и получится в результате так называемый Variable Length Array). Но вот для задания размера `static` массива такой `buffSize` не может быть использован даже в С99. Поэтому в С для этих целей используется #define-константы.
TheCalligrapher 13.09.2010 15:54 # 0