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

Указатель НЕ число!

Ну что ты тупняк несешь? Указатель — обычное 64-битное беззнаковое целое (на amd64). Их можно сравнивать, складывать-вычитать (в массивах это очень часто используется). Указатель — это же просто адрес переменной в виртуальном адресном пространстве данного процесса. А т.к. 0 нигде адресом не может быть (где и может, там по 0 обычно код самого процесса начинается), то его в стандарт и запихали, если dvl36 не врет.

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

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

мне важнее мыслить не «на нескольких уровнях», а на _нужном_ уровне. В случае стандарта, мне важно мыслить именно на уровне компилятора. Т.е. что-бы писать такой код, который компилятор понимает также как я. Если в стандарте написано UB, то писать так не нужно. Даже если все ЛОРовские аналитеги считают не так, как я и стандарт. А твой уровень и уровень муравья меня слабо волнуют.

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

несуществование по определению *NULL тоже удобное к использованию соглашение- вышеупомянутый Хоар ровно об этом и рыдал . что по причине ограничености NULL(в пределе лиш одно значение было NULL) возникла плохая ситуация когда NULL eq NULL вместо (NULL equal NULL)>(NULL eq NULL)

а что рыдать-то теперь? Тонны быдлокода с единственным NULL уже не перепишешь.

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

прочитай всё таки стандарт ( в котором как раз строка «T* a= 0;» парсится в a=NULL вне зависимости какое/ие значение указателей этой платформы приняты за NULL)

да я читал уже. Впервые много лет тому назад. Да, 0 преобразуется в NULL, если нужен указатель. А где я с этим спорил?

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

if((int)a==0){

И такое стандарт допускает

не допускает. В процитированной строчке UB. Пруф:

If the specified member is a bit-field, the behavior is undefined.

int в данном случае вполне катит за bit-field.

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

int * a = 0; if(a==0){ всегда true }

а это да, тут 0 превращается в указатель, и получается NULL. В обоих операторах так.

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

Ну что ты тупняк несешь? Указатель — обычное 64-битное беззнаковое целое (на amd64). Их можно сравнивать, складывать-вычитать (в массивах это очень часто используется)

ты упоролся. Сколько будет «указатель+указатель»?

Указатели можно лишь вычитать(на один и тот же массив), и получать ptrdiff_t. А этот ptrdiff_t можно складывать с указателем. Вот ptrdiff_t это действительно целое число.

Указатель — это же просто адрес переменной в виртуальном адресном пространстве данного процесса.

нет. Не просто адрес. Во первых компилятор знает, что это УКАЗАТЕЛЬ, во вторых он помнит НА ЧТО указатель. ptr+1 отличается для разных указателей. В коде это не ptr+1, а ptr+(ptrdiff_t)(sizeof(ptr[0]))

А т.к. 0 нигде адресом не может быть (где и может, там по 0 обычно код самого процесса начинается), то его в стандарт и запихали, если dvl36 не врет.

ИМХО причина в том, что 0 быстрее всего проверять/обрабатывать. Ну и опять-таки в сишечке традиционно нет типа bool, потому валидный указатель должен уметь быстро превращаться в true, а инвалидный в false. Ну так и получается само по себе, если уметь превращать в (int). очень удобно:

if(ptr)
// указатель хороший
else
// указатель плохой (NULL)
А внутри кода это вообще не требует никаких телодвижений, если NULL===0x0000.

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

Потому что это C, а не йава! Welcome!

на ява будет то же самое.

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

Сколько будет «указатель+указатель»?

Не так, а «указатель» + ptrdiff_t

ptr+1 отличается для разных указателей

Естественно: когда gcc компилирует код, он правильно вычисляет смещения.

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

у тебя с русским языком хуже чем у меня.

я как раз и показываю что битовое значение NULL указателя по стандарту может быть произвольным(т.е платформо-реализаци релейтед)

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

выше по тексту опонент гиклеса( и это вроде был ты) не распрарсивал в фразе гиклеса упомиеание 0 как имени null(т.е до конвертации в указатель) , а как число 0 и.

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

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

потому что boxing может быть только когда среді операндов есть Integer. Напрімер:

Integer.valueOf(5555) == 5555
(В этом случае будет каст на int, то есть результат -> true)

dzidzitop ★★
()

лор совсем измельчал

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

Почитай тред. Тут уже давно все выяснили, что имелось в виду, и срач идёт на другую тему.

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

Сколько будет «указатель+указатель»?

Не так, а «указатель» + ptrdiff_t

ты же говорил «можно складывать указатели», соврал?

Естественно: когда gcc компилирует код, он правильно вычисляет смещения.

вот когда компилятор помнит, что 0x123450 это не просто 0x123450, а адрес целого числа, вот тогда это и называется «тип».

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

Это не объяснение, это переформулировка.

Когда ты пишешь

Integer a = 5555;
это тоже самое, что и
int temp = 5555;
Integer a = temp;

Ява видит, что ты пытаешься присвоить переменной типа Integer значение типа int и автоматически конвертирует его так:

int temp = 5555;
Integer a = Integer.valueOf(temp);

Угу, в жабе даже 5555 == 5555 может дать False.

Эта твоя претензия — это полный бред.

5555 == 5555 в яве тождественно

int i = 5555;
int j = 5555;
System.out.println(i == j);
и всегда даёт true

То, что написал в доказательство ты

Integer i = 5555;
Integer j = 5555;
System.out.println(i == j);
тождественно Integer.valueOf(5555) == Integer.valueOf(5555)

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

у тебя с русским языком хуже чем у меня.

Не льсти себе. Да, доктор тоже трудночитаем, ибо «многа букав». Но, зачастую, распарсить тобой изложенное - это просто пипец.

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

ты же говорил «можно складывать указатели», соврал?

Не соврал: можно и два указателя сложить, просто не факт, что они на реальный объект будут указывать. А ты придрался к слову!

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

Ты тоже тред не читал, а решил сразу ответить?

Прочитал. Ты в самом первом комментарии, где 5555 == 5555, написал бред и продолжаешь возникать по этому поводу.

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

Прочитай чуть дальше первого комментария.

Какое слово в предложении «Прочитал.» тебе не ясно?

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

Если на клетке слона написано «Буйвол», не верь глазам своим. Если то, что ты говоришь, противоречит тому, что ты делаешь — угадай, что я проигнорирую?

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

Если на клетке слона написано «Буйвол», не верь глазам своим. Если то, что ты говоришь, противоречит тому, что ты делаешь — угадай, что я проигнорирую?

Проигнорируй, я не обижусь. Ты мне вот на какой вопрос ответь, ты всё ещё считаешь, что в яве 5555 == 5555 может давать разный результат? Или признаёшь, что в первом комментарии написал бред?

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

я как раз и показываю что битовое значение NULL указателя по стандарту может быть произвольным(т.е платформо-реализаци релейтед)

Я согласен с тем, что NULL может быть записан не только нулевыми битами, но доказательство у тебя некорректное. Как я уже говорил, NULL преобразуется в false, а false это таки 0.

Ну и вообще, любой указатель _можно_ преобразовать в целое, и получится 0, если указатель NULL, и не нуль, если указатель влезет в это целое, и UB если не влезет. Однако практической пользы от этого целого не много, т.к. непонятно, что с ним делать, кроме как сравнивать с нулём.

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

в С нет типов :)

