LINUX.ORG.RU

Особенности инициализации переменных в c/c++

 ,


0

4

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

1:

int a = 0,
    b = 0,
    c = 0;


2:
int a,
    b,
    c = 0;


3:
int a = 0;
int b = 0;
int c = 0;


Первые два приводят к тому, что переменные a, b содержат мусор, и только третий вариант работает как положено. В теории все три варианта равнозначны. Или нет?

★★

Ничего, что это — два абсолютно разных языка программирования? Какого хрена их через черточку пишут?

Потому, что в большинстве случаев можно писать на C и компилировать компилятором для C++. Бьерн сказал, что C - это подмножество языка C++.

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

Мало ли что Бьерн сказал? Это было черт-те когда, сейчас же кресты вообще от С ушли далеко. Скажем, я, дофига чего на С написавший, как вижу код на крестах, смотрю на это, как на китайские письмена!

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

Мало ли что Бьерн сказал?

Действительно, кому важно мнение изобретателя языка.

Это было черт-те когда, сейчас же кресты вообще от С ушли далеко.

Именно поэтому их и называют C++11, C++14, C++17.

Скажем, я, дофига чего на С написавший, как вижу код на крестах, смотрю на это, как на китайские письмена!

На C можно написать так, что и очень опытный C-программист ничего не поймет. Аналогично и с C++.

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

Второй вариант инициализирует только c.

Это я уже понял. Просто после того как потратил два часа на ища косяк в других местах, где использовались эти переменные (и моей полной уверенности в том, что они инициированы нулями) я начал сомневаться в собственных умственных способностях и знаниях элементарной арифметики.

ЗЫ
Под убунтой первый вариант отработал как задумано.

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

в большинстве случаев можно писать на C и компилировать компилятором для C++.

Сломается на первом же

T* ptr = malloc(...); // T != void, char...

utf8nowhere ★★★
()
Ответ на: комментарий от andreyu
int * p;
void * ptr = p;

это то же типизация?

В крестах просто убили семантику void* в одну сторону, но не убили полностью. К типизации это не имеет никакого отношения.

То, о чём ты пытаешься говорить - имеет отношения к ситуации с автокастом между указателями разных типов, но к void * это отношения не имеет.

Т.е.

int * p;
char * p0 = p;//это автокаст. Который не разрешен в С++ и требуется делать каст.

void * p1 = p;//это void *, который является выделенным, отдельным случаем. Что в Си, что в С++.

p = p1;//это так же void *, который так же является отдельно выделенным ото всех остальных "типом" указателя. Это часть семантики void *, которая переопределена в С++. Это не работает в С++.

//Но ни к какой типизации сильной/слабой это не имеет отношения. Т.к. воид в первом случае работает так же, как он работал в си. Хотя типы разные. Это неработает в некоторых случаях, но это исключения - т.к. это чисто крестовая логика - те же указатели на методы.
rustonelove
()
Ответ на: комментарий от andreyu

Я тебе говорю про всякий бред вроде шестикратного наследования, чисто виртуальных функций и долбаных шаблонов! Вот где шаблон рвет!!!

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

Тут с вами соглашусь, язык позволяет создать какашку на ровном месте. Но если отбросить эмоции и снять розовые очки, то можно заметить, что не менее страшную какашку можно сделать и на си. Что мы и наблюдаем во множестве открытых проектов.

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

про всякий бред вроде шестикратного наследования, чисто виртуальных функций и долбаных шаблонов!

чисто виртуальных функций

Как тебя, наверное, пугают нулевые указатели на функции в Си.

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

В крестах просто убили семантику void* в одну сторону, но не убили полностью. К типизации это не имеет никакого отношения.

Ты, как всегда, показываешь своё незнание плюсов. К типизации это имеет прямое отношение: в плюсах типизаию сделали более строгой и void причесали к идиоме type erasure.

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

Ты как всегда уже в соседней теме слился, а кукарекал так же. Вот ведь незадача.

К типизации это имеет прямое отношение:

Не имеет. Я уже всё объяснил. Хочешь опять в лужу - пасти цитату и рассказывай мне конкретно - что именно и почему я написал неверно.

в плюсах типизаию сделали более строгой и void причесали к идиоме type erasure.

Опять пришел, какую-то херню написал, которую где-то прочитал и что из неё сделает - не знаешь. Эти эксперты с базвордами.

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

в плюсах типизаию сделали более строгой

Чушь. Конкретно в случае с void* в плюсах на практике типизацию убрали.

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

Чушь. Конкретно в случае с void* в плюсах на практике типизацию убрали.

Попробуй осмыслить всё предложение сразу, а не его части по отдельности.

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

А что не так с нулевыми указателями? Все понятно и красиво. Тупо проверяешь — если метод == NULL, вызываешь дефолтный или не вызываешь вообще, если != NULL, вызываешь метод.

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

А что не так с чистыми виртуальными функциям? Всё понятно и красиво. Компилятор тупо проверяет — если метод = 0, ты обязан его реализовать в производном классе.

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

Єто мощная какаха в лицо разработчиков

Почему вы так считаете? Локальная переменная - это кусок памяти на стеке. В каком состоянии был тот участок памяти никому неизвестно. Следовательно если программист не инициализировал переменную, то ее значение может оказаться каким угодно.

andreyu ★★★★★
()

Вопрос на засыпку знатокам:

foo(аргументы)
{
    int var1=выражение_зависящее_от_(аргументов);
    int var2=выражение_зависящее_от(var1);

    ....
}
Может ли в var2 быть полная дичь?

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

только если функции мудак какой-нибудь писал… Скажем, так:

int выражение_зависящее_от(int var1){
    …
    return rand();
}

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

только если

Не. Ведь понятно, что вопрос был о том — это глюк компилятора, или я не в курсе тонкости стандарта, где описано, что auto могут инициализироваться в произвольном порядке, потому надеяться на верный результат простейшего:

int var2 = var1 + 1;
не стОит.

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

или я не в курсе тонкости стандарта, где описано, что auto могут инициализироваться в произвольном порядке

Не, не могут, тут sequence point

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

Может ли в var2 быть полная дичь?

Конечно, если в выражении для var1 насоздавал временныеы объекты и ухватил на них ссылки в var1

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

Ссылки тоже не ок

int& plus(int one) {
    int value = 1;
    return value = one;
}
int var1 = plus(1);
В топорном случае выше компилятор укажет на проблему, а не в топортм навряд ли. Не стоит переоценивать «надёжность» ссылок.

В результате выражения всегда может быть дичь если есть UB.

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

Почему вы так считаете? Локальная переменная - это кусок памяти на стеке.

Неверно. Нигде не определено то, что она находится на каком-то стеке. Она определена в рамках некой «автоматической» памяти, которой даже может и не быть.

В каком состоянии был тот участок памяти никому неизвестно.

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

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

Неверно. Это ни из чего не следует. Из какого угодно состояния так же следует то, что значение в ней будет нужное и валидное. Это типичная ошибка/манипуляция, когда мы подменяем понятия с «неопределенно» на «определенно как нерабочее, либо не имеющие смысла, либо „какое угодно“».

Раз в рамках стандарта не определенно какое-то конкретное поведение стека, то ему ничего не мешает на уровне железяке быть автозануляемым, либо на уровне моей реализации. Так же, мне может быть нужно это самое значение( привет опенссл).

Неизвестное/неопределённое заранее != невалидное. Это такая же подмена понятий.

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

Ну так то UB, всё как мы любим.

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

Не приходит. Это совершенно из другого места с совершенно другими свойствами. У void * нет type safe, а у std::any есть. При этом это не бесплатно, а значит любителям void * оно на смену не приходит.

А тем, кому оно было нужно - уже давно подобное используют. Т.е. оно нужно тем, кто использует левое, либо свои велосипеды - как замена на стандартное средство, либо тем, кто это хотел использовать, но не хотел тянуть левое/своё. Но никак не любители void *

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

Нигде не определено то, что она находится на каком-то стеке.

Да, компилятор может разместить ее в регистре.

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

Так и есть, состояние регистра или куска памяти компилятору неизвестно.

б) из того, что оно неизвестно - не следует то, что оно какое-то не такое.

Какое не такое? Если состояние регистра или участка памяти, выделенного под переменную неизвестно, то неизвестно и значение той переменной.

Неверно. Это ни из чего не следует.

Не следует только из вашей ущербной логики. Но, к счастью, ваша ущербная логика никого не интересует.

Раз в рамках стандарта не определенно какое-то конкретное поведение стека,

А если нет конкретного поведения, то нет и конкретного состояния.

то ему ничего не мешает на уровне железяке быть автозануляемым, либо на уровне моей реализации. Так же, мне может быть нужно это самое значение( привет опенссл).

И это говорит о том, что полагаться на состояние не инициализированной переменной нельзя.

Неизвестное/неопределённое заранее != невалидное. Это такая же подмена понятий.

Точно, и этой подменой понятий вы сейчас пользуетесь ради разведения флейма.

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

Какое не такое?

Обыкновенное. Разберу ещё раз попытку:

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

Как мы уже выяснили, и вы с этим согласились, что «не известно компилятору» - это не то же самое, что «никому». На этом уже можно выкидывать всё следующие выводы, но я продолжу.

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

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

Именно «не имеет смысла - можно делать что угодно» и есть «значение не такое».

По поводу формулировки:

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

Это не имеет смысла, т.к. ни компилятор ни кто-то ещё не должно волновать какое там значение.

Тут есть подменя понятий, откуда-то взялось какое-то состояние регистра/участка памяти, которого нет. Оно известно и определено.

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

Таким образом это полностью валидное состояние для переменной. И любая операция с этой переменной будет так же валидна.

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

В частности, в рамках языка разрешен asm, где может быть всё что угодно, так же как и инициализация этой памяти/регистра.

Не следует только из вашей ущербной логики. Но, к счастью, ваша ущербная логика никого не интересует.

Ты там уже выше показал свои познания и силу своей логики. твои попытки ссылаться на что-то - равны нулю.

Из этого ровным счётом и следует то, что неопределённое значение в значении переменной не делает её состояние каким-то невалидным, либо неверным.

А если нет конкретного поведения, то нет и конкретного состояния.

Опять какие-то попытки ретранслировать ахинею. Что должна значит эту ахинеия и к чему она тут написано - неясно.

И это говорит о том, что полагаться на состояние не инициализированной переменной нельзя.

Не на состояние, а на значение. Это опять следствие слабости и неспособности в логику, а именно отличать значение и саму переменную. Состояние будет и там одинаковое - валидное.

Точно, и этой подменой понятий вы сейчас пользуетесь ради разведения флейма.

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

А итог один.

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

А итог один.

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

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

И почему же это чушь и почему это бред, вы конечно же не скажете.

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

Удачи.

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

Я про разницу между дебаг и релиз версиями. Тестировали дебаг, а какашка прилетела с релиза

Какашка прилетела из кривого кода. С таким же успехом можно обвинять конфигурацию компьютера клиента, приговаривая «ну не знаю, у меня все работает».

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