由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
Programming版 - c++ pointer conversion question
相关主题
C++ formatted output questiona pointer to a const addr
最新某公司onsite面试题 (转载)C++ Q93 - Q95 (转载)
C++问题: 指针变量是哪里产生的?简单的c code问题
Why do I need to use "plain" pointer?array和pointer在作为函数返回时有啥区别 (C)
JHQ的一道指针题。int F::*x = &F::x是什么意思?
is smart_ptr really that good?c++ 里用到pointer 的地方我们尽可能用smart pointer吗?
pointer overflow不如各位高手挑个专题讲讲C++11吧
C++ Q05: pointer to constant variableGo adopts JavaScript’s idea of semicolon insertion
相关话题的讨论汇总
话题: float话题: pointer话题: int话题: printf话题: undefined
进入Programming版参与讨论
1 (共1页)
s******s
发帖数: 505
1
The C code blow can be used to read a floating point number
representation. However, line 8 will not work with g++
(invalid conversion from ‘void*’ to ‘float*’ [-fpermissive]).
What is the proper way to do this in C++?
Thank you.
========
1 #include
2
3 int main() {
4 float *numfp;
5 int numi;
6
7 numi = 1082130432;
8 numfp = (void *)&numi;
9 printf("%f\n", *numfp);
10 return 0;
11
12 }
a****l
发帖数: 8211
2
numfp = (float *)&numi;
what else do you want?

