LINUX.ORG.RU

В чём смысл делать так_s постфиксить_t ?

 , , ,


0

2
typedef struct name_s
{
   ....
}name_t

Сабж по постфиксам.

Я делаю всегда так

typedef struct name_t 
{
   ....
}name_t

И стараюсь не не дать так

typedef struct
{
   ....
}name_t

Ибо pahole и иже с ним не могут в анонимные. Но в чём практический смысл задавать и _s и _t одновременно просто постфиксы вносят ясность и смягчают уровень былого отвращения к typedef нивелируя тот упрёк что с typedef теряется ясность. Но вернёмся к постфиксам. Ну или префиксам для типов аля t_uint8 t_int64 вместо uint8_t int64_t может тут есть извращенцы я не знаю :D

ТайпдеТупедефаете вы как?

★★★★★

Последнее исправление: LINUX-ORG-RU (всего исправлений: 3)

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

Правда, ни один компилятор не выдаст здесь UB фактически

Выше было. Таки выдал

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

По сравнению с C++ стандарты Си просто нервно курят в сторонке.

По количеству UB стандарты C на 100 шагов впереди стандартов C++. Например, следующий код имеет неопределённое поведение в C, и определённое (даже не unspecified!) в C++.

struct S { int i; } arr[2];

&(arr[0].i) < &(arr[1].i); // UB в C, true в C++ !!!
anonymous
()
Ответ на: комментарий от anonymous

Нут так цитируй правила, а мы поржём над твоими потугами

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

Это распространенная практика, потому что большая часть программистов на C, в том числе ярых фанатиков этого языка уровня Iron_bug, легко валятся на собеседовании вопросом про strict aliasing. И я вот даже не знаю, их ли это вина, потому что в учебниках это мало упоминают, а стандарт написан как будто бы жопой

Я сам не знал про strict aliasing. Оно настолько вяжет руки, что проще выключить его один раз и больше не вспоминать про него. В MSVC его вообще никогда не было. Собсна, тот же C11 ни один компилятор в полном объеме не поддерживает. Потому, в данной ситуации я считаю уместным заявить, что стандарт ошибочен, компиляторы работают правильно, а проблема strict aliasing надумана.

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от anonymous
union u {
  int i; float f;
};
{
  u x;
  x.i = 0;  //UB in c++
  x.f;      //UB in c++
}
{
  char s[9000];
  *reinterpret_cast<int*>(s);  //UB in c++
  new(s) int(0);
  *reinterpret_cast<int*>(s);  //UB in c++
}

По количеству UB стандарты C на 100 шагов впереди стандартов C++

Да неужели...

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

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

Вся суть C, в общем-то. Алсо какой именно компилятор? Потому что они по-разному делают.

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

проще выключить его один раз и больше не вспоминать про него

И получить настоящее УГ от кодогенератора

проблема strict aliasing надумана

Нет такой проблемы. Есть попытка генерировать оптимальный код

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

Ладно, немного UB, но это не сильно волнует кого-либо, т.к. наследование иначе сделать крайне проблематично.

В стандарте только сказано, что такое использование данных в структурах возможно, если обе структуры находятся в одном union, при наличии общих одинаковых полей в начале обеих структур (т.н. common initial sequence), - в этом случае официально можно читать/менять общие поля в любой из структур этого union.

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

Ну, первый пример UB я бы назвал лукавым. Если совсем буквально читать стандарт, то можно сказать, что это UB. Но это очевидный ляп.

Остальные 3 примера — не UB.

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

чем вам строки не нравятся ? Это по сути элемент низкоуровневости, т.е. непосредственная особенность языка

Если ты делаешь «strncpy_s(dest, dest_size, src, src_len)» - то да, никаких проблем. Иначе ты получаешь чтения за пределы буфера, и запись за пределы буфера.

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

если обе структуры находятся в одном union

Про это я знаю, даже в крестах валидный случай

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

Легко валятся всякие самоуверенные недоучки, думающие, что тип выражения E1 в выражениях вида E1.E2 имеет какое-то значение для strict aliasing rule.

 ▲ ~/devel cat strict.c 
#include <stdio.h>
 
typedef struct { int i1; } s1;
typedef struct { int i2; } s2;
 
void f(s1 *s1p, s2 *s2p) {
  s1p->i1 = 2;
  s2p->i2 = 3;
  printf("%i\n", s1p->i1);
}
 
int main() {
  s1 s = {.i1 = 1};
  f(&s, (s2 *)&s);
}

 ▲ ~/devel gcc strict.c && ./a.out    
3

 ▲ ~/devel gcc strict.c -O2 && ./a.out
2

Вау! Как же так? Анонимус же сказал, что тип структуры значения не имеет!

А вообще, хватит уже! ВНОСИТЕ ЦАРЯ!

