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)

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

Хотя, не уверент, подходит ли это в случае данного параграфа.

http://port70.net/~nsz/c/c11/n1570.html#4p1

In this International Standard, "shall" is to be interpreted as a requirement on an implementation or on a program

В параграфе про strict aliasing «shall» относится к программе, а не к implementation.

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

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

Это почему?

6.7.2.1 Structure and union specifiers

Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning

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

Понятия не имею, у меня код на C. Так что давай, разъясни мне, что именно в моём коде не так? А то, может, никакого strict aliasing и не существует, и это всё заговор жидомассонов.

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

Понятия не имею, у меня код на C.

Тем не менее, при компиляции g++, вывод на консолечку такой же «неожиданный».

Так что давай, разъясни мне, что именно в моём коде не так?

Думай сам, тренируйся.

А то, может, никакого strict aliasing и не существует, и это всё заговор жидомассонов.

Ну да, что тебе остаётся, кроме как ёрничать.

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

Думай сам, тренируйся.

Ну вот. Ладно, буду считать заговором жидомасонов.

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

Да, точно, такой код – UB. Вот статья по теме: https://blog.regehr.org/archives/1307

Так ведь ub по ссылке в передаче в функцию, принимающую указатели на разные типы, одного и того же адреса.

UB, возникающее из-за нарушения strict aliasing здесь именно в этом месте

f(&s, (s2 *)&s);
const struct h* ph = (struct h*)&d;

Здесь же UB нет и кастовать типы можно. Нельзя одновременно использовать один и тот же объект, как разные типы.

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

UB, возникающее из-за нарушения strict aliasing здесь именно в этом месте

Ещё одному мерещится нарушение strict aliasing там, где его нет 🤦‍♂️

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

Функция f принимает на вход два указателя разных типов.
При включённом strict aliasing эти два указателя не должны указывать на один и тот же объект.
При вызове функции ей в обоих параметрах передаются указатели на один и тот же объект.
С чего вдруг это не нарушение strict aliasing?

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

Strict aliasing rule указано тут В чём смысл делать так_s постфиксить_t ? (комментарий)

Там сказано про то, через какие lvalue разрешён доступ к объекту данного типа. А не про то, куда какие указатели указывать могут. В f(&s, (s2 *)&s) нарушения правил с того параграфа нет.

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

Strict aliasing rule указано тут

Strict aliasing - это не правило стандарта, а правило некоторых компиляторов. Оно выводится ими путём особой интерпретации указанного тобой параграфа.

В случае gcc strict aliasing - это запрет «одновременного» использования указателей разных типов на одни и те же данные.

Или по-твоему gcc с -no-strict-aliasing нарушает стандарт, а без этого флага нет?

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

Strict aliasing - это не правило стандарта, а правило некоторых компиляторов.

Под strict aliasing rule традиционно понимают именно тот параграф про доступ через lvalue (или аналогичные в других версиях стандарта C и C++).

Или по-твоему gcc с -no-strict-aliasing нарушает стандарт, а без этого флага нет?

В каком смысле «нарушает стандарт»?

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

Под strict aliasing rule традиционно понимают именно тот параграф про доступ через lvalue (или аналогичные в других версиях стандарта C и C++).

Ну тут я не знаю. В традициях не силён.
Могу предположить, что это лишь указание на источник, откуда это правило взялось. Но gcc использует strict aliasing rule не так, как описано в данном параграфе.

В каком смысле «нарушает стандарт»?

В случае, когда нет флага -fno-strict-aliasing gcc не допускает возможности аргументам f() указывать в одно и то же место.
В случае, когда есть флаг -fno-strict-aliasing gcc такую возможность допускает.
Вопрос: в каком случае поведение gcc противоречит данному параграфу, а в каком нет?

В моём понимании ни в каком не противоречит, т.к. strict aliasing в стандарте не описан, а это всё заморочки gcc и ко.
Если же strict aliasing rule описан в стандарте, то его отключение должно это стандарт нарушать. Но не нарушает.

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

Хорошо, расскажи, что именно тебе непонятно в параграфе, который я привёл выше

