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

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

Ещё раз, для совсем тупых.

Я ЗНАЮ эти технические подробности. Я не понимаю, почему технические трудности имплементоров должны меня хоть сколько-то волновать.

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

Я ЗНАЮ эти технические подробности. Я не понимаю, почему технические трудности имплементоров должны меня хоть сколько-то волновать.

Если знаешь, нафига пишешь быдлокод?

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

и да,

int array[3];
int *p = array;
p += 2;// можно
*p = 17;// можно
p++;// ещё можно
*p = 22;// уже нельзя. UB. Нет там НИЧЕГО.
p++;// тоже нельзя, UB, переполнение указателя.

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

Я ЗНАЮ эти технические подробности. Я не понимаю, почему технические трудности имплементоров должны меня хоть сколько-то волновать.

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

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

Оправдать в чём? В том что она по умолчанию кэширует объекты что ли?

В подобном поведении ==.

Все это время анончик тщетно пытается оправдать жабу тем, что это не == работает неоднозначно, а = для Integer и числа.

Анонимус настолько плох что не может в логику?

Всё это время я пытаюсь объяснить товарищам, что они не умеют сравнивать объекты в жаве.

Продолжайте, желаю удачи в вашем нелегком деле просвещения.

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

Если знаешь, нафига пишешь быдлокод?

Для окончательно тупых. Я ОБСУЖДАЮ ПОВЕДЕНИЕ языка Java. Я не спрашиваю, как написать что-либо. Я не спрашиваю, в какую позу мне надо встать, чтобы язык работал так, как нужно. Я ОБСУЖДАЮ здесь, КАК он себя ведёт.

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

Для окончательно тупых. Я ОБСУЖДАЮ ПОВЕДЕНИЕ языка Java. Я не спрашиваю, как написать что-либо. Я не спрашиваю, в какую позу мне надо встать, чтобы язык работал так, как нужно. Я ОБСУЖДАЮ здесь, КАК он себя ведёт.

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

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

оно конечно стандарты дело хорошее и придерживатся их себе и окружающим меньше проблем.

однако в си(переносимый ассемблер который) намеренно «нет типов как таковых»

ну и само наличие адресной арифметики гарантирует, что указатели «числа»

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

ну слу .

в с ты можеш и тебе ни рантайм ни компилятор(если настойчего его попросиш) не восприпятствуют писать/читать что угодно откуда/куда угодно.

.

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

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

В подобном поведении ==.

Найди десять отличий.

$ cat Test.c
#include <stdio.h>
#include <stdlib.h>

void print(const int* a, const int* b, const int* c) {
  printf("a %s b\n", (a == b) ? "==" : "!=");
  printf("a %s c\n", (a == c) ? "==" : "!=");
  printf("b %s c\n", (b == c) ? "==" : "!=");
  printf("*a == %d\n", *a);
  printf("*b == %d\n", *b);
  printf("*c == %d\n", *c);
  printf("\n");
}

int main(int argc, char *argv[]) {
  int* number1 = (int*) malloc(sizeof(int));
  int* number2 = (int*) malloc(sizeof(int));
  *number1 = 1;
  *number2 = 2;

  const int* a = number1;
  const int* b = number2;
  const int* c = a;
  
  print(a, b, c);
  
  c = b;
  b = a;
  
  print(a, b, c);
  
  free(number1);
  free(number2);
  return 0;
}
$ ./a.out
a != b
a == c
b != c
*a == 1
*b == 2
*c == 1

a == b
a != c
b != c
*a == 1
*b == 1
*c == 2

$ cat Test.java
public class Test {
  static void print(Integer a, Integer b, Integer c) {
    System.out.printf("a %s b\n", (a == b) ? "==" : "!=");
    System.out.printf("a %s c\n", (a == c) ? "==" : "!=");
    System.out.printf("b %s c\n", (b == c) ? "==" : "!=");
    System.out.printf("*a == %d\n", a.intValue());
    System.out.printf("*b == %d\n", b.intValue());
    System.out.printf("*c == %d\n", c.intValue());
    System.out.printf("\n");
  }