hateyoufeel ★★★★★
()
Ответ на: комментарий от anonymous
union u {
  int i; float f;
};
{
  u x;
  x.i = 0;  //объект не создан - UB
  x.f;      //обращение к неактивному полю - UB
}
{
  char s[9000];
  *reinterpret_cast<int*>(s);  //объект не создан - UB
  new(s) int(0);
  *reinterpret_cast<int*>(s);  //объект создан, но см. почему std::launder() появился - UB
}
DllMain
()
Ответ на: комментарий от byko3y

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

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

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

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

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

Ах да, и gcc, и clang со мной согласны:

#include <new>

struct A {
	virtual int f();
};

struct B :A {
	int f() override { new(this) A(); return 2; }
};

int A::f() { new(this) B(); return 1; }

int main()
{
	A a;
	int i = a.f();
	return i + a.f();  //2 with gcc-8 -O2
}
#include <new>

struct A {
	virtual int f();
};

struct B :A {
	int f() override { new(this) A(); return 2; }
};

int A::f() { new(this) B(); return 1; }

int main()
{
	char s[900];
	new(s) A();
	int i = reinterpret_cast<A&>(s).f();
	return i + reinterpret_cast<A&>(s).f();  //3
}

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

x.i = 0; //объект не создан - UB

[class.union]/5 (нумерация по ISO/IEC 14882:2017).

x.f; //обращение к неактивному полю - UB

Что значит «обращение»?
Просто именование? Просто именовать неактивный член union это не UB.
Чтение? Тут нет чтения.

*reinterpret_cast<int*>(s); //объект не создан - UB *reinterpret_cast<int*>(s); //объект создан, но см. почему std::launder() появился - UB

В огороде бузина — в Киеве дядька.

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

Не соглашусь вы можете их преобразовывать если требуется, но если ввести тупо ASCII строки, как основной тип, жизнь легче не станет, т.к. всё тоже самое перетечёт в тему что нам нужны utf-8, utf-16 и другие кодировки, сейчас уже поздно что-том менять и эта простота строк обеспечивает высокую переносимость, т.к. вы свободны интерпретировать данные как пожелаете.

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

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

Вся суть C, в общем-то. Алсо какой именно компилятор? Потому что они по-разному делают

Все работают правильно. Все компиляторы поддерживают свободный алиасинг. Некоторые компиляторы поддерживают включение режима strict aliasing, вроде Clang, GCC, ICC.

Я бы хотел напомнить, с чего начался сыр-бор:

Это вообще мелочь по сравнению с бедной стдлиб и неоднозначностями в стандартах

Так вот, что я хочу ответить: стандарты писали и пишут мудаки, а работающий код пишут совершенно другие люди. Я еще не видел ни одного хорошего стандарта. По этой причине плохой стандарт является нормой и не мешает писать код. Однако, в том же C++ сам язык не дает возможности написать хорошую реализацию компилятора, нгезависимо от стандартов.

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

Ах да, и gcc, и clang со мной согласны:

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

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

ISO/IEC 14882:2017

Ну да, правильно. 14, 11 и 03 смотри

Что значит «обращение»?

Хоспаде, ну замени x.f на auto y = x.f;, делов-то

В огороде бузина — в Киеве дядька

Да, только цитатками сыпать и остаётся

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

Все работают правильно. Все компиляторы поддерживают свободный алиасинг.

Я выше для анона код запостил вот тут: В чём смысл делать так_s постфиксить_t ? (комментарий)

Clang выдаёт 3 в обоих случаях. Так какой из компиляторов правильно работает-то?

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

FTFY

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

проще выключить его один раз и больше не вспоминать про него

И получить настоящее УГ от кодогенератора

То есть, линукс - это, по-твоему. УГ?

проблема strict aliasing надумана

Нет такой проблемы. Есть попытка генерировать оптимальный код

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

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

Ну так раскури пример получше. Может и до тебя дойдёт, что c и c++ определяются не только стандартом.

пообещай мне, что ты не будешь писать такой говнокод нигде

Да это вообще не мой пример(первая часть)

Кстати, забыл ещё на тему валидности char* -> type*: std::aligned_storage посмотри и расскажи нам как его использовать, если char* -> type* UB

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

Ну так раскури пример получше. Может и до тебя дойдёт, что c и c++ определяются не только стандартом.

Так, пожжи! А кем они определяются? Царём что ли?

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

То есть, линукс - это, по-твоему. УГ?

Ну, вообще, да. А что такого-то?

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

То есть, линукс - это, по-твоему. УГ?

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

ломает логику работы

Логику работы корректного кода он не ломает

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

Ну, не хочешь угадывать, так и ладно, фапай на царя дальше. Я так понял, аргументов по поводу невалидности char* -> type* ты привести не сможешь?

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

Вау! Как же так? Анонимус же сказал, что тип структуры значения не имеет!

gcc -O2 -fno-strict-aliasing main.c && ./a.out
3

А теперь самый угар:

