LINUX.ORG.RU

Почему void* не нужен?

 , ,


0

2

Смеркалось.

Пятница.

Можете считать что я накидываю, но душа моя лешит к си, а все плюсовики говорят, что сабж – это плохо. А я не понимаю: ну не размахивай рукой, гогда у тебя в руке нож, взял, отрезал, положил нож на место.

Что можно сделать плохого? Явно привести ни к тому типу? Ну так и в плюсах можно. Разименовать нулевой? См. предыдущий пункт.

Что еще?

★★★★★

Им страшно, что они сами не нужны.

Bfgeshka ★★★★★
()

Что еще?

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

u5er
()

Явно привести ни к тому типу? Ну так и в плюсах можно.

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

FishHook
()

Хотел ворваться в тред и атаковать ненавистника Void Linux, а тут просто говнокодер с сырыми указателями.

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

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

Это я тоже спрошу, но не у всех, кто так заявляет, я могу спросить, а у вас – могу.

Например, говорят (говорят!) что в си нет стандартных, например, списков, потому что их можно реализовать в общем случае только с помощью макросов или воид*, и да – согласен, но почему это плохо у меня ума у самого не хватает.

Наверное, в сишном коммитете не глупее меня люди сидят и не хуже знают си, ну так почему тогда? :)

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

можно, но не нужно

Можно ли не использовать плюсы? очевидно – можно, этим аргументом можно многое покрыть

Если можно писать код в стиле, который позволяет избегать подобных ошибок, то почему этого не делать?

Если так можно, чтож воид* не выкинули из плюсов? Очевидно, можно, да не всегда

Странная логика, вернее её отсутсвие.

Воу-воу – полегче :)

pihter ★★★★★
() автор топика

Потому что он может стать чем угодно. Типобезопасноость отсутствует. Вот пример:

void foo(void *bar)
{…}

template<typename T>
void foo(const T &bar)
{…}

Во втором случае можно ограничить перечень применимых типов (допустим, через static_assert(std::is_same_v<T, UNWANTED_T>), хотя и не только так). В случае же с void* это если и возможно, то исключительно костыльно

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

Хотел ворваться в тред и атаковать ненавистника Void Linux

Не тут-то было!

говнокодер с сырыми указателями.

нуууууу… допустим я реализовал некую структуру данных, скажем, двусвязный список на си с применением сабжа для общего случая чтоб. И при использовании всегда явно привожу тип. Это считается за сырые указатели?

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

Если так можно, чтож воид* не выкинули из плюсов?

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

Можно ли не использовать плюсы? очевидно – можно,

Тебя ж не заставляют, не нравится - не ешь

FishHook
()

Явно привести ни к тому типу?

Помогите разобраться, как:

    auto a = new int[4]{1,2,3,4};
    void *b =a;
    for(int i=0;i<4;i++) std::cout << *(static_cast<int*>(b+i)) << ' ';

выхлоп:

1 33554432 131072 512
Ygor ★★★★★
()

Почему void* не нужен?

Он не ненужен, он обязателен.

а все плюсовики говорят, что сабж – это плохо.

Они просто не в курсе что без этого их язык работать не будет.

Что можно сделать плохого?

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

А так, плохо это пихать их везде без какого либо контекста. А так, всему своё место применения.

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от XMs

Потому что он может стать чем угодно

Ну ты явный каст делай при использоваинии и все – уже типизированный.

В случае с шаблоном, тебе теже тип надо будет явно указывать

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

Ну ты явный каст делай при использоваинии и все – уже типизированный.

А что если там не тот тип окажется? Компилятор уже за тебя это не проверит.

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

Переставай тупить

такой тиктокерский троллинг тупостью

В такой манере иди общайся с кем-нибудь другим

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

Потому что он может стать чем угодно.

Не может, он станет тем к чему ты его приведёшь и только к этим. :)

хотя и не только так). В случае же с void* это если и возможно, то исключительно костыльно

А тут он и не нужен (хотя можно через генерики), он нужен когда надо данные в pthread callback передать например, там никакие шаблоны не помогут.

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 4)
Ответ на: комментарий от pihter

У меня был односвязный. Вообще, я делаю структуру типа такой

struct item {
    struct item* next;
};

и вкладываю её в начало «рабочей» структуры. Тогда вроде как можно обойтись без void*. Ещё есть вариант типа такого

struct item {
    struct item* next;
    void* payload;
};

Но в таком случае при переборе придётся проходить по двум указателям.

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

Помогите разобраться, как

$ cat type.cpp 
#include <stdio.h>
#include <stdint.h>

int main() {
  int32_t a = 300;
  printf( "aaaa: %d\n", (int8_t)a );

  return 0;
}

$g++ type.cpp 
$ ./a.out 
aaaa: 44

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

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

Ну ты явный каст делай при использоваинии

Уже ответили, но продублирую — нет никакой защиты от ошибки.


В случае с шаблоном, тебе теже тип надо будет явно указывать

Нет:

class Unwanted;

template<typename T>
void foo(const T &)
{
    static_assert(std::is_same_v<T, Unwanted>);
}

#ifdef OPT_ENABLED
Unwanted bar()
{…}
#else // OPT_ENABLED
OtherType bar()
{…}
#endif // OPT_ENABLED