забыл «ИМХО» приписать. В сишечке типы есть.

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

А вот в ассемблере типов таких нет. Что-бы не лежало в регистре, правила выполнения операций не зависит от содержимого. Никакой тип нигде в ассемблере не хранится, максимум задаётся в каждой команде (некоторый команды для signed, некоторые для unsigned, а иные для float)/

В сишечке тип есть, ибо там любая переменная(и константа) имеет вполне определённый тип. И от типа зависит выполнение операций. Но ты конечно имеешь право этого не видеть. Я разрешаю, пиши быдлокод и дальше.

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

Не соврал: можно и два указателя сложить

таки соврал. Нельзя.

просто не факт, что они на реальный объект будут указывать.

факт, что будут указывать погоду на Марсе за вычетом фазы луны. Возможно, это даже совпадёт с каким-нибудь объектом, я не спорю.

Тебе тоже разрешаю так писать. Я добрый.

Можешь даже в своём коде писать: Мне сам emulek разрешил складывать указатели! И ссылку на этот пост.

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

вообщем то это и есть ассемблер.

Тебе нужно бы попробовать ассемблер. Написать что-то реальное, не лабы. C-и по сравнению с asm-ом это «детсад». Полный и абсолютный «детсад». В asm-е, ведь, шаг влево, шаг вправо, и сразу «кирдык». Очень дисциплинирует, должен отметить.

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

Можешь скомпилировать сам и проверить. В gcc срабатывает, в tcc, естественно, нет.

Это не потому, что строки равны, а скорее потому что компилятор видит что они одинаковые и пихает в одно место... а вообще не знаю, попробуй -s и посмотри сколько раз в ассемблере слово hello

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