gcc -O2 main.c && gdb -batch -ex 'file ./a.out' -ex 'disassemble main'
Dump of assembler code for function main:
   0x0000000000400460 <+0>:	sub    $0x8,%rsp
   0x0000000000400464 <+4>:	mov    $0x2,%esi
   0x0000000000400469 <+9>:	mov    $0x4008d2,%edi
   0x000000000040046e <+14>:	xor    %eax,%eax
   0x0000000000400470 <+16>:	callq  0x400430 <printf@plt>
   0x0000000000400475 <+21>:	xor    %eax,%eax
   0x0000000000400477 <+23>:	add    $0x8,%rsp
   0x000000000040047b <+27>:	retq   
End of assembler dump.

gcc -O2 -fno-strict-aliasing main.c && gdb -batch -ex 'file ./a.out' -ex 'disassemble main'
Dump of assembler code for function main:
   0x0000000000400460 <+0>:	sub    $0x8,%rsp
   0x0000000000400464 <+4>:	mov    $0x3,%esi
   0x0000000000400469 <+9>:	mov    $0x4008d2,%edi
   0x000000000040046e <+14>:	xor    %eax,%eax
   0x0000000000400470 <+16>:	callq  0x400430 <printf@plt>
   0x0000000000400475 <+21>:	xor    %eax,%eax
   0x0000000000400477 <+23>:	add    $0x8,%rsp
   0x000000000040047b <+27>:	retq   
End of assembler dump.

Вот такая вот оптимизация, наслаждайтесь.

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

Ну да, правильно.

Правильно, что нет UB?

14, 11 и 03 смотри

Если ты веруешь (а ты, похоже, веруешь), что доступ неактивному члену union это не UB в C, то wording в C++ 14, 11, и 03 можно натянуть так, что оно будет не UB и в C++14, 11 и 03.

Хоспаде, ну замени x.f на auto y = x.f;

Это называется «подмена тезиса». ;-)
Исходный тезис в том, что x.f;, а не auto y = x.f; это UB.
Я правильно понял, что ты отказываешься от своего начального заявления?

делов-то

Для тебя подменять тезисы это обычное дело?

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

Я так понял, аргументов по поводу невалидности char* -> type* ты привести не сможешь?

Какие тебе аргументы нужны-то? Это undefined behaviour. Точка. Если ты пишешь такой код, то ты мудак, потому что, даже если твой код работает сейчас, он может сломаться в будущем.

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

Сознание ты обрёл, а вот с иронией у тебя явно туго.

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

-fno-strict-aliasing

Это не по стандарту, чувак. Твой аргумент не засчитан за читерство. Алсо, как часто ты видишь сборку проектов с этим флагом? Потому что большинство программистов на C про него даже не знают.

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

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

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

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

Это undefined behaviour. Точка

Фанбою царя с лора на слово как-то не верится

вот с иронием у тебя явно туго

Сори, если задел. Кстати, с иронией у меня явно лучше, чем у тебя с чуством юмора

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

Если ты веруешь (а ты, похоже, веруешь), что доступ неактивному члену union это не UB в C

Мы уже о c++

Это называется «подмена тезиса»

Просто ты проглотил шланг, никакой подмены. Но да ладно

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

Так, пожжи! А кем они определяются? Царём что ли?

Языки определяются реализацией, а стандарты пишутся по реализации, зачастую эту реализацию перевирая. Что и случилось со strict aliasing.

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

Фанбою царя с лора на слово как-то не верится

Прочитай вот это. Сравни со своим кодом.

Strict aliasing is an assumption, made by the C (or C++) compiler, that dereferencing pointers to objects of different types will never refer to the same memory location (i.e. alias eachother.)

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

а стандарты пишутся по реализации, зачастую эту реализацию перевирая.

Хахахахахаха! Ты, видимо, про эпопею с export в C++ забыл.

Языки определяются реализацией

Так какой именно реализацией определяются C и C++?

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

Логику работы корректного кода он не ломает

Код собирается и правильно работает на всех архитектурах процессоров. С чего бы это он был некорректен? Пока в стандарте нет способов обозначить безопасное преобразование между указателями на структуры разного размера - я не хочу ничего слышать про strict aliasing. Блин, да целый object pascal сделан на loose aliasing. Намного более адекватная фича - это модификатор restrict.

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

Код собирается и правильно работает на всех архитектурах процессоров

Это ты про какой код? Про ведро? Так оно со strict aliasing работать, скорее всего, не будет

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

Это не по стандарту, чувак. Твой аргумент не засчитан за читерство. Алсо, как часто ты видишь сборку проектов с этим флагом?

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

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

Мы уже о c++

Я сказал, что в C больше UB, чем в C++ (разумеется, имеется в виду код, который будет well-formed и в C, и в C++).
Ты скинул какой-то пример, с якобы UB в C++ (которого там на самом деле нет). Если заменить там касты на C-style касты, чтобы этот код был well-formed C-кодом, то там также не будет UB.
Я подумал это типа код-контраргумент, в котором будет больше UB при интерпретировании его как C++-кода, чем при интерпретировании его как C-кода.
Но, похоже, ты просто не умеешь следить за темой.

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