Ты про «Раздел 6.5, пункт 7»? Это называется «тред не читай - отвечай». Не ясно, что такое «доступ» и к какому «значению». В частности, является ли чтение поля доступом к объекту или же только доступом к одному полю. Доступ в определениях объявлен как чтение или запись во время выполнения, однако же, логика исходного кода и сгенерированный маш код - это две совершенно разные вещи.

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

Ну тут я не знаю. В традициях не силён.
Могу предположить, что это лишь указание на источник, откуда это правило взялось. Но gcc использует strict aliasing rule не так, как описано в данном параграфе.

Ладно, хер с ним, кто что как называет.
Можешь по стандарту, а не кивками на GCC, показать, что нарушает тот код? (Если нарушает)

В случае, когда нет флага -fno-strict-aliasing gcc не допускает возможности аргументам f() указывать в одно и то же место.
В случае, когда есть флаг -fno-strict-aliasing gcc такую возможность допускает.
Вопрос: в каком случае поведение gcc противоречит данному параграфу, а в каком нет?

Думаю, ни в каком не противоречит. Implementation может доопределять поведение, которое не определено по стандарту, но только явно. Что gcc и делает.
-fno-strict-aliasing, я думаю, доопределяет поведение для того параграфа. Но не только для него!
В коде, как мы выяснили выше, нет нарушения этого параграфа. Т.к. доступа к объекту типа s1 через lvalue типа s2 нет.

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

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

Не знаю, с кем у вас тут такой разговор был

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

Давай лучше ты покажешь в том коде конкретное выражение и конкретное подвыражение в нём, при вычислении которого происходит нарушение strict aliasing rule

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

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

В частности, является ли чтение поля доступом к объекту или же только доступом к одному полю.

Доступом только к полю, но не ко всему объекту-структуре, содержащему это поле.

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

int main()
{
struct S s2;
s2 = s; // есть доступ через `s` lvalue
s2.i = s.i; // нет доступа через `s`, есть только через `s.i` >lvalue
}

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

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

В частности, является ли чтение поля доступом к объекту или же только доступом к одному полю.

Доступом только к полю, но не ко всему объекту-структуре, содержащему это поле.

Это ты сам додумал.

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

UB, возникающее из-за нарушения strict aliasing здесь именно в этом месте
f(&s, (s2 *)&s);

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

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

Если считать доступ к полю доступом ко всему объекту, то получится, что любой доступ к полю это UB.

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

Если считать доступ к полю доступом ко всему объекту, то получится, что любой доступ к полю это UB

В 6.5.2.3 (про структуры) примерно это и написано. Правда, речь была про атомарные структуры, а неатомарный доступ стал исключением.

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

В 6.5.3 (про структуры), примерно это и написано.

Там сказано, что к объекту можно получать доступ через lvalue типа структуры, содержащего этот объект, а не наоборот.

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

В том, что доступ к полю это доступ ко всему объекту типа структуры.

struct S { int i; float f; } s;
int* pi = &s.i;
*pi = 0; // доступ только к полю `s.i`, но не ко всему `s`.
s.i = 0; // то же самое
anonymous
()
Ответ на: комментарий от byko3y

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

Логика сгенерированного кода вообще не релевантна.

5.1.2.3 Program execution
The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant.

Я ссылался на поведение GCC с volatile чтобы сделать «доступ» более видимым, т.к. доступ к volatile-объектам должен происходить в соответствие с правилами абстрактной машины C. (не факт, конечно, что в GCC нет бага ;-))

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

В том, что доступ к полю это доступ ко всему объекту типа структуры

Логический доступ к объекту в исходном коде. Фактически программа может совсем ничего не исполнять, но это не отменяет наличие некой логики доступа в исходном коде.

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

The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant

Только они забыли стандартизировать абстрактную машину так-то.

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

Я тебе уже про логический-**ический написал. Доступ к полю это не доступ ко всему содержащему его объекту-структуре. Хоть логически, хоть как.

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

Доступ к полю это не доступ ко всему содержащему его объекту-структуре

Почему? Потому что GCC/LLVM так генерирует код с отключенной оптимизацией? А вот у меня абстрактный исполнитель полностью читает и пишет струтуры, потому что в нем отключена оптимизация.

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

Только они забыли стандартизировать абстрактную машину так-то.

🤦‍♂️ Стандарт C это и есть описание поведения абстрактной машины.

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

Стандарт C это и есть описание поведения абстрактной машины

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

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