  public static void main(String[] args) {
    Integer number1 = new Integer(1);
    Integer number2 = new Integer(2);

    Integer a = number1;
    Integer b = number2;
    Integer c = a;
    
    print(a, b, c);
    
    c = b;
    b = a;
    
    print(a, b, c);
  }
}
$ java Test
a != b
a == c
b != c
*a == 1
*b == 2
*c == 1

a == b
a != c
b != c
*a == 1
*b == 1
*c == 2

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

Оправдать в чём? В том что она по умолчанию кэширует объекты что ли?

В подобном поведении ==.

логика тут в том, что Integer вовсе не обязан быть тем, что хочется тебе. И не обязан вести себя так, как тебе хочется. Если ты этим не доволен — ступай варить борщ делать свой ЯП.

int* в сишечке это тоже НЕ int. И на твои хотелки всем насрать. Это разве не логично?

Я не знаю точно как в жабе, но вот про сишечку знаю: там тоже иногда можно сравнивать int*, а иногда(точнее почти всегда) — нельзя. Причём это «нельзя» тоже не всегда отлавливается компилятором (а если и отлавливается, то часто как варнинг, который говнокодеры принципиально игнорируют). Т.ч. это не какой-то «жабоспецифичный баг», а вполне себе общее правило. Сформулировать его можно так: результат арифметической операции зависит от спецификации ЯП, а не от хотелок ЛОРовских аналитегов.

Смирись с этим.

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

Для окончательно тупых. Я ОБСУЖДАЮ ПОВЕДЕНИЕ языка Java. Я не спрашиваю, как написать что-либо. Я не спрашиваю, в какую позу мне надо встать, чтобы язык работал так, как нужно. Я ОБСУЖДАЮ здесь, КАК он себя ведёт.

для тех, кто в бункере: ЯП (любой, в частности ява), ведёт себя так, как указано в его спецификации.

А совсем не так, как «нужно» тебе.

В данном случае он ведёт себя так, как лучше на данной платформе. Т.е. зависит от конкретной системы, на которой запущен. И это — логично.

Сишечка вот такой код int x = 7; int y = x-- - --x; на моей платформе считает эквивалентным коду int x = 5; int y = 0;, по той причине, что во первых такая трактовка допустима, а во вторых она самая быстрая и самая экономичная. Ну а на другой платформе трактовка может быть иной, разве это не логично? ИМХО верх логики. У жабы более жёсткие рамки, потому результат этого говнокода тоже другой, более медленный и дорогой естественно. Но суть та же.

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

однако в си(переносимый ассемблер который) намеренно «нет типов как таковых»

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

ну и само наличие адресной арифметики гарантирует, что указатели «числа»

ничего оно не гарантирует. Разделяй свои фантазии от реальной жизни. Я понимаю, что в красивом фантике тебе хочется найти конфетку, но реальность такова, что там может быть и дерьмо. Смирись с этим.

Наличие какой-то арифметики никак не гарантирует того, что все правила из известной тебе арифметики просто переносятся в новую без изменений. Если в обычной арифметике int тебе нельзя только переполнять числа и делить на ноль, то в адресной арифметике тебе нельзя НАМНОГО больше. Даже банальное == почти всегда выдаёт такой же «результат», как и деление на ноль в целых. А переполнение может наступить при сложении нуля с четвёркой. И тут нет никаких «нелогичнностей», ибо int чисел у тебя INT_MAX-INT_MIN, а вот указателей у тебя всего на 1 больше, чем эл-тов массива.

И да, что такое «умножение указателей», и тем более «деление указателей» я вообще не врубаюсь. А вот для int это тривиально. Потому-что int это безразмерная сущность, и произведение int'ов имеет тип int, а вот указатель — принципиально другое, и произведение указателей должно иметь тип «квадратный указатель», а что это такое мне непонятно.

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

