LINUX.ORG.RU

Си


2

4
#include <stdlib.h>
#include <stdio.h> 

int main(int argc, char *argv[]) {

char *num = «5555»; 	
	
	if (argc != 2) {
	printf(«No param\n»);
		exit(0);
	}
	
	if (argv[1] != num) {
	printf(«Fail num %s\n»,num);
	printf(«Fail arg %s\n»,argv[1]);
		exit(0);
	}

...
}

Подскажите, почему сравниваются два одинаковых значения, но определяются, как - неодинаковые!

Вывод программы:

Fail num 5555
Fail arg 5555

Ответ на: комментарий от emulek

Это ты точно сказал! У меня самого велосипеды так вроде бы работают, а в один прекрасный момент — бац! И фигвам! Особенно «приятно», когда наблюдаешь ты, а у тебя вдруг — бац, и глюк в программке, собирающей данные с ПЗСки; приходится в срочном порядке в «боевых условиях» искать баг и перекомпилировать софтинку, пока небо не затянуло или утро не настало!

Anon
()
Ответ на: комментарий от Anon

Особенно «приятно», когда наблюдаешь ты, а у тебя вдруг — бац, и глюк в программке, собирающей данные с ПЗСки; приходится в срочном порядке в «боевых условиях» искать баг и перекомпилировать софтинку, пока небо не затянуло или утро не настало!

почему-бы тебе всё таки не прочитать про основные типы в сишечке, и не прочитать, в каких местах обычно встречается UB?

К сожалению ссылку не дам, не знаю. Знаю, что опыт НЕ написания кода UB формируется годами...

emulek
()
Ответ на: комментарий от emulek

Я несколько раз читал K&R и считаю, что прекрасно ориентируюсь в сишечке!

Просто обычно, когда делаю что-нибудь на скорую руку, не сильно-то беспокоюсь по поводу тщательного контроля. Вот иной раз и выскакивает всякая фигня (то буфер переполнится, то на нуль поделю, то еще что). Естественно, полная элементарщина у меня отсекается при помощи -Wall -Werror.

Anon
()
Ответ на: комментарий от dvl36

логирование(безусловный дебугпринт в «куда нибудь» в память) сильно увеличивало тайминги?

отладчик зло ( искать у Вирта) - ну а уж многоисполнительное(ните/процессо) хе хе хе.

qulinxao ★★☆
()
Ответ на: комментарий от Anon

Я несколько раз читал K&R и считаю, что прекрасно ориентируюсь в сишечке!

на самом деле сишечка — язык со строгой типизацией, блекджеком и шлюхами.

В качестве шлюх выступают правила преобразования типов, подобранные таким образом, что-бы тебя удовлетворять. Например, в нормальным ЯП со строгой типизацией нельзя указатель преобразовать в bool, но в сишечке есть шлюха, которая для тебя сделает из указателя целое, которое false если указатель NULL, и true в противном случае. Да так, что ты даже не заметишь, и будешь думать, что ты в уютном асме/бейсике, а то, что тебе сделало хорошо — твоя жена. Нет. Это сишечка. И это не жена, а шлюха. Она думает только о своём профите, а на тебя ей насрать. Если ты думаешь, что она заботится о тебе, попытайся загнать указатель 64 бита в int. Int сейчас 32х битный, и эта шлюха сделает так, как ей удобнее. Просто порежет нафиг указатель. Причём так, что обратно ты его уже и не восстановишь. И ты сам виноват, в стандарте ясно написано — UB.

Ну а UB выступает как блекджек. Ты можешь сыграть, и получить неплохой профит. Но удача в любой момент от тебя может отвернуться. Причём тогда, когда ты этого никак не ожидаешь. А ты ССЗБ, не рассчитывай на азартные игры, такие как UB. Особенно опасен блекджек, если с тобой шлюхи. И чем шлюх больше, тем быстрее тебя выкинут на мороз.

emulek
()
Ответ на: комментарий от tailgunner

отладчик добро для обнаружения не соответствия реализации компилятора его описанию.

в остальном же преждевременное его использование приводит к мозаичности знания языка.

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

отладчик зло

ИМХО отладчик — костыль. Для тех, кто пока ещё не умеет ходить самостоятельно. Это удобно, и полезно. Но ходить всю жизнь со здоровыми ногами и с костылями — плохо. Надо учится ходить, хотя это и сложно.

emulek
()
Ответ на: комментарий от qulinxao

отладчик добро для обнаружения не соответствия реализации компилятора его описанию.

разве для этого мало gcc -S ? Мне хватает.

emulek
()
Ответ на: комментарий от qulinxao

отладчик добро для обнаружения не соответствия реализации компилятора его описанию.

Отладчик - это добро для обнаружения несоответствия _любого_ алгоритма его описанию.

преждевременное его использование приводит к мозаичности знания языка.