【在 s******s 的大作中提到】
: The C code blow can be used to read a floating point number
: representation. However, line 8 will not work with g++
: (invalid conversion from ‘void*’ to ‘float*’ [-fpermissive]).
: What is the proper way to do this in C++?
: Thank you.
: ========
: 1 #include
: 2
: 3 int main() {
: 4 float *numfp;

s******s
发帖数: 505
3

Oh, Yeah! I was thinking about truncating, lol.
Thank you.

【在 a****l 的大作中提到】
: numfp = (float *)&numi;
: what else do you want?

t****t
发帖数: 6806
4
ok, according to C/C++ standard, accessing an object with other type of
pointer/reference is undefined unless you do it through union, compatible
types (such as int*/unsigned*), or char*.

【在 s******s 的大作中提到】
:
: Oh, Yeah! I was thinking about truncating, lol.
: Thank you.

t****t
发帖数: 6806
5
let me show you an example:
/* 1.c */
#include
void bar(int* a, float* b)
{
a[5]=200;
b[5]=1.0;
printf("%d\n", a[5]);
printf("&a[5]=%p &b[5]=%p\n", a+5, b+5);
}
/* 2.c */
void bar(int*, float*);
int main()
{
int a[10];
float* b=(float*)a;
bar(a, b);
}
What do you think the result is?
compile with -O2 and -O0, you get different results:
$ gcc -O0 1.c 2.c
$ a.out
1065353216
&a[5]=0x7fffb3828964 &b[5]=0x7fffb3828964
$ gcc -O2 1.c 2.c
$ a.out
200
&a[5]=0x7fff2e722424 &b[5]=0x7fff2e722424
[You must use 2 compilation unit, or gcc will "figure out" correct answer for you.]

【在 t****t 的大作中提到】
: ok, according to C/C++ standard, accessing an object with other type of
: pointer/reference is undefined unless you do it through union, compatible
: types (such as int*/unsigned*), or char*.

a***y
发帖数: 2803
6
re

【在 a****l 的大作中提到】
: numfp = (float *)&numi;
: what else do you want?

s******s
发帖数: 505
7
That's code looks pretty solid to me. Where did you
get them? Did you make it up? How did you find it?

【在 t****t 的大作中提到】
: let me show you an example:
: /* 1.c */
: #include
: void bar(int* a, float* b)
: {
: a[5]=200;
: b[5]=1.0;
: printf("%d\n", a[5]);
: printf("&a[5]=%p &b[5]=%p\n", a+5, b+5);
: }

t****t
发帖数: 6806
8
i wrote the example myself (and tested it).
when you know what's the rule, and how the compiler follows the rule, you
can create whatever examples for your points. you don't have to find it
somewhere.

【在 s******s 的大作中提到】
: That's code looks pretty solid to me. Where did you
: get them? Did you make it up? How did you find it?

a***y
发帖数: 2803
9
a[5]=200;
printf("%d\n", a[5]);
为什么用-00 得出的结果不对呢?

【在 t****t 的大作中提到】
: let me show you an example:
: /* 1.c */
: #include
: void bar(int* a, float* b)
: {
: a[5]=200;
: b[5]=1.0;
: printf("%d\n", a[5]);
: printf("&a[5]=%p &b[5]=%p\n", a+5, b+5);
: }

t****t
发帖数: 6806
10
you didn't read my previous post, did you?
and you didn't read the code carefully, either. intuitively, -O0 result is "correct", -O2 result is "wrong".
But the code is undefined anyway, so both result are correct. any result can be expect for undefined code.

【在 a***y 的大作中提到】
: a[5]=200;
: printf("%d\n", a[5]);
: 为什么用-00 得出的结果不对呢?

相关主题
is smart_ptr really that good?a pointer to a const addr
pointer overflowC++ Q93 - Q95 (转载)
C++ Q05: pointer to constant variable简单的c code问题
进入Programming版参与讨论
a***y
发帖数: 2803
11
a[5]=200;
printf("%d\n", a[5]);
预期结果不就是200吗?

"correct", -O2 result is "wrong".
can be expect for undefined code.

【在 t****t 的大作中提到】
: you didn't read my previous post, did you?
: and you didn't read the code carefully, either. intuitively, -O0 result is "correct", -O2 result is "wrong".
: But the code is undefined anyway, so both result are correct. any result can be expect for undefined code.

t****t
发帖数: 6806
12
that's not my code, my code has another line between it.

【在 a***y 的大作中提到】
: a[5]=200;
: printf("%d\n", a[5]);
: 预期结果不就是200吗?
:
: "correct", -O2 result is "wrong".
: can be expect for undefined code.

a***y
发帖数: 2803
13
懂了.
浮点数1.0,二进制表示是
0 01111111 00000000000000000000000
就是十进制的 1065353216

【在 t****t 的大作中提到】
: that's not my code, my code has another line between it.
v******l
发帖数: 512
14
your point makes sense but your sample may not be quite relevant...
It merely shows how improper code (of course you deliberately made it so)
will break with optimization. The behavior of your sample is actually quite
predictable.

【在 t****t 的大作中提到】
: let me show you an example:
: /* 1.c */
: #include
: void bar(int* a, float* b)
: {
: a[5]=200;
: b[5]=1.0;
: printf("%d\n", a[5]);
: printf("&a[5]=%p &b[5]=%p\n", a+5, b+5);
: }

t****t
发帖数: 6806
15
my point is to show what is improper code: you are not to alias and access
an object with imcompatible type through pointer conversion. for int and
float, maybe it is obvious that you shouldn't do it. but for some other
types, it may not be that obvious: for example, you can't change a void*
through pointer/reference to void**, even if you do casting (e.g. when
x is void*, you can't do (*(void***)(&x)) = ...., even with casting). i
personally fell through that trap several years ago, when i built a custom
object pool.
of course the reason why it is improper, is that C/C++ want to make more
aggressive optimization legal, and therefore only allowing certain limited
kind of aliasing (which i mentioned in the previous post: compatible type,
char, union).

quite

【在 v******l 的大作中提到】
: your point makes sense but your sample may not be quite relevant...
: It merely shows how improper code (of course you deliberately made it so)
: will break with optimization. The behavior of your sample is actually quite
: predictable.

a****l
发帖数: 8211
16
I don't know why it is so complicated. A pointer is a pointer, as long as
you know where it points to, you can cast it to anything you want. The code
is simply pointing to the binary of a float and try to interpret it as
integer, which surprises me that sometimes it actually would work.

【在 t****t 的大作中提到】
: my point is to show what is improper code: you are not to alias and access
: an object with imcompatible type through pointer conversion. for int and
: float, maybe it is obvious that you shouldn't do it. but for some other
: types, it may not be that obvious: for example, you can't change a void*
: through pointer/reference to void**, even if you do casting (e.g. when
: x is void*, you can't do (*(void***)(&x)) = ...., even with casting). i
: personally fell through that trap several years ago, when i built a custom
: object pool.
: of course the reason why it is improper, is that C/C++ want to make more
: aggressive optimization legal, and therefore only allowing certain limited

t****t
发帖数: 6806
17
i guess you don't know what i am talking about.
removing the twist in my example, the program basically do:
int a[1];
*a=200;
*((float*)a)=1.0f;
printf("%d\n", a); // may print 200, or print 1.0f interpreted as integer
my point is, this is undefined, you can NOT do this. optimization may ignore
that (float*)a and a are pointing to the same address.

code

【在 a****l 的大作中提到】
: I don't know why it is so complicated. A pointer is a pointer, as long as
: you know where it points to, you can cast it to anything you want. The code
: is simply pointing to the binary of a float and try to interpret it as
: integer, which surprises me that sometimes it actually would work.

a****l
发帖数: 8211
18
is it possible that b[5]=1.0 got deleted by the optimization process? E.g.,
if we do like this:
volatile int k;
void bar(int* a, float* b)
{
a[5]=200+k;
b[5]=1.0+k;
k = a[5]*b[5];
printf("%d,%d,%d\n", a[5],b[5],k);
printf("&a[5]=%p &b[5]=%p\n", a+5, b+5);
}
will that make any difference with different optimization switch?

【在 t****t 的大作中提到】
: let me show you an example:
: /* 1.c */
: #include
: void bar(int* a, float* b)
: {
: a[5]=200;
: b[5]=1.0;
: printf("%d\n", a[5]);
: printf("&a[5]=%p &b[5]=%p\n", a+5, b+5);
: }

t****t
发帖数: 6806
19
1st of all, the function is not supposed to delete that statement arbitrary,
since the function may be called with different parameter. what happens
here is, compiler thinks b[5]=1.0 is not supposed to change a[5] because
float and int are incompatible. so compiler just use 200 as a[5].

,

【在 a****l 的大作中提到】
: is it possible that b[5]=1.0 got deleted by the optimization process? E.g.,
: if we do like this:
: volatile int k;
: void bar(int* a, float* b)
: {
: a[5]=200+k;
: b[5]=1.0+k;
: k = a[5]*b[5];
: printf("%d,%d,%d\n", a[5],b[5],k);
: printf("&a[5]=%p &b[5]=%p\n", a+5, b+5);

v******l
发帖数: 512
20
First, I suppose your last statement should be:
printf("%d\n", a[0]);
OR
printf("%d\n", *a);
because otherwise you're printing a pointer as an integer, which does not
make much sense here.
With that change, I doubt this sample will ever print 200 at all because you
clearly give the compiler that logic you want (unlike that last sample you
deliberately hide the fact from the compiler that the two pointers are to
the same address). I'm pretty sure it will print 1065353216 on any 32/64-bit
small-endian machines.
The "undefined" thing, as I understand, is because C++ does not define the
exact layout of a data structure (especially instances of complex classes
with multiple/virtual inheritance) in memory. Thus the layout of target memory
of an arbitrary casted pointer is also regarded as "undefined". However in any case C++ should not break the program logic if it is unambiguously given by programmer, and the proper use of such a
pointer is programmer's responsibility.

integer
ignore

【在 t****t 的大作中提到】
: i guess you don't know what i am talking about.
: removing the twist in my example, the program basically do:
: int a[1];
: *a=200;
: *((float*)a)=1.0f;
: printf("%d\n", a); // may print 200, or print 1.0f interpreted as integer
: my point is, this is undefined, you can NOT do this. optimization may ignore
: that (float*)a and a are pointing to the same address.
:
: code

相关主题
array和pointer在作为函数返回时有啥区别 (C)不如各位高手挑个专题讲讲C++11吧
int F::*x = &F::x是什么意思?Go adopts JavaScript’s idea of semicolon insertion
c++ 里用到pointer 的地方我们尽可能用smart pointer吗?C一个问题搞不懂
进入Programming版参与讨论
t****t
发帖数: 6806
21
yes, that *a is a typo. and removing the twist, yes, compiler most probably
will give the result you expect. (but the program remains undefined.)
but no, your understanding is wrong. the target of an arbitrary cast pointer
is not undefined. but you can not alias it. the rule of thumb here is, do
not cast lvalue [and access it], but you can cast rvalue. casting a pointer
to another type is ok, but accessing through that pointer is usually not (
unless it is compatible).

you
you
bit

【在 v******l 的大作中提到】
: First, I suppose your last statement should be:
: printf("%d\n", a[0]);
: OR
: printf("%d\n", *a);
: because otherwise you're printing a pointer as an integer, which does not
: make much sense here.
: With that change, I doubt this sample will ever print 200 at all because you
: clearly give the compiler that logic you want (unlike that last sample you
: deliberately hide the fact from the compiler that the two pointers are to
: the same address). I'm pretty sure it will print 1065353216 on any 32/64-bit

v******l
发帖数: 512
22
I don't quite get what you mean by "can not alias it". Your sample code is a
typical aliasing and as long as there is no memory issue (overflow or
something) there is nothing wrong with it.
Look at it this way: You need a buffer by using malloc you get a big chunk
of memory pointed by void *p0. There is nothing wrong you first cast it to
int* and fill it with a bunch of integers, then cast to float* and reads
them out as floats. It is merely a re-interpretation of data and it behaves
just like a union.

probably
pointer
pointer

【在 t****t 的大作中提到】
: yes, that *a is a typo. and removing the twist, yes, compiler most probably
: will give the result you expect. (but the program remains undefined.)
: but no, your understanding is wrong. the target of an arbitrary cast pointer
: is not undefined. but you can not alias it. the rule of thumb here is, do
: not cast lvalue [and access it], but you can cast rvalue. casting a pointer
: to another type is ok, but accessing through that pointer is usually not (
: unless it is compatible).
:
: you
: you

t****t
发帖数: 6806
23
What you describe is exactly undefined by standard, as I showed in my
example. it is as undefined as "a[i]=i++", or "j=(i++)*(i++)". read standard
3.10, and gcc manual "-fstrict-aliasing".
you may use union to achieve the desired result with defined behaviour.

a
behaves

【在 v******l 的大作中提到】
: I don't quite get what you mean by "can not alias it". Your sample code is a
: typical aliasing and as long as there is no memory issue (overflow or
: something) there is nothing wrong with it.
: Look at it this way: You need a buffer by using malloc you get a big chunk
: of memory pointed by void *p0. There is nothing wrong you first cast it to
: int* and fill it with a bunch of integers, then cast to float* and reads
: them out as floats. It is merely a re-interpretation of data and it behaves
: just like a union.
:
: probably

v******l
发帖数: 512
24
Ok I think I see your point. Still, there is a difference between strict-
aliasing rule and "a[i]=i++" situation, the later is semantically ambiguous
by itself, while the alias issue is actually a BREAK of otherwise perfect
logic as a price paid for aggressive optimization.

standard

【在 t****t 的大作中提到】
: What you describe is exactly undefined by standard, as I showed in my
: example. it is as undefined as "a[i]=i++", or "j=(i++)*(i++)". read standard
: 3.10, and gcc manual "-fstrict-aliasing".
: you may use union to achieve the desired result with defined behaviour.
:
: a
: behaves

t****t
发帖数: 6806
25
you may have a point, but "otherwise perfect logic" is defined by whom?
AFAIK, strict-aliasing is enforced as early as C89. maybe some compilers
allow it, but that doesn't make it legal.

ambiguous

【在 v******l 的大作中提到】
: Ok I think I see your point. Still, there is a difference between strict-
: aliasing rule and "a[i]=i++" situation, the later is semantically ambiguous
: by itself, while the alias issue is actually a BREAK of otherwise perfect
: logic as a price paid for aggressive optimization.
:
: standard

v******l
发帖数: 512
26
I said "perfect logic" because there is no underline logic flaw as it is.
Problem only occurs when the strict-aliasing rule assumes "pointers of
different types cannot point to the same memory address". This assumption
adds complexity to the language and is anti-intuitive, thus make the
learning curve a little bit steeper, but sure it is well justified by
performance improvement and other benefits.

【在 t****t 的大作中提到】
: you may have a point, but "otherwise perfect logic" is defined by whom?
: AFAIK, strict-aliasing is enforced as early as C89. maybe some compilers
: allow it, but that doesn't make it legal.
:
: ambiguous

1 (共1页)
进入Programming版参与讨论
相关主题
Go adopts JavaScript’s idea of semicolon insertionJHQ的一道指针题。
C一个问题搞不懂is smart_ptr really that good?
C 语言,初学者,简单问题pointer overflow
pointer to override function?C++ Q05: pointer to constant variable
C++ formatted output questiona pointer to a const addr
最新某公司onsite面试题 (转载)C++ Q93 - Q95 (转载)
C++问题: 指针变量是哪里产生的?简单的c code问题
Why do I need to use "plain" pointer?array和pointer在作为函数返回时有啥区别 (C)
相关话题的讨论汇总
话题: float话题: pointer话题: int话题: printf话题: undefined