void somefunc()
{
    foo(bar());
}

На шаблонах я могу соорудить простую защиту. А как она будет выглядеть с void*?

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

прямой путь к сюрпризам в рантайме

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

Критикуйте )

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

А что если там не тот тип окажется? Компилятор уже за тебя это не проверит.

Ну а что если в то место, куда ты тыкаешь ножом не булка хлеба окажется? Ну так ты же смотри куда тыкаешь – сразу приводи тип.

Я понимаю про что ты, но мне кажется это хоть и справедливый, но довольно притянутый аргумент: мы же о низкоуровневом программировании говорим, а что если в TCP пакете не те данные окажутся, которые ты ждешь при парсе? Как компилятор от этого защитит?

Так же и тут.

// не сочтите что я троллю, я пытаюсь выяснить чего я не понимаю, ибо у меня картина мира не складывается: если бы все было как я понимаю – стоило бы запилить в стандартную поставку структуры данных, с опорой на сабж, а этого не сдалали

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

и вкладываю её в начало «рабочей» структуры

Ну это не типоуниверсальный список: это – каждый раз имплементить одно и то же

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

На шаблонах я могу соорудить простую защиту. А как она будет выглядеть с void*?

На шаблонах – это немного другой разговор. Их корректнее, имхо, сравнивать с макросами типов в си.

Мой аргумент же был: можно явно кастануть не туда воид* в си, ну так ведь можно явно кастануть не туда что угодно в что угодно в плюсах.

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

Ну функции для работы со списком просто выносятся в отдельную «либу» и всё. При переборе элементов указатель приводится к типу struct item*, а при обращении к данным - к типу рабочей структуры. Других способов сделать это на обычной сишке я не знаю.

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

Пятница

Не надо так прорицать.

Ты – Шрайк или где? :)

(кстати, почему руки – две? думал я не замечу? :) )

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

Не, ну если ты гарантируешь сам себе, что никогда не ошибёшься, то пожалуйста. Флаг в руки. Но я бы не был на твоём месте так самоуверен и на сишную старуху бывает сегфолт.

З.Ы. Только публичный код так не пиши.

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

А ты сравни скорость работы qsort и std::sort и поймешь, почему сишка с void* на каждый чих – убогий язычок

Это некорректное сравнение: тут выйгрыш от оптимизатора, потому что можно функцию-компаратор инлайнить – синтетический пример

можно легко придумать пример, на котором си выйграет ( наверное, так должно быть :) )

pihter ★★★★★
() автор топика

Что можно сделать плохого? Явно привести ни к тому типу?

именно

Ну так и в плюсах можно.

но не нужно

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

Это не притянутый аргумент. Я видел всякое. Даже если ты уверен, что всегда будешь правильно приводить тип, это не гарантия.

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

cocucka_B_TECTE
()

Польза:

чтобы можно было делать такие штуки:

void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));

Для которых в плюсах есть шаблоны.

Вред (там же, где польза, рядышком):

Можно указатель на тип T1 скастовать в указатель на тип T2, который никак не соотносится с типом T1, его размером, членами, и поиметь все сишные проблемы: выход за пределы валидной памяти, целочисленные преполнения и проч.

Ваш капитан очевидность.

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

Не, ну если ты гарантируешь сам себе, что никогда не ошибёшься, то пожалуйста

Ну а ты гарантируешь сам себе что не ошибешься, беря в руку нож?

и на сишную старуху бывает сегфолт.

:)

Только публичный код так не пиши.

Дв в публичном коде такого – ну ю ноу про количество кода написанного на си

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

Даже если ты уверен, что всегда будешь правильно приводить тип, это не гарантия

спору нет: ночь программирования вообще темна и полна ужосов

Например, при копипасте куска кода

У меня такое – постоянно :)

pihter ★★★★★
() автор топика

Ну так и в плюсах можно.

Плюсы исторически совместимы с сями, и это никуда не денется, потому что преемственность поколений и совместимость - один из столпов дизайна плюсов. Но во всех книгах и в благословенных босами «C++ core guidelines» рекомендуется использовать современные фичи вместо сишного наследия, потому что см. выше капитана очевидность.

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

У тебя что, кнопка «и» отвалилась?

выЙграет?

У меня есть бага в голове: я пишу неграмотно, а потом, когда читаю – вижу позор. Видимо, это связано с тем, что за писание и читание отвечает немного разный мозг. Помогает перечитываение перед публикацией, но, в пылу сражения, иногда забиваю – понять и призреть – вот что вам остается :)

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

Ну а ты гарантируешь сам себе что не ошибешься, беря в руку нож?

А ты гарантируешь, что не подцепишь какую-нибудь хрень, если будешь всё жрать немытыми руками? Что за детский сад?

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

А что в нем синтетического? Алгоритмы и структуры данных – это основа любой программы, а в сишки они все на void* будут.

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

Ваш капитан очевидность

Ну то что можно явно не в ту дырку кастануть – это уже говорили. В плюсах тоже можно.

Разумный контраргумент – плюсы предоставляют средсва, где так нельзя, однако это же тоже не бесплатно: плюсы стократно сложнее со всеми вытекающими

pihter ★★★★★
() автор топика
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.