Теоретики программирования в треде, все в машину.

tailgunner ★★★★★
()
Ответ на: комментарий от qulinxao

к несчастью не все референс реализации языков сделаны под gcc , тот же golang «например»

к счастью мне это не нужно.

emulek
()
Ответ на: комментарий от tailgunner

Отладчик - это добро для обнаружения несоответствия _любого_ алгоритма его описанию.

а какая разница между «алгоритмом» и его «описанием»?

emulek
()
Ответ на: комментарий от emulek

Что такое UB?

И какой, нафиг, bool в сях? Там bool — это просто int! И stdbool просто делает хитрость (т.е. что ни воткни в этот int, а он все равно будет давать либо 1, либо 0).

Anon
()

Вот это вброоос. Как я мимо-то прошел. Ну да. Строки в Си сравниваются именно с помощью «==». *бьется головой об стену*

coderage
()
Ответ на: комментарий от Anon

Что такое UB?

неопределённое поведение. Это когда случится может ВСЁ. Примеры:

int a[1];
a[1] = 17;//UB
int *p = a+1;
p++;//UB
(int)a;//UB, если int* МОЖЕТ не влезть в int.
// а оно может, никто не гарантировал ширину int.
// ИЧСХ, на amd64 так оно и есть.
p = NULL;
int ub = *p;//UB, NULL никуда не указывает
ub = p;//UB, NULL не лезет в int, см. выше. 
//Да, компилятор промолчит, если #define NULL 0
int b[22];
a == b;//UB, нельзя сравнивать указатели на разные массивы.
p-- - --p;//UB, brainfuck

И какой, нафиг, bool в сях?

там не всё так просто. Нет отдельного типа bool, но в семантике языка такой «тип» есть. Трактовать его можно как «целый тип нужного размера». Если указатель преобразовать в bool (засунуть внутрь if() например), то указатель сначала преобразуется (формально) в разность указателя и NULL, которая имеет тип ptrdiff_t. Численно это сам указатель и есть, как в ассемблере(если конечно у тебя NULL побитно равен нулю). Вот только размер его НЕ int. И вот прямо так ЭТО будет сравниваться с нулём.

Т.е. семантика языка такова, что когда компилятор хочет bool (if, while, ...), он преобразовывает выражение в подходящее целое, и сравнивает это целое с нулём. Проще всего выдрать bool таким кодом:

int b = !!(x);// преобразование в bool

emulek
()
Ответ на: комментарий от emulek

Отладчик — для тех, кто не хочет в голове делать то, для чего создан компьютер — выполнять программу.

PolarFox ★★★★★
()
Ответ на: комментарий от IvanR

у вас симпотичнее получилось,

int my_strcmp(const char *x, const char *y)
{
  while(*x && *y)
  {
    if(*x++ != *y++)
      return 1;
  }
  return 0;
}

это натуральный быдлокод, который даже «1» и «12» сравнить не сможет, про то, что на самом деле возвращает strcmp и вспоминать не будем

wota ★★
()
Ответ на: комментарий от PolarFox

Отладчик — для тех, кто не хочет в голове делать то, для чего создан компьютер — выполнять программу.

...и при этом хочет сначала писать, а потом думать (а чё не работает-то?!)

emulek
()
Ответ на: комментарий от wota

это натуральный быдлокод

за «быдлокод» ответишь?

который даже «1» и «12» сравнить не сможет

я знаю. Это не баг, а фича. Я к тебе не нанимался, что-бы для тебя код писать. Если надо, измени одну строчку, что-бы выдавала правильный ответ.

Ну а вообще, я уже выше писал, почему ЭТО вообще не нужно применять IRL.

про то, что на самом деле возвращает strcmp и вспоминать не будем

кто-то обещал тебе сделать аналог strcmp(3)? Может ты мне за это уже заплатил, а теперь обижаешься, что твой заказ выполнен не точно? Я что-то не припоминаю...

emulek
()
Ответ на: комментарий от wota

ты неправильно воспринимаешь. Мне по барабану. Не хочешь отвечать — никто не заставляет.

Оставим на твоей совести очередной слив: «всё неправильно, аффтор м*дак, это очевидно, а поправить я не смогу, потому-что никто всё равно не поймёт моего ОБВМ!»...

emulek
()
Ответ на: комментарий от emulek

Мне по барабану

я заметил ;)

Оставим на твоей совести очередной слив

о, так мы «знакомы», не напомнишь прошлый раз, когда я «сливался»?

wota ★★
()
Ответ на: комментарий от wota

о, так мы «знакомы», не напомнишь прошлый раз, когда я «сливался»?

лень искать, если честно.