Доступ к полю это не доступ ко всему содержащему его объекту-структуре

Почему?

struct S { int i; float f; } s;
int* pi = &s.i;
*pi = 0;

Т.е. по-твоему в последней строке тут доступ ко всему s?

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

6.5.3.2 Address and indirection operators
Semantics
4 The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.

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

struct S { int i; float f; } s;
int* pi = &s.i;
*pi = 0;
Т.е. по-твоему в последней строке тут доступ ко всему s?

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

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

The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined

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

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

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

С чего вдруг?

Исправил уже в исходном сообщении. Ты обращаешься к одному и тому же объекту по разным указателям, «struct S» и «int *», которые не являются совместимыми типами.

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

Здесь нет описания работы

define «работа»

Где поведение, где конкретные действия машины?

define «конкретное действие» И почему у абстрактной машины оно должно быть? Не задумывался, почему она называется абстрактной?

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

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

Это исключительно твои фантазии.

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

Здесь нет описания работы

define «работа»

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

define «конкретное действие» И почему у абстрактной машины оно должно быть? Не задумывался, почему она называется абстрактной?

Потому что они в определении «accessed» описывают выполнение. Ну и где это выполнение? А нету его.

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

«Записать значение из адреса памяти в регистр», «записать значение из регистра в ячейку памяти».

Если ты думаешь, что «абстрактная машина», обязана иметь какие-то регистры — то это только твои хотелки/проблемы.

Потому что они в определении «accessed» описывают выполнение. Ну и где это выполнение?

5.1.2.3 Program execution

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

Если ты думаешь, что «абстрактная машина», обязана иметь какие-то регистры — то это только твои хотелки/проблемы

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

Потому что они в определении «accessed» описывают выполнение. Ну и где это выполнение?

5.1.2.3 Program execution

«In the abstract machine, all expressions are evaluated as specified by the semantics»

Стандарт снова радует нас «исчерпывающими» деталями. «Хорошо жить, когда всё хорошо» - говорит нам стандарт. Так как, все-таки, мне исполнить разыменовывание указателя? Стандарт мне собирается об этом говорить?

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

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

Вот именно. Я не спец по теории вычислимости, но IUC лямбда-исчисление эквивалентно машине Тьюринга, а регистров там нет :/

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

Проблема стандарта C не в отсутствии конкретной машины, а явного указания, когда происходит access. Приходится местами догадываться, используя ответы комитета под defect report-ами, аналогию со стандартом C++, опираться на имплементации стандарта или common sense. Это, конечно, не очень хорошо.

«In the abstract machine, all expressions are evaluated as specified by the semantics»

Так как, все-таки, мне исполнить разыменовывание указателя?

Я тебе скидывал. Подраздел даже озаглавлен как Semantics. Что тебе не понравилось?

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

Вот именно. Я не спец по теории вычислимости, но IUC лямбда-исчисление эквивалентно машине Тьюринга, а регистров там нет

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

Я тебе скидывал. Подраздел даже озаглавлен как Semantics. Что тебе не понравилось?

Тем, что там нет исполнения. «Исполнять в соответствии с семантикой» по сути значит «исполнять как угодно», поскольку для семантики не определены правила трансляции.

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

конкретный исполнитель может не иметь никаких регистров, и, тем не менее, быть совместимым с абстрактной машиной.

А может и иметь регистры и быть совместимым с абстрактной машиной, у которой нет регистров.

Тем, что там нет исполнения. «Исполнять в соответствии с семантикой» по сути значит «исполнять как угодно», поскольку для семантики не определены правила трансляции.

Правила трансляции во что?

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

Тем, что там нет исполнения. «Исполнять в соответствии с семантикой» по сути значит «исполнять как угодно», поскольку для семантики не определены правила трансляции.

Правила трансляции во что?

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

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

Правила трансляции во что?

В программу.

На каком языке?

Интерпретация является разновидностью трансляции.

Вот и отлично! Бери текст программы на C, парси его в соответствие с синтаксическими правилами и интерпретируй получившиеся выражения/подвыражения так, как указано в подразделах Semantics для соответствующих выражений.

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

UB возникает при разыменовывании.

Нет. Тут ub возникает при передаче недопустимых параметров в функцию. Как верно сказал анон выше неправильного разыменования здесь нет.

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