|
|||
|
Wojtek Lerch <wojtek_l@yahoo.ca> writes:
> On 06/02/2011 6:54 PM, Ben Bacarisse wrote: >> Also, in C, E->M is not defined to >> be the same as (*E).M or there would certainly be an access via an >> lvalue expression of type T1. > > Why? Are you saying that whenever an lvalue expression such as S.M is > evaluated, it counts not only as an access to the member but also an > access to the whole structure? (Except, I assume, in a context where > it does not access an object at all, such as in &S.M?) Hmm... I did not want to derail the discussion of the pointer access but I think you are right. I should just have said "there would certainly be an lvalue expression of type T1" without saying if there is an access "via" it or not. > Or do you have something more subtle in mind, maybe along the lines > that the expression S.M accesses only the member, but it accesses it > "via" an lvalue expression of the structure type, without accessing > the whole structure, because the struct lvalue is a subexpression of > the lvalue designating the object actualy accessed? I think used to but I am really not sure anymore! One certainly can't read the definition of . as implying an access of the whole structure, but then I am puzzled by the pupose of the second to last of the access rules (6.5 p7). I see that the rules don't use the term "via" but simply "by". I think it might help if I start a new thread asking a naive question about 6.5 p7. -- Ben. |
|
|
||||
|
||||
|
|
|
|||
|
Joshua Maurice wrote:
> On Feb 6, 3:34 pm, "Johannes Schaub (litb)" > <schaub.johan...@googlemail.com> wrote: >> [snipped] > To be clear, you think that there's a difference between > a->x = 2; > and > int* x = & a->x; > *x = 2; > ? > > It would take me a long time to buy that. Yes I think there is a difference between te two. The first uses the struct for the access. The second does not. |
|
|||
|
On Feb 7, 8:09*am, "Johannes Schaub (litb)"
<schaub.johan...@googlemail.com> wrote: > Joshua Maurice wrote: > > On Feb 6, 3:34 pm, "Johannes Schaub (litb)" > > <schaub.johan...@googlemail.com> wrote: > >> [snipped] > > To be clear, you think that there's a difference between > > * a->x = 2; > > and > > * int* x = & a->x; > > * *x = 2; > > ? > > > It would take me a long time to buy that. > > Yes I think there is a difference between te two. The first uses the struct > for the access. The second does not. I never really considered this beyond a first glance. Again, to be crystal clear, consider: /* 1 */ a -> x = 2; and /* 2 */ * ( & ( a -> x )) = 2; and /* 3 */ int* x = & a->x; *x = 2; You really think there's a difference? Really? Where's the difference? Between 1 and 2, or 2 and 3? I /hope/ between 1 and 2. 2 and 3 better be entirely equivalent, or I'm really losing it. As a naive understanding for the difference between 1 and 2: The addressof operator (&) simply returns the address of the object referred to the lvalue, and then the dereference operator (*) simply takes that pointer value and returns back the same lvalue (which refers to the same object). This isn't operator overloading in C++. I would think that it ought to be a noop. If there is any difference at all between any of 1, 2, and 3 above in this post, then I have a fundamental misunderstanding of the language. |
|
|||
|
On 07/02/2011 3:11 PM, Joshua Maurice wrote:
> Again, to be crystal clear, consider: > /* 1 */ > a -> x = 2; > and > /* 2 */ > * (& ( a -> x )) = 2; > and > /* 3 */ > int* x =& a->x; > *x = 2; > > You really think there's a difference? Really? Where's the difference? > Between 1 and 2, or 2 and 3? I /hope/ between 1 and 2. 2 and 3 better > be entirely equivalent, or I'm really losing it. > > As a naive understanding for the difference between 1 and 2: The > addressof operator (&) simply returns the address of the object > referred to the lvalue, and then the dereference operator (*) simply > takes that pointer value and returns back the same lvalue (which > refers to the same object). This isn't operator overloading in C++. I > would think that it ought to be a noop. If there is any difference at > all between any of 1, 2, and 3 above in this post, then I have a > fundamental misunderstanding of the language. I don't think a C pointer is simply just the address of an object. If you consider the rules of pointer arithmetic and DR260, a pointer value carries some extra properties that decide what operations on it are defined. Two pointers may compare equal and be represented by identical bit patterns, but depending on their "provenance", one of them may be safe to dereference or increment but not decrement, while the other may be safe to decrement but not increment or dereference. The standard tells us that every object can be considered an array element, and every pointer to an object has a range of integers that can be legitimately added to it, based on the object's "arrayness"; but the standard rarely bothers explaining how to determine what that array is, and all we can do is rely on obvious guesses where they're obvious, and in less-obvious cases we can hope that the guess is even harder for a compiler, forcing it to generate code that does the "naive" thing regardless of what the limit would be if the standard didn't neglect to specify it. Since this "arrayness" is not exactly on topic here, I don't want to go too deep into it now; but maybe pointers are also supposed to remember their "structness", and your &a->x (and also your x) are not just pointers to an int that is known not to be an array element, but pointers to an int that is known not to be an array element but is also known to be the "x" member of a struct T1? If that were the case, then maybe a simple assignment to *x could still impose an effective type of struct T1 on the object surrounding the int that x points to. But of course none of that is actually discussed in the standard, just like the transformations of "arrayness" are not discussed for most of the operations where they apparently happen. |
|
|||
|
On Feb 7, 1:31*pm, Wojtek Lerch <wojte...@yahoo.ca> wrote:
> On 07/02/2011 3:11 PM, Joshua Maurice wrote: > > > > > Again, to be crystal clear, consider: > > * */* 1 */ > > * *a -> *x = 2; > > and > > * */* 2 */ > > * ** (& *( a -> *x )) = 2; > > and > > * */* 3 */ > > * *int* x =& *a->x; > > * **x = 2; > > > You really think there's a difference? Really? Where's the difference? > > Between 1 and 2, or 2 and 3? I /hope/ between 1 and 2. 2 and 3 better > > be entirely equivalent, or I'm really losing it. > > > As a naive understanding for the difference between 1 and 2: The > > addressof operator (&) simply returns the address of the object > > referred to the lvalue, and then the dereference operator (*) simply > > takes that pointer value and returns back the same lvalue (which > > refers to the same object). This isn't operator overloading in C++. I > > would think that it ought to be a noop. If there is any difference at > > all between any of 1, 2, and 3 above in this post, then I have a > > fundamental misunderstanding of the language. > > I don't think a C pointer is simply just the address of an object. *If > you consider the rules of pointer arithmetic and DR260, a pointer value > carries some extra properties that decide what operations on it are > defined. *Two pointers may compare equal and be represented by identical > bit patterns, but depending on their "provenance", one of them may be > safe to dereference or increment but not decrement, while the other may > be safe to decrement but not increment or dereference. *The standard > tells us that every object can be considered an array element, and every > pointer to an object has a range of integers that can be legitimately > added to it, based on the object's "arrayness"; but the standard rarely > bothers explaining how to determine what that array is, and all we can > do is rely on obvious guesses where they're obvious, and in less-obvious > cases we can hope that the guess is even harder for a compiler, forcing > it to generate code that does the "naive" thing regardless of what the > limit would be if the standard didn't neglect to specify it. > > Since this "arrayness" is not exactly on topic here, I don't want to go > too deep into it now; but maybe pointers are also supposed to remember > their "structness", and your &a->x (and also your x) are not just > pointers to an int that is known not to be an array element, but > pointers to an int that is known not to be an array element but is also > known to be the "x" member of a struct T1? *If that were the case, then > maybe a simple assignment to *x could still impose an effective type of > struct T1 on the object surrounding the int that x points to. *But of > course none of that is actually discussed in the standard, just like the > transformations of "arrayness" are not discussed for most of the > operations where they apparently happen. Indeed. This is exactly what I meant when I was saying "data dependency analysis". I think your way is clearer. (It could be that) pointer values carry with them some semantic information, in this case it remembers that it came from a memberof expression on a T1 lvalue. I'll have to check out that DR. Are there any other spots in the C standard which you suggest that I look at regarding this "arrayness"? |
|
|||
|
On 07.02.2011 12:10, Tim Rentsch wrote:
> "Johannes Schaub (litb)"<schaub.johannes@googlemail.com> writes: > >> [snip] >> >> In particular, I think the committee intends the spec to say that a struct >> or union access expression involves an access with the struct or union >> lvalue. >> >> T1 *p = malloc(sizeof *p); >> p->x = 0; >> >> In this case, I think the committee's intent is that the object pointed to >> by "p" is accesse by an lvalue of type T1, and so the effective type of the >> object containing the int changes to T1. So a later cast and access by an >> lvalue of T2 will be undefined behavior. > > I'm not aware of any evidence that supports this theory (ie, > that using '.' or '->' is also an access for the left operand). > Furthermore it seems to be in conflict with the definitions the > Standard gives for access, value, etc. > > Do you have any such evidence to offer? Or are you simply > stating an unsupported opinion? The committee argues that way in the union DR. See http://www.open- std.org/jtc1/sc22/wg14/www/docs/dr_236.htm . |
|
|||
|
On 07.02.2011 21:11, Joshua Maurice wrote:
> On Feb 7, 8:09 am, "Johannes Schaub (litb)" > <schaub.johan...@googlemail.com> wrote: >> Joshua Maurice wrote: >>> On Feb 6, 3:34 pm, "Johannes Schaub (litb)" >>> <schaub.johan...@googlemail.com> wrote: >>>> [snipped] >>> To be clear, you think that there's a difference between >>> a->x = 2; >>> and >>> int* x =& a->x; >>> *x = 2; >>> ? >> >>> It would take me a long time to buy that. >> >> Yes I think there is a difference between te two. The first uses the struct >> for the access. The second does not. > > I never really considered this beyond a first glance. > > Again, to be crystal clear, consider: > /* 1 */ > a -> x = 2; > and > /* 2 */ > * (& ( a -> x )) = 2; > and > /* 3 */ > int* x =& a->x; > *x = 2; > > You really think there's a difference? Really? Where's the difference? > Between 1 and 2, or 2 and 3? I /hope/ between 1 and 2. 2 and 3 better > be entirely equivalent, or I'm really losing it. > Yes, I think /* 1 */ is different from /* 2 */ in that /* 1 */ involves the type of a's struct in the access. /* 2 */ is equivalen to /* 3 */ I think. Anyway, the committee says in the union-DR that this is UB: union A { int a; float b; } u; u.a = 0; float *b = &u.b; *b = 0.f; // *&u.b = 0.f; // i think this is equivalent The only way I can use aliasing rule to get to UB is: The object at "u" has effective type "union A" (with a sizeof union A) and effective type int (with a sizeof int). If you access it with merely "int", you access the object whose' effecive type is A with an lvalue of type int. And have undefined behavior. But I don't think that this makes sense. It would mean the following is UB too: struct A { int a; } b; b.a = 0; *&b.a = 0; Same situation. We access an object whose effective type is struct A by an lvalue of type int. So I can't follow the committee's intent here anyway. I.e whatever you might think about /* 1 */ and /* 2 */ having apparently different semantics, I can neither explain nor understand the extent of it. > As a naive understanding for the difference between 1 and 2: The > addressof operator (&) simply returns the address of the object > referred to the lvalue, and then the dereference operator (*) simply > takes that pointer value and returns back the same lvalue (which > refers to the same object). This isn't operator overloading in C++. I > would think that it ought to be a noop. If there is any difference at > all between any of 1, 2, and 3 above in this post, then I have a > fundamental misunderstanding of the language. I thought we agreed that "a.b = ..." and "*x = ..." are different in that the type of "a" has some influence on the access, in order to deem the following UB. typedef struct A { int a; } A; typedef struct B { int a; } B; A *x = malloc(sizeof *a); x->a = 0; // access with effective type A and int ((B*)x)->a = 0; // I thought we agreed this is UB // and committee intent. I think *I* am misunderstanding the matter rather than you ![]() |
|
|||
|
On 07.02.2011 21:11, Joshua Maurice wrote:
> On Feb 7, 8:09 am, "Johannes Schaub (litb)" > <schaub.johan...@googlemail.com> wrote: >> Joshua Maurice wrote: >>> On Feb 6, 3:34 pm, "Johannes Schaub (litb)" >>> <schaub.johan...@googlemail.com> wrote: >>>> [snipped] >>> To be clear, you think that there's a difference between >>> a->x = 2; >>> and >>> int* x =& a->x; >>> *x = 2; >>> ? >> >>> It would take me a long time to buy that. >> >> Yes I think there is a difference between te two. The first uses the struct >> for the access. The second does not. > > I never really considered this beyond a first glance. > > Again, to be crystal clear, consider: > /* 1 */ > a -> x = 2; > and > /* 2 */ > * (& ( a -> x )) = 2; > and > /* 3 */ > int* x =& a->x; > *x = 2; > > You really think there's a difference? Really? Where's the difference? > Between 1 and 2, or 2 and 3? I /hope/ between 1 and 2. 2 and 3 better > be entirely equivalent, or I'm really losing it. > Yes, I think /* 1 */ is different from /* 2 */ in that /* 1 */ involves the type of a's struct in the access. /* 2 */ is equivalen to /* 3 */ I think. Anyway, the committee says in the union-DR that this is UB: union A { int a; float b; } u; u.a = 0; float *b = &u.b; *b = 0.f; // *&u.b = 0.f; // i think this is equivalent The only way I can use aliasing rule to get to UB is: The object at "u" has effective type "union A" (with a sizeof union A) and effective type int (with a sizeof int). If you access it with merely "int", you access the object whose' effecive type is A with an lvalue of type int. And have undefined behavior. But I don't think that this makes sense. It would mean the following is UB too: struct A { int a; } b; b.a = 0; *&b.a = 0; Same situation. We access an object whose effective type is struct A by an lvalue of type int. So I can't follow the committee's intent here anyway. I.e whatever you might think about /* 1 */ and /* 2 */ having apparently different semantics, I can neither explain nor understand the extent of it. > As a naive understanding for the difference between 1 and 2: The > addressof operator (&) simply returns the address of the object > referred to the lvalue, and then the dereference operator (*) simply > takes that pointer value and returns back the same lvalue (which > refers to the same object). This isn't operator overloading in C++. I > would think that it ought to be a noop. If there is any difference at > all between any of 1, 2, and 3 above in this post, then I have a > fundamental misunderstanding of the language. I thought we agreed that "a.b = ..." and "*x = ..." are different in that the type of "a" has some influence on the access, in order to deem the following UB. typedef struct A { int a; } A; typedef struct B { int a; } B; A *x = malloc(sizeof *a); x->a = 0; // access with effective type A and int ((B*)x)->a = 0; // I thought we agreed this is UB // and committee intent. I think *I* am misunderstanding the matter rather than you ![]() |
|
|||
|
"Johannes Schaub (litb)" <schaub.johannes@googlemail.com> writes:
> On 07.02.2011 12:10, Tim Rentsch wrote: >> "Johannes Schaub (litb)"<schaub.johannes@googlemail.com> writes: >> >>> [snip] >>> >>> In particular, I think the committee intends the spec to say that a struct >>> or union access expression involves an access with the struct or union >>> lvalue. >>> >>> T1 *p = malloc(sizeof *p); >>> p->x = 0; >>> >>> In this case, I think the committee's intent is that the object pointed to >>> by "p" is accesse by an lvalue of type T1, and so the effective type of the >>> object containing the int changes to T1. So a later cast and access by an >>> lvalue of T2 will be undefined behavior. >> >> I'm not aware of any evidence that supports this theory (ie, >> that using '.' or '->' is also an access for the left operand). >> Furthermore it seems to be in conflict with the definitions the >> Standard gives for access, value, etc. >> >> Do you have any such evidence to offer? Or are you simply >> stating an unsupported opinion? > > The committee argues that way in the union DR. See http://www.open- > std.org/jtc1/sc22/wg14/www/docs/dr_236.htm . Actually they don't. You might infer that's what they are thinking, but no such position is stated, nor is it necessary to reach the conclusions they reach. |
|
|||
|
On 08.02.2011 04:17, Tim Rentsch wrote:
> "Johannes Schaub (litb)"<schaub.johannes@googlemail.com> writes: > >> On 07.02.2011 21:11, Joshua Maurice wrote: >>> On Feb 7, 8:09 am, "Johannes Schaub (litb)" >>> <schaub.johan...@googlemail.com> wrote: >>>> Joshua Maurice wrote: >>>>> On Feb 6, 3:34 pm, "Johannes Schaub (litb)" >>>>> <schaub.johan...@googlemail.com> wrote: >>>>>> [snipped] >>>>> To be clear, you think that there's a difference between >>>>> a->x = 2; >>>>> and >>>>> int* x =& a->x; >>>>> *x = 2; >>>>> ? >>>> >>>>> It would take me a long time to buy that. >>>> >>>> Yes I think there is a difference between te two. The first uses the struct >>>> for the access. The second does not. >>> >>> I never really considered this beyond a first glance. >>> >>> Again, to be crystal clear, consider: >>> /* 1 */ >>> a -> x = 2; >>> and >>> /* 2 */ >>> * (& ( a -> x )) = 2; >>> and >>> /* 3 */ >>> int* x =& a->x; >>> *x = 2; >>> >>> You really think there's a difference? Really? Where's the difference? >>> Between 1 and 2, or 2 and 3? I /hope/ between 1 and 2. 2 and 3 better >>> be entirely equivalent, or I'm really losing it. >>> >> >> Yes, I think /* 1 */ is different from /* 2 */ in that /* 1 */ >> involves the type of a's struct in the access. /* 2 */ is equivalen to >> /* 3 */ I think. >> >> Anyway, the committee says in the union-DR that this is UB: >> >> union A { int a; float b; } u; >> u.a = 0; >> float *b =&u.b; >> *b = 0.f; >> // *&u.b = 0.f; // i think this is equivalent > > Assuming you're talking about DR 236, they say no such thing. Then I encourage you to tell us what else they say by: > Committee believes that Example 2 violates the aliasing rules in 6.5 paragraph 7: > > "an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union)." > In order to not violate the rules, function f in example should be written as: > union tag { > int mi; > double md; > } u; > void f(int *qi, double *qd) { > int i = *qi + 2; > u.md = 3.1; // union type must be used when changing effective type > *qd *= i; > return; > } |
|
|||
|
On 08.02.2011 04:30, Johannes Schaub (litb) wrote:
>> Assuming you're talking about DR 236, they say no such thing. > > Then I encourage you to tell us what else they say by: > >> Committee believes that Example 2 violates the aliasing rules in 6.5 >> paragraph 7: >> >> "an aggregate or union type that includes one of the aforementioned >> types among its members (including, recursively, a member of a >> subaggregate or contained union)." >> In order to not violate the rules, function f in example should be >> written as: >> union tag { >> int mi; >> double md; >> } u; >> void f(int *qi, double *qd) { >> int i = *qi + 2; >> u.md = 3.1; // union type must be used when changing >> effective type >> *qd *= i; >> return; >> } > Hm, it seems I may have misunderstood what they say. They actually seems to say that a write like "*qd = 0" does *not* chagne the effective type of the accessed object. But that seems wrong, because the aliasing rule says that a write changes the effective type *for that access* and for all further read accesses. So WTF does the committee say!? |
|
|||
|
On Feb 7, 7:37*pm, "Johannes Schaub (litb)"
<schaub.johan...@googlemail.com> wrote: > On 08.02.2011 04:30, Johannes Schaub (litb) wrote: > > > > >> Assuming you're talking about DR 236, they say no such thing. > > > Then I encourage you to tell us what else they say by: > > >> Committee believes that Example 2 violates the aliasing rules in 6.5 > >> paragraph 7: > > >> "an aggregate or union type that includes one of the aforementioned > >> types among its members (including, recursively, a member of a > >> subaggregate or contained union)." > >> In order to not violate the rules, function f in example should be > >> written as: > >> * *union tag { > >> * * * * * * * * int mi; > >> * * * * * * * * double md; > >> * * * * } u; > >> * * * * void f(int *qi, double *qd) { > >> * * * * * * * * int i = *qi + 2; > >> * * * * * * * * u.md = 3.1; * // union type must be used when changing > >> effective type > >> * * * * * * * * *qd *= i; > >> * * * * return; > >> * * * * } > > Hm, it seems I may have misunderstood what they say. They actually seems > to say that a write like "*qd = 0" does *not* chagne the effective type > of the accessed object. > > But that seems wrong, because the aliasing rule says that a write > changes the effective type *for that access* and for all further read > accesses. So WTF does the committee say!? I wish I knew. The entire set of rules is inconsistent as written, and judging from that one resolution to the DR in the C++ draft standard (in that thread on comp.lang.c++ or whatever long ago [months?]), they don't have a good idea of where to go. Apparently the C committee isn't doing much better. Both committees can leave this unresolved, or they can sit down together (or the C committee can dictate), and figure out some equitable solution. There appear to be solutions, just none of them are currently Rules As Written. The first thing the standard(s) need to do is clear up any possible differences for the following. The context is: typedef struct T { int v; int x; } T; The four examples are: a -> x = 1; and * ( & (a -> x)) = 1; and int* x = & (a -> x); *x = 1; and int* x = (int*) (((char*)a) + offsetof(T, x)); *x = 1; Which of those allow the following read to be defined? return a -> x; Those 4 examples should appear basically verbatim in the standards, and not as a non-binding notes but as actual (binding) examples which show how these rules are supposed to work. My initial naive take is that they should all be entirely equivalent. Apparently this is not a widely agreed upon conclusion. Furthermore, if they are all indeed equivalent, then you can't get "reading a T2 object" through a "T2 lvalue" is UB. My hope is that the first three are all equivalent, and the last is where it's different. (Or we just abandon large parts of strict aliasing, which doesn't seem too likely.) With that, you can have the resulting pointer value and/or lvalue carry with it semantic information that it came from a memberof expression on a T lvalue, and thus the write through that pointer value and/or lvalue can be said to change the effective type of the object to T. (Then, we just need to get the C++ standard to come along, and we're all happy.) PS: Is my rambling too much? I'm trying not to repeat myself. I think I'm just recapping where I think the conversation is now with those four examples. |
|
|||
|
On Feb 7, 7:59*pm, Joshua Maurice <joshuamaur...@gmail.com> wrote:
> Furthermore, if they are all indeed equivalent, then you can't get > "reading a T2 object" through a "T2 lvalue" is UB. Typo. Should read: > Furthermore, if they are all indeed equivalent, then you can't get "reading a *T1* object" through a "T2 lvalue" is *necessarily* UB. |
|
|||
|
On Feb 7, 6:29*pm, "Johannes Schaub (litb)"
<schaub.johan...@googlemail.com> wrote: > On 07.02.2011 21:11, Joshua Maurice wrote: > > As a naive understanding for the difference between 1 and 2: The > > addressof operator (&) simply returns the address of the object > > referred to the lvalue, and then the dereference operator (*) simply > > takes that pointer value and returns back the same lvalue (which > > refers to the same object). This isn't operator overloading in C++. I > > would think that it ought to be a noop. If there is any difference at > > all between any of 1, 2, and 3 above in this post, then I have a > > fundamental misunderstanding of the language. > > I thought we agreed that "a.b = ..." and "*x = ..." are different in > that the type of "a" has some influence on the access, in order to deem > the following UB. > > * *typedef struct A { int a; } A; > * *typedef struct B { int a; } B; > * *A *x = malloc(sizeof *a); > * *x->a = 0; // access with effective type A and int > * *((B*)x)->a = 0; // I thought we agreed this is UB > * * * * * * * * * *// and committee intent. > > I think *I* am misunderstanding the matter rather than you ![]() Well, we agreed that's one possible resolution. I don't think we agreed that's the Rules As Written. I definitely feel that it's unintuitive. Sorry for that source of confusion. |
|
|||
|
On 07/02/2011 10:37 PM, Johannes Schaub (litb) wrote:
> But that seems wrong, because the aliasing rule says that a write > changes the effective type *for that access* and for all further read > accesses. Only if the object doesn't have a declared type. > So WTF does the committee say!? That's a good question indeed. If you don't mind hearing my opinion instead of the committee's, I find the whole concept of effective types hopelessly underspecified. In particular: * WTF is the declared type of an object? Does a subobject of a declared object, such as a structure member or an array element, have a declared type, or does it not? If not, then why is it OK to read the value of the member without giving it an effective type first, such as in this example: struct S { int x, y; } a; a = (struct S) { 1, 2 }; printf( "%d\n", a.x ); // Oops? Also, why does the footnote mention allocated objects but not members and elements as an example of objects without a declared type? * But if the subobjects do have a declared type, then what happens when the structure or array is the same object as its member or element (which happens when the array has only one element, or the structure has one member and no padding)? Does the object have two declared types at the same time? Or possibly more, for instance when it's a union? (Or do the rules for union members differ from those for structure members and array elements?) * Similarly, if I assign a structure to an allocated object, the effective type of the object becomes the structure type; but do all the subobjects that correspond to structure members acquire the corresponding effective type? If not, then why is it OK to read a member back? * And, in general, when an assignment to an object gives it an effective type, does it also erase the effective type of any overlapping objects that had an effective type from previous assignments? If yes, does that really mean that after I gave an allocated object a structure type by a structure assigment, assigning a new value to one of the members erases the effective type of the big object? * WTF, exactly, does it mean to copy an object "as an array of a character type"? Does it only cover algorithms that provably copy each byte value from one object to the same byte position in the other, by a simple assignment or a chain of such assignments, or does any algorithm count as long as it can be proven to reconstruct the sequence of bytes, even if it involves transforming the byte values, perhaps by some complicated formula such as compression and decompression, encryption and decryption, writing to a file and reading back (as either binary or formatted text), or maybe even dictating to a person and having them enter the values back, under oath? |
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|