Так ты код обсуждать будешь, или слив засчитывать? (:

emulek
()
Ответ на: комментарий от qulinxao

угу.

вторую ошибку можно исправить, если вместо 1 возвращать x[-1]-y[-1], а вместо *x||*y возвращать *x ? !!*y : -1

и я оопять не проверял (:

emulek
()
Ответ на: комментарий от emulek

эээээ есть такая проблема компы это ЦЭВМ.

поэтому указатели обязаны быть битовыми строками адрессами либо в память либо «адресами»-номерами в базе менеджера памяти которые по номерку будет возвращать значение(стороки бит той или иной длины).

и да. указатели очень хорошо идут обучением через массив- внутри которого в ручную реализуют свой менеджер различных «древесно/графовых» структур узлов , после такого массива заменителя указатели воспринимаются без всякой мистики

ну и вообще 0[m+i][m+j] :)

qulinxao ★★☆
()
Ответ на: комментарий от anonymous

использование массива из базовых элементов для своего блэкджека и балерин.

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

прежде чем заявлять баг ты хоть на нём код (мысленно желательно) проверял?

не зря я тебя игнорю...

~$ cat 1.c
int my_strcmp(const char *x, const char *y){
        return *x**y?*x||*y:my_strcmp(x+1,y+1);
}

int main() {
	printf( "%d\n", my_strcmp( "", "" ) );
}
~$ gcc -w 1.c && ./a.out 
1

и да - такие криворукие быдлокодеры еще про ненужность отладки говорят

// ваш д'Артаньян

wota ★★
()
Ответ на: комментарий от wota

учить нужно на сырцах с багами.

скажи что нужно исправить в моём быдлокоде ?

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

поэтому указатели обязаны быть битовыми строками адрессами либо в память либо «адресами»-номерами в базе менеджера памяти которые по номерку будет возвращать значение(стороки бит той или иной длины).

указатели в сишечке НИЧЕМ тебе не обязаны. Они вообще никому, кроме стандарта, не обязаны. А в стандарте такого правила нет.

Посему смирись — это твоя фантазия, что указатель кому-то должен.

По стандарту, указатель это отдельная сущность, для которой определены вполне определённые правила. Никакой «ЦЭВМ» в стандарте нет.

Существует также связь между указателем и целым. Это специальный тип ptrdiff_t для разности указателей, а также size_t, это тип размера в неких абстрактных char'ах. Во многих реализациях этот char является обычным байтом, но не обязательно.

Т.е. сишечка оперирует некоторой виртуальной ЦЭВМ. В отличие от скажем явы, эта виртуальная машина не эмулируется, а используется реальный CPU, на котором и выполняется код C.

Потому, писать код C надо так, что-бы он выполнялся на любых реальных CPU без переделок(в коде. Если стандарт говорит, что загрузка 0 в указатель даёт NULL, то компилятор обязан сделать из 0 _этот_ NULL, даже если он не нулевой. При сравнении компилятор должен вернуть этот нуль на место). Т.е. размер char'а в битах может быть любой, содержимое NULL любым, размер int в char'ах любой. А твой код всё равно должен отлично работать.

Также и выражение x-- - --x может выполняться тремя разными способами, и твой код должен правильно работать на всех трёх платформах, и давать один и тот же результат.

Также и функция f(X, Y) может вычислить сначала X, а потом Y, или наоборот, и твой код должен правильно работать в обоих случаях. Потому-что в стандарте не написано, в каком именно порядке считать. А следовательно порядок будет определён во время компиляции, а может даже в рантайме.

и да. указатели очень хорошо идут обучением через массив- внутри которого в ручную реализуют свой менеджер различных «древесно/графовых» структур узлов , после такого массива заменителя указатели воспринимаются без всякой мистики

нираспарсил.

ну и вообще 0[m+i][m+j] :)

Ах, какой ты умный! А тут почти все знают, что a[j] это синтаксический сахар над *(a+j). Потому не для кого не секрет, что это тоже самое, что *(j+a) и даже *(0+j+a).

emulek
()
Ответ на: комментарий от anonymous

А ты, прежде чем обзываться, спросил бы: а являюсь я вообще программистом?

Ты еще бы человека, который у себя дома ремонт делает, упрекнул в незнании базового ПТУшного курса "маляр-штукатур"...

Anon
()
Ответ на: комментарий от wota

ну убедил:

int my_strcmp(const char *x, const char *y){
        return *x**y?*x!=*y?1:my_strcmp(x+1,y+1):*x||*y;
}
qulinxao ★★☆
()
Ответ на: комментарий от Anon

Конечно являешься, ты ж там какую-то прикладную математику пишешь на сишечке.

Хотя в одном ты прав: слово неуч не подходит. Когда человек из религиозных побуждений отказывается от удобных инструментов, я хз, каким словом это называется.

anonymous
()
Ответ на: комментарий от emulek

о значении нераспарсенного абзаца.

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

после такого собственного менеджера легко и просто переходить к malloc|free

qulinxao ★★☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.