类型打孔/铸造问题 [英] Type-punning / casting problem

查看:52
本文介绍了类型打孔/铸造问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

亲爱的专家,


我需要一个浮点函数,在

处交换它的字节序(htonl),并返回一个char *指针到它的第一个字节。这是一个

系列函数之一,它准备了不同的数据类型,用于传递给另一个进程的



我有在施法时,关于什么不起作用,什么会起作用的规则混淆,

和什么可能有效。具体来说,我有一个

实现,直到我删除我的调试,此时

编译器似乎决定它可以优化写入
除第一个之外的
字节,或类似的东西。这是:


模板< typename T>

inline const char * encode_arg(T& t); //链接器错误如果你试图

//编码一个类型,其中

//没有实现


/ /这个工作:

模板<>

内联const char * encode_pq_arg< int>(int& i){

i = htonl (i);

return reinterpret_cast< const char *>(& i);

}


//这一个不是:

模板<>

inline const char * encode_arg< float>(float& f){

uint32_t * ptr = reinterpret_cast< uint32_t *>(& f);

* ptr = htonl(* ptr);

const char * cptr = reinterpret_cast< const char * >(ptr);

返回cptr;

}

当我在返回之前将cptr [0]转储到cptr [3]时,有用。如果没有

调试,它就会失败;在这种情况下,很明显很难看到结果中的结果是什么,但它看起来是未定义的。


所以,是否有一些调整,将使这项工作,并确定

工作?我最好使用工会,还是更少定义?

有谁知道规则究竟是什么?

非常感谢,

Phil。

Dear Experts,

I need a function that takes a float, swaps its endianness (htonl) in
place, and returns a char* pointer to its first byte. This is one of a
family of functions that prepare different data types for passing to
another process.

I have got confused by the rules about what won''t work, what will work,
and what might work, when casting. Specifically, I have an
implementation that works until I remove my debugging, at which point
the compiler seems to decide that it can optimise away the writes to the
bytes other than the first, or something like that. Here it is:

template <typename T>
inline const char* encode_arg(T& t); // linker error if you try to
// encode a type for which there
// is no implementation

// This one works:
template <>
inline const char* encode_pq_arg<int>(int& i) {
i = htonl(i);
return reinterpret_cast<const char*>(&i);
}

// This one doesn''t:
template <>
inline const char* encode_arg<float>(float& f) {
uint32_t* ptr = reinterpret_cast<uint32_t*>(&f);
*ptr = htonl(*ptr);
const char* cptr = reinterpret_cast<const char*>(ptr);
return cptr;
}
When I dump cptr[0] to cptr[3] before the return, it works. Without the
debug, it fails; it''s obviously hard to see what ends up in the result
in that case, but it looks undefined.

So, is there some tweak that will make this work, and be certain to
work? Am I better off using a union, or is that even less defined?
Does anyone know what the rules actually are?
Many thanks,

Phil.

推荐答案

Phil Endecott写道:
Phil Endecott wrote:

亲爱的专家,
我需要一个带浮点数的函数,在

处交换它的字节序(htonl),并返回一个指向其第一个字节的char *指针。这是一个

系列函数之一,它准备了不同的数据类型,用于传递给另一个进程的



我有在施法时,关于什么不起作用,什么会起作用的规则混淆,

和什么可能有效。具体来说,我有一个

实现,直到我删除我的调试,此时

编译器似乎决定它可以优化写入
除第一个之外的
字节,或类似的东西。这是:


模板< typename T>

inline const char * encode_arg(T& t); //链接器错误如果你试图

//编码一个类型,其中

//没有实现


/ /这个工作:

模板<>

内联const char * encode_pq_arg< int>(int& i){
Dear Experts,

I need a function that takes a float, swaps its endianness (htonl) in
place, and returns a char* pointer to its first byte. This is one of a
family of functions that prepare different data types for passing to
another process.

I have got confused by the rules about what won''t work, what will work,
and what might work, when casting. Specifically, I have an
implementation that works until I remove my debugging, at which point
the compiler seems to decide that it can optimise away the writes to the
bytes other than the first, or something like that. Here it is:

template <typename T>
inline const char* encode_arg(T& t); // linker error if you try to
// encode a type for which there
// is no implementation

// This one works:
template <>
inline const char* encode_pq_arg<int>(int& i) {



错字? ^^

Typo? ^^


i = htonl(i);

return reinterpret_cast< const char *>(& i);

}
i = htonl(i);
return reinterpret_cast<const char*>(&i);
}