в с ты можеш и тебе ни рантайм ни компилятор(если настойчего его попросиш) не восприпятствуют писать/читать что угодно откуда/куда угодно.

ты не думал поменять свой ник на «govnokoder»? Я не думаю, что кто-то будет против такой замены. Ну а раз никто не против, то почему ты ещё не поменял? ИМХО ты нелогичен, раз можно, значит так и надо делать!

И да, не забудь отстрелить свои яйца. Это тоже можно сделать, и никакой огнестрел этому не помешает (:

Зато генофонду планеты ты принесёшь неоценимую услугу...

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

void print(const int* a, const int* b, const int* c) {printf(«a %s b\n», (a == b) ? «==» : "!=");

вот ты сишечки не знаешь, и потому тебе непонятно, что этот говнокод НЕ ПРУФ. Данный говнокод имеет полное право вывести «fuck off!», а вовсе не то, что у тебя получилось. То, что получилось у тебя, всего лишь совпадение, и ничего не доказывает.

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

Ну, был бы ЛОР на КОИ8, я бы не вставлял юникодные смайлики. Можно подумать, я бы сильно обиделся…

А Кнут — легенда. Ему памятник только за ТеХ поставить надо!

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

что этот говнокод НЕ ПРУФ. Данный говнокод имеет полное право вывести «fuck off!», а вовсе не то, что у тебя получилось. То, что получилось у тебя, всего лишь совпадение, и ничего не доказывает.

Обоснуй.

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

P.S. Доктор, тебя снова заносит. Вспомни про участь зеленой лошади.

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

Ну перепиши правильно

«правильно» в данном случае сравнивать *a == *b, а результат a==b может быть КАКИМ УГОДНО. Ну точно также, как результат 0/0. Как это выражение нужно «переписать»?

Что-бы понять это, попробую найти аналогию в IRL, попробуй сравнивать не указатели в сишечеке, а указатели на дорогах. Вот например сравни указатель «St. Petersburg» и указатель «St. Petersburg». Тот, что рядом со мной указывает на один город, а тот, что во Флориде — совсем на другой. Причём в том же месте, что и мой указатель, есть ещё и указатель «Moscow», их координаты(указателей) равны, что не мешает им указывать на совершенно разные объекты. Точно также и в сишечке: расстояние между указателями ну вообще НИЧЕГО не говорит об расстояниями между объектами. А == в сишечке как раз и говорит о том, что расстояние между аргументами нулевое.

На самом деле указатель в сишечке равен исключительно самому себе, и это не фича, а баг, который введён для того, что-бы быстрее работало. По уму попытка сравнения указателей должна валить программу с исключением. Ибо предопределённый указатель NULL по определению никуда не указывает, и потому NULL != NULL (как в SQL). Но это больно сложная логика, и K&R решили не усложнять, а сделать попроще. Да и не сделать такое в сишечке, ибо в ней просто нет такого типа, который никак не определён, вроде NIL из CL. Вот и получилось так, что void* разименовывается в хрен знает что, и что сравнение указателей тоже даёт хрен знает что. Ну и многое другое тоже работает хрен знает как.

Но всё это тщательно документировано, потому _можно_ писать вполне годный код. Никто же не заставляет сравнивать указатели?

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

Ну, был бы ЛОР на КОИ8, я бы не вставлял юникодные смайлики. Можно подумать, я бы сильно обиделся…

а ЛОР тут не причём. Юникод ты можешь вствлять на любой форум, в т.ч. и в koi8. Ведь & # никто не запрещает.

А Кнут — легенда. Ему памятник только за ТеХ поставить надо!

ну и как по твоему читать выхлоп ТеХа в koi8-r? Формулы ты как увидишь? Вот с такими значками: ∀

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

Сделать массив, нет?

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

void print(const int* a, const int* b, const int* c) {
  printf("a %s b\n", (a == b) ? "==" : "!=");
  printf("a %s c\n", (a == c) ? "==" : "!=");
  printf("b %s c\n", (b == c) ? "==" : "!=");
  printf("*a == %d\n", *a);
  printf("*b == %d\n", *b);
  printf("*c == %d\n", *c);
  printf("\n");
}

int main(int argc, char *argv[]) {
  int* numbers = (int*) malloc(2 * sizeof(int));

  number[0] = 1;
  number[1] = 2;

  const int* a = number[0];
  const int* b = number[1];
  const int* c = a;
  
  print(a, b, c);
  
  c = b;
  b = a;
  
  print(a, b, c);
  
  free(numbers);
  return 0;
}

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

Обоснуй. Все с этим кодом правильно, хотя я бы так не стал делать.

Обоснование в том, что == является арифметической операцией. Да, по стандарту можно сравнивать указатели, и ответ получается true если p == p, и false если p1 == p2, при этом p1 указывает на другой объект, нежели p2. Но это послабление стандарта, связанное с упрощением. Оно _может_ работать неправильно. ИЧСХ работает неправильно, потому-что NULL == NULL, а результат этой операции должен быть неопределённым (т.к. неопределено «в никуда» == «в никуда»)

В стандарте таких мест довольно много, это совсем не говорит о том, что их можно и нужно использовать.

Просто потому, что ЯП это всего-лишь отражение реальной жизни, и он просто не может всё что угодно описывать. Да и не должен. Ну простой пример: в реальности нет самого большого целого числа, а по стандарту нет целых чисел больше INT_MAX. Ну и что? Всё равно лучше не использовать в своём коде этот INT_MAX, будь он хоть трижды описан. Это тоже упрощение, ибо иногда без него сложно обойтись(так, что-бы не потерять в производительности и/или в размере кода и/или в совместимости)

Доктор, тебя снова заносит. Вспомни про участь зеленой лошади.

лошадь — она и есть лошадь (:

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

Но это послабление стандарта, связанное с упрощением. Оно _может_ работать неправильно.

C это низкоуровневый язык, на нем ядра пишут. И сравнение указателей это норма.

работает неправильно, потому-что NULL == NULL,

Константа нулевого указателя — это целочисленное константное выражение со значением 0, или (только в Си) такое же выражение, но приведённое к типу void *.

http://ru.wikipedia.org/wiki/NULL_(%D0%A1%D0%B8)

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

Сделать массив, нет?

ну тогда код по моему мнению правильный, хотя и даёт «неправильный» результат. Ну в том смысле, что ТС хотел другой.

Если это массив, то можно не только == использовать, но и < и >. И эти значки будут давать вполне годный и осмысленный результат. Только этот результат всё равно будет никак не связан с содержимым массива (:

Т.е. &a[1] < &a[2], причём это никак не зависит от того, что там внутри. Да и непонятно, чем это лучше/хуже 1 < 2 ? Ну кроме того, что если это указатели, то мы можем прыгать по этому массиву, и p1 < p2 значит, что p1 ещё не догнал p2. (именно потому можно сравнивать указатель с указателем который ЗА верхней границей массива, что-бы просто и быстро сделать проверку того, что мы вышли за границу. Т.е. for(p=array; p<&array[sizeof(array)/sizeof(array[0])]; p++))

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

что ТС хотел другой.

Дык я не для ТСа пишу.

причём это никак не зависит от того, что там внутри.

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

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

Но это послабление стандарта, связанное с упрощением. Оно _может_ работать неправильно.

C это низкоуровневый язык, на нем ядра пишут. И сравнение указателей это норма.

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

Сравнение указателей в сишечке это «норма», вот только не надо этой нормой злоупотреблять...

PS: срал я на твою википедию. 7.17

3
The macros are
NULL
which expands to an implementation-defined null pointer constant; and
offsetof(type, member-designator)
which expands to an integer constant expression that has type size_t, the value of
which is the offset in bytes, to the structure member (designated by member-designator),
from the beginning of its structure (designated by type). The type and member designator
shall be such that given
static type t;
then the expression &(t.member-designator) evaluates to an address constant. (If the
specified member is a bit-field, the behavior is undefined.)
учимся читать стандарт, а не мнение каких-то *****. Т.к. в стандарте ясно сказано, что «expands to an integer constant expression», то становится очевидно, что в сишечке NULL==NULL. Но по логике самого указателя «в никуда», это не правильно. Но и «правильно» тоже сделать невозможно, т.к. в сишечке нет типа, который может иметь неопределённое значение.

И да, _значение_ NULL в стандарте НЕ определено, и ясно сказано, что «implementation-defined». Если в твоём wintel оно ноль, то это твоя проблема.

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

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

как я понимаю — не всегда. Ведь в яве иногда результат == зависит от значения, а иногда не зависит? Я правильно понимаю?

А вот в сишечке НИКОГДА не зависит. Только «зависит» если сравниваешь указатель сам с собой, в этом случае результат действительно всегда true, как и значение всегда одинаковое. Даже в том случае, когда указатель «указывает» В НИКУДА(а значение попросту не существует).

Кстати, в яве есть ссылки, которые никуда не указывают? Если да, то они все «равны»? А что будет, если разименовать? В сишечке по стандарту UB, а в Linux программа падает с сегфолтом.

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

Ведь в яве иногда результат == зависит от значения, а иногда не зависит? Я правильно понимаю?

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

int a = 1;
int b = 2;
if (a == b) {} else {}
Всё кроме этих восьми примитивных типов является «ссылочными типами». Их можно сравнивать операторами «==» и "!=", операторов «>» и «<» для них нет. Если две переменных a и b ссылочного типа указывают на один и тот же объект, тогда a == b будет true. Если они обе указывают на null, тогда a == b тоже будет true. Если они указывают на два разных объекта, тогда a == b будет false. Если a или b не инициализованны, тогда компилятор тебя обматерит. Ещё компилятор тебя обматерит, если типы данных у a и b разные, с оговоркой на наследование. Чтобы сравнить значения a и b, надо писать a.equals(b).

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

сделаны в ущерб логике, в угоду производительности

Логика бывает направлена в угоду производительности.

учимся читать стандарт

И правильно делаете, что учитесь. Учитесь прилежнее, ибо приведенное ниже ваше утверждение идет вразрез со стандартом:

И да, _значение_ NULL в стандарте НЕ определено, и ясно сказано, что «implementation-defined».

6.3.2.3 Pointers
...
3 An integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant.55) If a null pointer constant is converted to a
pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal
to a pointer to any object or function.
------
55) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.17.

Документ: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

Если в твоём wintel оно ноль, то это твоя проблема.

Я для armel разрабатываю и, внезапно:

#ifndef _LINUX_STDDEF_H
#define _LINUX_STDDEF_H



#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif


#endif

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

SO/IEC 9899. 6.3.2.3 Pointers, параграфы 3 и 4.

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.55) If a null pointer constant is converted to a

pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function. и что? Тут говорится только то, что константа =0 кастуется в NULL если ты кастуешь в void*. Но это совсем не означает, что NULL не может быть скажем 0xFFAD17. Или ещё чему-нибудь. В приведённой мною цитате ясно сказано, что значение не определено.

Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.

А этим ты мне что доказываешь? У тебя чтением проблемы?

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

Если две переменных a и b ссылочного типа указывают на один и тот же объект, тогда a == b будет true. Если они обе указывают на null, тогда a == b тоже будет true. Если они указывают на два разных объекта, тогда a == b будет false

а если определить один Intager и СРАЗУ второй такой же Intager, то для них ява сделает один объект, я правильно понимаю? Ну типа как в сишечке «xyz»==«xyz»(хотя и обматерит, но получится true).

Чтобы сравнить значения a и b, надо писать a.equals(b).

угу. А в сишечке надо для ASCIIZ юзать strcmp(3).

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

И да, _значение_ NULL в стандарте НЕ определено, и ясно сказано, что «implementation-defined».

вразрез со стандартом: The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.17.

ты белены объелся? Я же тебе специально 7.17 привёл. Это определение МАКРОСА, а НЕ ЗНАЧЕНИЯ. Т.е. там написано только как СДЕЛАТЬ это ваш NULL, а вот что получится — не написано. И мало того, написано, что получится может всё, что угодно (конечно только в определённых рамках). Да, в x86 получается 0x00000000, это ничего не доказывает.

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

#define NULL ((void *)0)

и где тут написано, что NULL это целое «ноль»?

Вот ты всё никак не можешь понять простой вещи: преобразование типов вовсе не обязательно представляют собой тупое копирование. Даже для целых чисел тупое копирование не работает(например char x = -1, и при этом x == 255, если его тупо скопировать в более широкий int), а уж для указателей так вообще может быть что угодно. Указатели вообще не обязаны ложится в какие-либо целые числа, например в x86 до 32х бит размер указателя был 20 бит эффективных, при этом он был в виде 32х битного числа, из двух 16и битных половинок, которые складывались. Т.е. один и тот же адрес можно было представить с помощью 2048и разных указателей. В частности было ровно 2048 абсолютно идентичных указателей NULL, и только один из них был равен 0x0000 0000. А вот например второй NULL был равен 0x0001 FFF0, что тоже самое для i8086. Конечно что-бы не сношать мозг использовались только «правильные» указатели.

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

#if defined(__cplusplus) #define NULL 0

и да, разница тут в том, что формально в C++ _всегда_ применяется оператор преобразования, даже для встроенных типов. Т.е. строчка

int x = NULL;
в C++ всегда будет правильно работать, ибо int -> указатель ->int всегда даёт для нуля ноль.

А вот в C неявные преобразования происходят не всегда, а только тогда, когда младший тип преобразуется в старший. Посему эта строчка в сишечке вообще не соберётся, ибо не имеет смысла. А если определить NULL как в C++, то соберётся, но будет работать неправильно, ибо «правильно» это побитовое копирование, а если NULL не равен 0 побитно, то будет ошибка, причём она будет незаметна до тех пор, пока это всё тестируется где NULL === 0.

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

а вот что получится — не написано.

Все написано:

7.17
3 The macros are
NULL
which expands to an implementation-defined null pointer constant;
...
6.3.2.3
3 An integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant.

Да, в x86 получается 0x00000000, это ничего не доказывает.

И в ARM-е и в MIPS-е. Ты хоть можешь назвать платформу где это не так?

P.S. Доктор, бронелобость это не признак ума.

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

И да, _значение_ NULL в стандарте НЕ определено, и ясно сказано, что «implementation-defined». Если в твоём wintel оно ноль, то это твоя проблема.

Скажи, а ты не пытался стандарт ЧИТАТЬ? Если пытался, то каковы были успехи?

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

На аппаратном уровне null pointer constant не обязан состоять из одних нулей. Но стандарт указывает, что константа 0 это и есть null pointer constant в рамках языка.

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

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

а если определить один Intager и СРАЗУ второй такой же Intager, то для них ява сделает один объект, я правильно понимаю? Ну типа как в сишечке «xyz»==«xyz»(хотя и обматерит, но получится true).

Тут сложнее. В жаве константа состоящая только из цифр, например 42, имеет тип int. Жава умеет автоматически конвертировать int в Integer и наоборот, это называется «boxing» и «unboxing».

Так создаётся два разных объекта:

Integer a = new Integer(42); //Конструктор Integer вызывается с параметром типа int
Integer b = new Integer(42);

Так создаётся один объект:

Integer a = new Integer(42);
Integer b = a;

А если ты пишешь так, то результат даже не UB, а зависит от настроек jvm, в которой пользователь запустит твою программу:

Integer a = 42;
Integer b = 42;
Ты по сути пытаешься присвоить значение типа int переменной типа Integer. Это вообще позволяется только благодаря «boxing». Раз ты написал Integer, значит тебе нужен Integer, а не int, жава тебе его сделает. Она, в зависимости от настроек, либо создаёт новые Integer'ы, либо использует кэшированые. Так как значения 42 и 42 одинаковые, то жава может взять один и тот же объект из кэша.

Проблем не возникает, поскольку Integer иммутабелен, тоесть ты не можешь изменить объект, на которой a или b указывает. Например:

Integer a = new Integer(42);
Integer b = a;
// Сейчас a и b указывают на один и тот же объект со значением 42
// Сейчас я попытаюсь изменить значение b, как будто b - обычный int, а не Integer
b++; // жава берёт Integer b, конвертирует его в int ("unboxing"), добавляет к int единицу, создаёт или берёт из кэша Integer со значением 43 ("boxing"), присваевает его b
// Сейчас a и b указывают на два разных объекта со значениями 42 и 43

А если кто-то делает так:

Integer a = 42;
Integer b = 42;
if (a == b) {
}
вместо:
int a = 42;
int b = 42;
if (a == b) {
}
тогда этот кто-то либо отдаёт себе отчёт, что результат зависит от настроек жавы, либо этот кто-то - обезьяна.

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

Зацепка тут только в том, что при кастинге из целочисленной константы 0 в *void может получиться вовсе не 0x0 адрес. Да, теоретически может. Практически - очень сомневаюсь. 0 ведь выбран неспроста.

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

Лол, ты вообще понял о чем базар?

Если коротко, в ждаве есть базовые типы (int, long, char и т.д.) они сравниваются по значению. Что бы сравнивать их по ссылке нужно сделать обертку.

class MyInt
{
  public int value;
  public MyInt(value)
  {
    this.value = value;
  }
}
int x = 50;
int y = 50;
x == y //true

MyInt a = new MyInt(50);
MyInt b = new MyInt(50);
a == b //false

Сравнивать числа по ссылке нужно, естественно, что в стандартной библиотеке уже есть MyInt - Integer. Беда в том, что этот класс не простой, а магический.

Во-первых, можно писать так (перегрузки «=» в java нет, магия):

Integer b = 30;
Во-вторых, взывает когнитивный диссонанс в промежутке от -128 до 127:
Integer a = 30;
Integer b = 30;
a == b //true

Integer x = 300;
Integer y = 300;
x == y //false

Integer w = new Integer(30);
Integer t = new Integer(30);
w == t //true

В поседением случае объект был создан явно. В первом a и b ссылаются на один и тот же объект из буфера. Во втором x и y неявно создаются как new Integer(300).

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

Сишечка вот такой код int x = 7; int y = x-- - --x; на моей платформе считает эквивалентным коду int x = 5; int y = 0;, по той причине, что во первых такая трактовка допустима, а во вторых она самая быстрая и самая экономичная.

Трактовки бывают только у библий и коранов. То что разные компиляторы по разному трактуют этот код - проблема.

Kuzy ★★★
()

argv[1] - массив символов num = num[0] - первый символ

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

Она себя ведёт так, как от неё этого требует программист.

Это не значит ничего вообще. Так делают все языки и даже PHP.

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

Ты хоть можешь назвать платформу где это не так?

это не важно.

Доктор, бронелобость это не признак ума.

этот вопрос уже обсуждался Over9000 раз. Можешь поискать обсуждения, и сделать для себя выводы. Если где-то написано, что «чёрное — чёрное», то в рамках этого чего-то чёрное — чёрное. Вот в стандарте C написано вот так вот. Смирись с этим. Не нравится — иди варить борщ/писать свой ЯП.

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