Информация об изменениях

Сообщение Re[3]: При портировании кода на линукс столкнулся с проблемо от 09.08.2019 12:08

Изменено 09.08.2019 12:10 watchmaker

Re[3]: При портировании кода на линукс столкнулся с проблемой
Здравствуйте, gwg-605, Вы писали:

G6>Здравствуйте, watchmaker, Вы писали:


W>>Обе проблемы решаются исправлением кода в соответствии со стандартом языка:
printf( "%u--%s--%u", 0x55, c0.m_Pointer, 0xAA);

G6>Можно ссылочку в стандарте на эту часть?

Важны эти пункты:

[expr.call]
When there is no parameter for a given argument, the argument is passed in such a way that the receiving
function can obtain the value of the argument by invoking va_arg
...
Passing a potentially-evaluated argument of class type (Clause 12) having a non-trivial copy constructor, a non-trivial move constructor, or a non-trivial destructor, with no corresponding parameter, is conditionally-supported with implementation-defined semantics.

То есть нет гарантий работоспособности передачи такого типа через .... То есть это заведомо непереносимо, т.к. "implementation-defined semantics" может быть UB или отказом от компиляции.

Но если если "implementation-defined semantics" устраивает для известного множества версий компиляторов (например, как в gcc), то формально писать так можно.


А вот чтение параметра не того типа — уже всегда UB:

[cstdarg.syn]
If the parameter parmN is of a reference type, or of a type that is not compatible with the type that results when passing an argument for which there is no parameter, the behavior is undefined.

printf будет читать в соответствии с спецификатором %s, а нужно только с va_arg(…, ttt<char>) (ну и при условии предыдущего пункта).
Re[3]: При портировании кода на линукс столкнулся с проблемо
Здравствуйте, gwg-605, Вы писали:

G6>Здравствуйте, watchmaker, Вы писали:


W>>Обе проблемы решаются исправлением кода в соответствии со стандартом языка:
printf( "%u--%s--%u", 0x55, c0.m_Pointer, 0xAA);

G6>Можно ссылочку в стандарте на эту часть?

Важны эти пункты:

[expr.call]
When there is no parameter for a given argument, the argument is passed in such a way that the receiving
function can obtain the value of the argument by invoking va_arg
...
Passing a potentially-evaluated argument of class type (Clause 12) having a non-trivial copy constructor, a non-trivial move constructor, or a non-trivial destructor, with no corresponding parameter, is conditionally-supported with implementation-defined semantics.

То есть нет гарантий работоспособности передачи такого типа через .... То есть это заведомо непереносимо, т.к. "implementation-defined semantics" может быть UB или отказом от компиляции.

Но если если "implementation-defined semantics" устраивает для известного множества версий компиляторов (например, как в gcc), то формально писать так можно.
clang тут прав.
gcc, с разным способом передачи в зависимости от наличия конструктора, тоже прав.

А вот чтение параметра не того типа — уже всегда UB:

[cstdarg.syn]
If the parameter parmN is of a reference type, or of a type that is not compatible with the type that results when passing an argument for which there is no parameter, the behavior is undefined.

printf будет читать в соответствии с спецификатором %s, а нужно только с va_arg(…, ttt<char>) (ну и при условии предыдущего пункта).