您是否打算交换传递值的字节?

Did you intend the bytes of the passed value to be swapped?


//这个没有:

模板<>

inline const char * encode_arg< float>(float& f){

uint32_t * ptr = reinterpret_cast< uint32_t *>(& f);

* ptr = htonl(* ptr);

const char * cptr = reinterpret_cast< const char *>(ptr);

返回cptr;

}


当我将cptr [0]转储到cptr时[3]返回之前,它的工作原理。如果没有

调试,它就会失败;在这种情况下,显然很难看到结果中的结果是什么,但它看起来未定义。
// This one doesn''t:
template <>
inline const char* encode_arg<float>(float& f) {
uint32_t* ptr = reinterpret_cast<uint32_t*>(&f);
*ptr = htonl(*ptr);
const char* cptr = reinterpret_cast<const char*>(ptr);
return cptr;
}
When I dump cptr[0] to cptr[3] before the return, it works. Without the
debug, it fails; it''s obviously hard to see what ends up in the result
in that case, but it looks undefined.



什么不是'工作?


-

Ian Collins。

What doesn''t work?

--
Ian Collins.


Ian Collins写道:
Ian Collins wrote:

Phil Endecott写道:
Phil Endecott wrote:

>亲爱的专家,

我需要一个获取float的函数,在
位置交换其endianness(htonl),并返回一个指向其第一个字节的char *指针。这是一系列函数之一,它们准备了不同的数据类型,以便传递给另一个进程。

我对于什么不能工作的规则感到困惑,什么会起作用,
以及在施法时可能起作用的东西。具体来说,我有一个
实现,直到我删除我的调试,此时编译器似乎决定它可以优化写入除第一个以外的
字节,或者类似的东西。这是:

模板< typename T>
内联const char * encode_arg(T& t); //链接器错误,如果你试图//编码一个没有实现的类型

//这个工作原理:
template< >
内联const char * encode_pq_arg< int>(int& i){
>Dear Experts,

I need a function that takes a float, swaps its endianness (htonl) in
place, and returns a char* pointer to its first byte. This is one of a
family of functions that prepare different data types for passing to
another process.

I have got confused by the rules about what won''t work, what will work,
and what might work, when casting. Specifically, I have an
implementation that works until I remove my debugging, at which point
the compiler seems to decide that it can optimise away the writes to the
bytes other than the first, or something like that. Here it is:

template <typename T>
inline const char* encode_arg(T& t); // linker error if you try to
// encode a type for which there
// is no implementation

// This one works:
template <>
inline const char* encode_pq_arg<int>(int& i) {



错字? ^^


Typo? ^^



是的,复制和牧师,对不起!

Yes, copy&pastism, sorry!


> i = htonl(i);
返回reinterpret_cast< const char *>(& i);
}
> i = htonl(i);
return reinterpret_cast<const char*>(&i);
}



您是否打算要交换的传递值的字节数?

Did you intend the bytes of the passed value to be swapped?



是;来电者不再需要这个价值,所以我就地交换了

而不是制作副本。如果我复制了那么我将不得不为它分配内存并稍后释放它。

Yes; the caller doesn''t need the value any more, so I swap it in-place
rather than making a copy. If I made a copy then I would have to
allocate memory for it and free it later.


> //这个没有:
模板<>
内联const char * encode_arg< float>(float& f){
uint32_t * ptr = reinterpret_cast< uint32_t *>(& f);
* ptr = htonl(* ptr);
const char * cptr = reinterpret_cast< const char *>(ptr);
return cptr;
}

当我在返回之前将cptr [0]转储到cptr [3]时,它可以工作。如果没有
调试,它就会失败;在这种情况下,结果显然很难看到结果是什么,但它看起来未定义。
>// This one doesn''t:
template <>
inline const char* encode_arg<float>(float& f) {
uint32_t* ptr = reinterpret_cast<uint32_t*>(&f);
*ptr = htonl(*ptr);
const char* cptr = reinterpret_cast<const char*>(ptr);
return cptr;
}
When I dump cptr[0] to cptr[3] before the return, it works. Without the
debug, it fails; it''s obviously hard to see what ends up in the result
in that case, but it looks undefined.



什么不起作用?

What doesn''t work?



此函数返回的const char *指向的四个字节最终会被发送到套接字,我可以观察它们在另一个