нет.

тока написание на асме сложнее(рутиней) чем на си - однако неожиданого поведения как раз меньше в асме чем в си , а в си чем в с++ именно по тому что модель проще в асме ( всё битовые «полоски» и набор операций над ними и их местоположением в памяти/регистрах) чем в си (есть несколько пережитков со static и прочим entry) чем в си++( который уже давно перегнал pl/i в «универсальности»)

ну и что бы ещё пост не писать :

[google] I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. [/google]

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

if ((*argv[1])) != (*num))

Это сравнение первых элементов будет

if (printf(«%s»,argv[1]) != printf(«%s»,num))

Это сравнение возвращаемого значения:

Return value Upon successful return, these functions return the number of characters printed (not including the trailing '\0' used to end output to strings).

Читай man 3 printf

То есть если длина одинакова, то вернёт одно и то же.

Поизучай лучше ассемблер, иначе так и не поймёшь. Советую fasm — с очень простым и понятным синтаксисом и мощной системой макросов... хотя AT&T-ассемблер считается более продвинутым, тут например GNU as.

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

Правильно было бы так:

Твоя функция вернёт 1 если строки одинаково начинаются, можно заменить && на ||

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

Написать что-то реальное, не лабы. C-и по сравнению с asm-ом это «детсад». Полный и абсолютный «детсад».

не. Везде свои сложности. Для меня было очень сложно понять технику указателей сишечки, я её год наверное осваивал и раскуривал... В асме всё просто, INC это всегда INC, и NULL это всегда 0. А в сишечке это не детсад, а зона боевых действий, когда враг применяет бактериологическое оружие. Вроде как бегаешь, прыгаешь, а на самом деле — ты уже труп. Шаг влево, шаг вправо — ☣. Но ты сам этого не знаешь, и у тебя даже всё работает.

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

Потому что это C, а не йава! Welcome!

nanoolinux не знает Java? :)

В ней поведение будет таким же самым.

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

(рутиней) чем на си

Пространства для творчества все равно больше. Реализовывая что-то на асм-е коротко и эффективно получаешь массу удовольствия от проделанной работы.

однако неожиданого поведения как раз меньше в асме чем в си

Неожиданного поведения действительно меньше в самом асм-е, но и права на ошибку меньше. А ведь еще нужно и взаимодействовать с системой. Впрочем, это зависит от того, что конкретно писать. Раньше, давно, я писал TSR-ы. Ошибка в обработчике - перезагрузка reset-ом, и только так. Отладить - очень, очень сложно.

It was the invention of the null reference in 1965.

Кто-то придумал что-то лучше? Проще и эффективней?

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

если ты писал TSR-ы , ты недостаточно стар.

и Вирт вообще против отладчиков :)

«право на ошибку» - охо хох

вроде как у Кернигана&Пайка? первейший совет мутить инструментарий.

упорно писать tsr без создания себе резидента на тот же int 4? c возможностью интроспекции состяния всей машины и диалоговым режимом - это действительно «безумство храбрых» :)

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

billion-dollar mistake

Таки в самом NULL нет ничего плохого. Проблема только в *x, для T* x при x == NULL, то есть в частичной операции разыменования — ну мало ли таких операций, приводящих к innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. operator[], например, или operator/, или operator- для unsigned, даже operator+/* для fixnums которые должны притворяться большими числами.

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от qulinxao

«право на ошибку» - охо хох

Я имею в виду, что tasm тебя не предупредит, о том что ты сделал что-то не так, как это бывает в языке.

первейший совет мутить инструментарий.

Оплачивать время, потраченное на создание собственного инструментария, никто не собирался. Был готовый TSR с дизассемблером и плюшками, но он не исполнял.

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

это задача с целевой минимизации времени&усилий ,

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

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

это задача с целевой минимизации времени&усилий

Ты, все же, не совсем понимаешь о чем речь. Представляешь отладку обработчика аппаратного прерывания, таймера, например?

Про реентерабельность кода DOS-а и BIOS-а слышал? Возможности все остановить и посмотреть на состояние обычно не было, ибо «железо», и все в динамике.

если проще «страдать ресетами»

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

то сейчас ссылатся на это как на опыт «превозмогания» это как бе .

Частые ресеты, они у нубов только. А вообще дисциплинируют, знаешь ли. Заставляют много думать, прежде чем что-то печатать, и очень внимательно проверять свой код. Хорошие качества развивают. Жаль что я уже «расслабился» в этом плане.

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