结束。他们错了,即如果我通过2.0那么另一端的值

可能是8.923461290e-44。我看到的价值观中存在一些非确定性,这让我觉得我正在考虑未经初始化的记忆而不是系统性的腐败。我的第一个想法就是这样添加

somethng:


std :: cout<< cptr [0] =" << static_cast< int>(cptr [0])<< ....等等
[1]至[3] ...<< " \ n";


但是,只要我添加它(就在return语句之前),它就会产生

起作用:正确的值是在另一个过程中看到。我的感觉是

,调试中的cptr [n]表达式告诉编译器需要这些字节

;当没有出现这种情况时,它会认为没有使用它们,并将它们优化掉。你能想到任何其他

的解释吗?

问候,


菲尔。

The four bytes pointed to by the const char* that this function returns
eventually get sent to a socket, and I can observe them at the other
end. They are wrong, i.e. if I pass 2.0 then the value at the other end
might be 8.923461290e-44. There is some non-determinism in the values I
see, which makes me think that I''m looking at uninitialised memory
rather than a systematic corruption. My first thought was to add
somethng like this:

std::cout << "cptr[0] = " << static_cast<int>(cptr[0]) << ....etc for
[1] to [3] ... << "\n";

However, as soon as I add this (just before the return statement), it
works: the correct value is seen in the other process. My feeling is
that the cptr[n] expressions in the debugging tell the compiler that
these bytes are needed; when the debuging is not there, it thinks that
they are not used, and optimises them away. Can you think of any other
explanation?
Regards,

Phil.


Phil Endecott写道:
Phil Endecott wrote:

[..]

const char *指向的四个字节,这个函数

返回最终被发送到套接字,我可以在

另一端观察它们。它们是错误的,即如果我通过2.0,那么另一端的价值可能是8.923461290e-44。在我看到的值中有一些

非确定性,这让我觉得我是在看未初始化的内存而不是系统性的腐败。我的

首先想到的是添加这样的东西:


std :: cout<< cptr [0] =" << static_cast< int>(cptr [0])<< ....等等
[1]至[3] ...<< " \ n";


但是,只要我添加它(就在return语句之前),它就会产生

起作用:正确的值是在另一个过程中看到。我的感觉是

,调试中的cptr [n]表达式告诉编译器需要这些字节

;当没有出现这种情况时,它会认为没有使用它们,并将它们优化掉。你能想到其他的解释吗?
[..]
The four bytes pointed to by the const char* that this function
returns eventually get sent to a socket, and I can observe them at
the other end. They are wrong, i.e. if I pass 2.0 then the value at
the other end might be 8.923461290e-44. There is some
non-determinism in the values I see, which makes me think that I''m
looking at uninitialised memory rather than a systematic corruption. My
first thought was to add somethng like this:

std::cout << "cptr[0] = " << static_cast<int>(cptr[0]) << ....etc for
[1] to [3] ... << "\n";

However, as soon as I add this (just before the return statement), it
works: the correct value is seen in the other process. My feeling is
that the cptr[n] expressions in the debugging tell the compiler that
these bytes are needed; when the debuging is not there, it thinks that
they are not used, and optimises them away. Can you think of any
other explanation?



编译器由人类编写。 Errare humanum est。因此所有

编译器都有错误,已知和未知。如果你想知道你遇到的bug是否已知,请联系编译器编写者。

如果你只是想要解决方法,请禁用优化小的

模块,其中这个函数(这些函数)是(是),看看是否

它有什么不同。我之前看到过HP和Sun编译器看似随机行为的显着改善,以及

甚至< gasp!与微软的VC ++编译器,如果优化是在本地禁用



V

-

请删除资金''通过电子邮件回复时的答案

我没有回复最热门的回复,请不要问

Compilers are written by humans. Errare humanum est. Hence all
compilers have bugs, known and unknown. If you want to know whether
the bug you''re encountering is known, contact the compiler writers.
If you just want a work-around, disable optimization for the small
module in which this function (these functions) is (are), and see if
it makes any difference. I''ve seen a significant improvement from
seemingly random behaviour with the HP and Sun compilers before, and
even <gasp!with Microsoft''s VC++ compiler, if optimizations are
disabled locally.

V
--
Please remove capital ''A''s when replying by e-mail
I do not respond to top-posted replies, please don''t ask


这篇关于类型打孔/铸造问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