Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #30504 > unrolled thread
| Started by | Noob <root@127.0.0.1> |
|---|---|
| First post | 2013-01-22 16:36 +0100 |
| Last post | 2013-01-22 20:48 -0800 |
| Articles | 20 on this page of 64 — 13 participants |
Back to article view | Back to comp.lang.c
Initializing a malloc'ed struct whose fields are const with run-time values Noob <root@127.0.0.1> - 2013-01-22 16:36 +0100
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 11:23 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 21:26 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values James Kuyper <jameskuyper@verizon.net> - 2013-01-22 16:41 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values William Ahern <william@wilbur.25thandClement.com> - 2013-01-22 13:25 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 23:17 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 13:09 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Noob <root@127.0.0.1> - 2013-01-23 14:16 +0100
Re: Initializing a malloc'ed struct whose fields are const with run-time values "BartC" <bc@freeuk.com> - 2013-01-23 13:25 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Noob <root@127.0.0.1> - 2013-01-23 15:21 +0100
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 14:56 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Noob <root@127.0.0.1> - 2013-01-23 16:40 +0100
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 18:26 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-23 20:39 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-23 17:14 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ike Naar <ike@sverige.freeshell.org> - 2013-01-22 17:59 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 14:09 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Noob <root@localhost> - 2013-01-22 21:59 +0100
Re: Initializing a malloc'ed struct whose fields are const with run-time values glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2013-01-22 21:19 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 23:47 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 21:05 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 16:15 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-23 09:43 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values William Ahern <william@wilbur.25thandClement.com> - 2013-01-22 13:19 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values William Ahern <william@wilbur.25thandClement.com> - 2013-01-22 13:35 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-23 10:45 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 17:07 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-22 21:29 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 13:54 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-23 17:08 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-24 11:29 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-23 18:26 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-24 14:03 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-23 23:58 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 23:36 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-24 13:55 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-24 02:44 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-23 21:39 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-24 00:54 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-24 17:56 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-24 13:58 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values James Kuyper <jameskuyper@verizon.net> - 2013-01-22 16:37 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-22 21:22 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-22 21:06 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-23 19:55 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-23 00:48 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-23 23:06 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 21:02 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 16:12 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 22:37 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 22:29 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 04:28 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-23 00:07 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 14:04 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Noob <root@localhost> - 2013-01-22 22:10 +0100
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 21:13 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 16:25 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 22:21 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values William Ahern <william@wilbur.25thandClement.com> - 2013-01-22 13:32 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 03:50 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Nick Bowler <nbowler@draconx.ca> - 2013-01-22 21:43 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 03:45 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Keith Thompson <kst-u@mib.org> - 2013-01-24 08:23 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-22 20:48 -0800
Page 3 of 4 — ← Prev page 1 2 [3] 4 Next page →
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2013-01-24 13:58 -0800 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <kfn1udatf9x.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #30617 |
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> Tim Rentsch <txr@alumni.caltech.edu> writes:
>
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> <snip>
>>> More curious to me is that gcc (in conforming mode) permits
>>> this:
>>>
>>> struct toto { const int i; const float f; const void *p; };
>>>
>>> struct toto foo(int i, float f, void *p)
>>> {
>>> return (struct toto){i, f, p};
>>> }
>>>
>>> int bar(struct toto p) { return p.i; }
>>>
>>> int main(void)
>>> {
>>> return bar(foo(1, 2, 0));
>>> }
>>>
>>> but 6.5.2.2 p2 says:
>>>
>>> "Each argument shall have a type such that its value may be
>>> assigned to an object with the unqualified version of the
>>> type of its corresponding parameter."
>>>
>>> The phrase "unqualified version of the type" can't surely be
>>> intended to mean the recursive removal of all type qualifiers.
>>> Elsewhere it simply means that the "top level" qualifiers are
>>> removed. If that's the right interpretation, the call to bar
>>> should be a constraint violation.
>>>
>>> [speculation about why gcc acts as it does] Anyway, either
>>> I'm misreading something or gcc has missed something.
>>
>> [snip] this case also represents an oversight, [and it was
>> expected that such cases would be allowed.] All that remains
>> is making sure what's in the Standard gets updated to reflect
>> that.
>
> One option would be to define function calling in terms of
> initialization but that may have unforeseen consequences.
> Something like
>
> "Each argument shall have a type such that its value may be
> used as a single expression initializer of its corresponding
> parameter."
>
> and later:
>
> "In preparing for the call to a function, the arguments are
> evaluated, and each parameter is initialized using the value
> of the corresponding argument."
Yes, I think something along these lines is the right approach.
> At first glance, all the right wording is there, at least for
> scalar types:
>
> 11 The initializer for a scalar shall be a single expression,
> optionally enclosed in braces. The initial value of the
> object is that of the expression (after conversion); the
> same type constraints and conversions as for simple
> assignment apply, taking the type of the scalar to be the
> unqualified version of its declared type."
>
> but then paragraph 13 surprised me a little:
>
> 13 The initializer for a structure or union object that has
> automatic storage duration shall be either an initializer
> list as described below, or a single expression that has
> compatible structure or union type. In the latter case,
> the initial value of the object, including unnamed
> members, is that of the expression.
>
> This is from the "semantics" section, so for structure and union
> types there is no constraint violation if the types are not
> compatible. Whilst this is an odd anomaly of initialization,
> it's probably unacceptable for function calls -- you really want
> to mandate a diagnostic when the types don't match.
Surely this anomaly, as you call it, is just another oversight,
and the wording in p13 should be changed to be in line with
what everyone expects. That would eliminate any incongruity
with treating function arguments as initializing expressions,
and also remedy the point you identify next.
> Also, on a side issue, the wording about disregarding the type's
> qualifiers is also missing. Obviously
>
> const struct s = (struct s){0};
>
> is supposed to be permitted, so is "struct s" a "compatible
> structure or union type"? Probably. It's not a compatible type,
> but the extra words might be there to suggest that it's only the
> structural part that is to be considered. I'd rather that were
> more explicit, though.
One approach to the second problem would be to use type categories
instead of compatible type, eg,
13 The initializer for a structure or union object that has
automatic storage duration shall be either an initializer
list as described below, or a single expression having
the same type category as that of the structure or union
object. In the latter case, the initial value of the object,
including unnamed members, is that of the expression.
However, that wording by itself doesn't address the need for a
constraint violation for expressions not having the same type
category. (Note: surely it was intended that such cases be
constraint violations -- wasn't it?) Another idea is to change
p13 to have wording along the lines of what is used in p11.
Personally I kind of like the type category idea, but I think
using p11-like wording is more consistent, and so more likely
to be adopted if a change were proposed.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2013-01-22 16:37 -0500 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <50FF0682.10004@verizon.net> |
| In reply to | #30533 |
On 01/22/2013 04:19 PM, William Ahern wrote: > Ian Collins <ian-news@hotmail.com> wrote: ... >> Is that legal? struct toto has const members, so can it be returned by >> value from a function? > > What about foo().f? Does the simple return constitute modification of a > const-qualified lvalue? > > I'm still not convinced that "modifying" a const-qualified member through > assignment of a non-const-qualified aggregate is undefined behaviour. But I > don't know enough about the rules of lvalues to prove it. A struct containing a member that is const-qualified is not modifiable (6.3.2.1p1). It is a constraint violation for an assignment operator to have a left operand which is not a modifiable lvalue (6.5.16p2). Arguments passed to a function (6.5.2.2p7), and values returned by a function (6.8.6.4p3), are both converted "as if by assignment", and I believe are therefore subject to the same constraints.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2013-01-22 21:22 -0800 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <kfn7gn4scbq.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #30537 |
James Kuyper <jameskuyper@verizon.net> writes: > On 01/22/2013 04:19 PM, William Ahern wrote: >> Ian Collins <ian-news@hotmail.com> wrote: > ... >>> Is that legal? struct toto has const members, so can it be returned by >>> value from a function? >> >> What about foo().f? Does the simple return constitute modification of a >> const-qualified lvalue? >> >> I'm still not convinced that "modifying" a const-qualified member through >> assignment of a non-const-qualified aggregate is undefined behaviour. But I >> don't know enough about the rules of lvalues to prove it. > > A struct containing a member that is const-qualified is not modifiable > (6.3.2.1p1). It is a constraint violation for an assignment operator to > have a left operand which is not a modifiable lvalue (6.5.16p2). > Arguments passed to a function (6.5.2.2p7), and values returned by a > function (6.8.6.4p3), are both converted "as if by assignment", and I > believe are therefore subject to the same constraints. Too funny. First, the constraint violation for assignment operators has nothing to do with conversions that are done as part of performing the operation. These aspects appear in different paragraphs and in different types of subsections. Second, 'return' only does such an assignment-like conversion when the type of the return expression differs from the result type of the function.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2013-01-22 21:06 -0800 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <kfnbocgsd28.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #30520 |
Ian Collins <ian-news@hotmail.com> writes:
> Ike Naar wrote:
>>> [snip]
>>
>> And how about returning by value?
>>
>> struct toto foo(int i, float f, void *p)
>> {
>> struct toto res = {i, f, p};
>> return res;
>> }
>
> Is that legal? struct toto has const members, so can it be
> returned by value from a function?
Can you name a constraint or a 'shall' provision that it
violates? I can't find one. If there is no such violation,
then the behavior is well-defined (and I believe that is in
fact the case).
Furthmore this result is more useful than it might appear at
first blush, because such functions can be used as part of
initialization:
struct toto somethin = foo( 0, 3.14, malloc( 97 ) );
Of course there isn't much point for this particular
definition of foo(), but it's easy to imagine other
"constructor" functions that would be quite handy to have
around.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2013-01-23 19:55 +1300 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <am9fraFbgsgU6@mid.individual.net> |
| In reply to | #30558 |
Tim Rentsch wrote:
> Ian Collins <ian-news@hotmail.com> writes:
>
>> Ike Naar wrote:
>>>> [snip]
>>>
>>> And how about returning by value?
>>>
>>> struct toto foo(int i, float f, void *p)
>>> {
>>> struct toto res = {i, f, p};
>>> return res;
>>> }
>>
>> Is that legal? struct toto has const members, so can it be
>> returned by value from a function?
>
> Can you name a constraint or a 'shall' provision that it
> violates? I can't find one. If there is no such violation,
> then the behavior is well-defined (and I believe that is in
> fact the case).
No, I'm not one for remembering where stuff is in the standard... But I
think I (and possibly the Sun compiler writers) took the assignment like
nature of return too literally.
--
Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2013-01-23 00:48 -0800 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <kfnmww0qo8i.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #30562 |
Ian Collins <ian-news@hotmail.com> writes:
> Tim Rentsch wrote:
>> Ian Collins <ian-news@hotmail.com> writes:
>>
>>> Ike Naar wrote:
>>>>> [snip]
>>>>
>>>> And how about returning by value?
>>>>
>>>> struct toto foo(int i, float f, void *p)
>>>> {
>>>> struct toto res = {i, f, p};
>>>> return res;
>>>> }
>>>
>>> Is that legal? struct toto has const members, so can it be
>>> returned by value from a function?
>>
>> Can you name a constraint or a 'shall' provision that it
>> violates? I can't find one. If there is no such violation,
>> then the behavior is well-defined (and I believe that is in
>> fact the case).
>
> No, I'm not one for remembering where stuff is in the
> standard...
Sorry, what I said came out sounding accusatory and I
didn't mean it that way. All I meant was, this question
is what should be considered to resolve the issue.
> But I think I (and possibly the Sun compiler writers) took
> the assignment like nature of return too literally.
Actually my first reaction was similar to that, even though
I wasn't thinking specifically of assignment. Upon further
consideration though allowing it makes more sense, because
what's happening is more like an initialization than an
assignment, and initializers certainly are allowed for
const-qualified types.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2013-01-23 23:06 +1300 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <am9r0aFbgsgU10@mid.individual.net> |
| In reply to | #30565 |
Tim Rentsch wrote:
> Ian Collins <ian-news@hotmail.com> writes:
>
>> Tim Rentsch wrote:
>>> Ian Collins <ian-news@hotmail.com> writes:
>>>
>>>> Ike Naar wrote:
>>>>>> [snip]
>>>>>
>>>>> And how about returning by value?
>>>>>
>>>>> struct toto foo(int i, float f, void *p)
>>>>> {
>>>>> struct toto res = {i, f, p};
>>>>> return res;
>>>>> }
>>>>
>>>> Is that legal? struct toto has const members, so can it be
>>>> returned by value from a function?
>>>
>>> Can you name a constraint or a 'shall' provision that it
>>> violates? I can't find one. If there is no such violation,
>>> then the behavior is well-defined (and I believe that is in
>>> fact the case).
>>
>> No, I'm not one for remembering where stuff is in the
>> standard...
>
> Sorry, what I said came out sounding accusatory and I
> didn't mean it that way. All I meant was, this question
> is what should be considered to resolve the issue.
No offense taken.
>> But I think I (and possibly the Sun compiler writers) took
>> the assignment like nature of return too literally.
>
> Actually my first reaction was similar to that, even though
> I wasn't thinking specifically of assignment. Upon further
> consideration though allowing it makes more sense, because
> what's happening is more like an initialization than an
> assignment, and initializers certainly are allowed for
> const-qualified types.
Now I've taken the time to check 6.8.6.4p3 I think the wording
"the value of the expression is returned to the caller as the value of
the function call expression"
is clear enough. I might ask the now Oracle compiler people why they
consider it an error.
--
Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-01-22 21:02 +0000 |
| Message-ID | <0.9cf74e9e26ab50dd0add.20130122210219GMT.87pq0x3p9g.fsf@bsb.me.uk> |
| In reply to | #30511 |
Ike Naar <ike@sverige.freeshell.org> writes:
> On 2013-01-22, Noob <root@127.0.0.1> wrote:
>> #include <stdlib.h>
>> #include <string.h>
>> struct toto *foo(int i, float f, void *p)
>> {
>> struct toto s = { i, f, p };
>> struct toto *res = malloc(sizeof *res);
>> if (res != NULL) memcpy(res, &s, sizeof s);
>
> Why memcpy instead of an assignment?
> if (res != NULL) *res = s;
Because it'll provoke an error! The struct's members are const so the
assignment is a constraint violation.
>> return res;
>> }
>
> And how about returning by value?
>
> struct toto foo(int i, float f, void *p)
> {
> struct toto res = {i, f, p};
> return res;
> }
This limits what you can do with it for the same reason. You can't
assign a strust toto because of its const members.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-22 16:12 -0500 |
| Message-ID | <kdmvbj$i54$1@dont-email.me> |
| In reply to | #30523 |
On 1/22/2013 16:02, Ben Bacarisse wrote:
> Ike Naar <ike@sverige.freeshell.org> writes:
>
>> On 2013-01-22, Noob <root@127.0.0.1> wrote:
>>> #include <stdlib.h>
>>> #include <string.h>
>>> struct toto *foo(int i, float f, void *p)
>>> {
>>> struct toto s = { i, f, p };
>>> struct toto *res = malloc(sizeof *res);
>>> if (res != NULL) memcpy(res, &s, sizeof s);
>>
>> Why memcpy instead of an assignment?
>> if (res != NULL) *res = s;
>
> Because it'll provoke an error! The struct's members are const so the
> assignment is a constraint violation.
>
>>> return res;
>>> }
>>
>> And how about returning by value?
>>
>> struct toto foo(int i, float f, void *p)
>> {
>> struct toto res = {i, f, p};
>> return res;
>> }
>
> This limits what you can do with it for the same reason. You can't
> assign a strust toto because of its const members.
>
Are you sure about that? 'res' undergoes lvalue conversion and no
longer has qualified type.
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-01-22 22:37 +0000 |
| Message-ID | <0.79f4d99d1221a429891e.20130122223749GMT.87vcao3kua.fsf@bsb.me.uk> |
| In reply to | #30527 |
Shao Miller <sha0.miller@gmail.com> writes:
> On 1/22/2013 16:02, Ben Bacarisse wrote:
>> Ike Naar <ike@sverige.freeshell.org> writes:
>>
>>> On 2013-01-22, Noob <root@127.0.0.1> wrote:
<snipping has lost the fact that struct toto has const qualified members>
>>> And how about returning by value?
>>>
>>> struct toto foo(int i, float f, void *p)
>>> {
>>> struct toto res = {i, f, p};
>>> return res;
>>> }
>>
>> This limits what you can do with it for the same reason. You can't
>> assign a strust toto because of its const members.
>
> Are you sure about that? 'res' undergoes lvalue conversion and no
> longer has qualified type.
Am I sure about what? I think you know that you can't assign to a
struct toto object, so are you saying if I am sure that returning this
struct type limits what one can do with it?
A pointer to allocated storage is more flexible (because you have
control over the lifetime) and the function as given is almost identical
to a simple expression: (struct toto){i, f, p}.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-22 22:29 -0500 |
| Message-ID | <kdnlet$b13$1@dont-email.me> |
| In reply to | #30547 |
On 1/22/2013 17:37, Ben Bacarisse wrote:
> Shao Miller <sha0.miller@gmail.com> writes:
>
>> On 1/22/2013 16:02, Ben Bacarisse wrote:
>>> Ike Naar <ike@sverige.freeshell.org> writes:
>>>
>>>> On 2013-01-22, Noob <root@127.0.0.1> wrote:
>
> <snipping has lost the fact that struct toto has const qualified members>
>
>>>> And how about returning by value?
>>>>
>>>> struct toto foo(int i, float f, void *p)
>>>> {
>>>> struct toto res = {i, f, p};
>>>> return res;
>>>> }
>>>
>>> This limits what you can do with it for the same reason. You can't
>>> assign a strust toto because of its const members.
>>
>> Are you sure about that? 'res' undergoes lvalue conversion and no
>> longer has qualified type.
>
> Am I sure about what? I think you know that you can't assign to a
> struct toto object, so are you saying if I am sure that returning this
> struct type limits what one can do with it?
>
> A pointer to allocated storage is more flexible (because you have
> control over the lifetime) and the function as given is almost identical
> to a simple expression: (struct toto){i, f, p}.
>
Sorry, Ben. I've approached this in my head in four ways:
1. (Non-preferred; must be wrong because of lvalue conversion)
'res', before lvalue conversion, has a compatible type with the return
type of the function, so "the value is converted as if by assignment to
an object having the return type of the function" does not apply, and
"the value of" 'res' "is returned to the caller as the value of the
function call expression"
2. (More preferred than #1)
'res' undergoes lvalue conversion and yields an unqualified type with
the value. This type is incompatible with the return type of the
function, so "the value is converted as if by assignment to an object
having the return type of the function", but the footnote reminds us
that "The return statement is not an assignment." So there might be one
or more differences.
Looking at 6.5.16p1, it cannot apply as it is, since "an object having
the return type of the function" isn't the same as "a modifiable lvalue
designating an object having the return type of the function." We need
to twist it a bit. There's also no direct discussion of conversion for
the RHS operand... That's "2 strikes". So what if we drop that bit and
move on to 6.5.16.1?
Alternatively to moving on, there's a constraint violation (as you've
mentioned) based on "modifiable". But why pick "modifiable" and not
"lvalue"? :)
Looking at 6.5.16.1p1, the return type of 'foo' and the unqualified type
of rvalue from 'res' satisfy the second bullet. Then p2 does indeed
refer back to 6.5.16p2, but only insofar as the type of the
assignment-expression. The type of the assignment-expression so happens
to be the unqualified type of 'struct toto', which is the same type as
the rvalue from 'res', so there's actually no conversion for the rvalue
from 'res'.
3. (Preferred)
6.7.3p4: "The properties associated with qualified types are meaningful
only for expressions that are lvalues.132)" But "the value of the
function call expression" is never an lvalue, so perhaps the return type
of a function is never qualified.
In that case, the lvalue conversion of 'res' yields an rvalue whose type
is already compatible with the return type, so "the value is converted
as if by assignment to an object having the return type of the function"
does not apply, and "the value of" 'res' "is returned to the caller as
the value of the function call expression".
If #3 is true, the wording could be a bit clearer.
4. (D'oh!)
Unfortunately, I don't think any of #1, #2, #3 is true, due to 6.7.3p9:
"...If the specification of a function type includes any type
qualifiers, the behavior is undefined.136)" (Since at least C90.) I
think that means that 'foo' can't be declared that way.
(This is Ike Naar's 'foo', obviously. Citations relative to N1570.)
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-01-23 04:28 +0000 |
| Message-ID | <0.e251726b430fb93a3af3.20130123042854GMT.87ehhc34l5.fsf@bsb.me.uk> |
| In reply to | #30551 |
Shao Miller <sha0.miller@gmail.com> writes:
> On 1/22/2013 17:37, Ben Bacarisse wrote:
>> Shao Miller <sha0.miller@gmail.com> writes:
>>
>>> On 1/22/2013 16:02, Ben Bacarisse wrote:
>>>> Ike Naar <ike@sverige.freeshell.org> writes:
>>>>
>>>>> On 2013-01-22, Noob <root@127.0.0.1> wrote:
>>
>> <snipping has lost the fact that struct toto has const qualified members>
>>
>>>>> And how about returning by value?
>>>>>
>>>>> struct toto foo(int i, float f, void *p)
>>>>> {
>>>>> struct toto res = {i, f, p};
>>>>> return res;
>>>>> }
>>>>
>>>> This limits what you can do with it for the same reason. You can't
>>>> assign a strust toto because of its const members.
>>>
>>> Are you sure about that? 'res' undergoes lvalue conversion and no
>>> longer has qualified type.
>>
>> Am I sure about what? I think you know that you can't assign to a
>> struct toto object, so are you saying if I am sure that returning this
>> struct type limits what one can do with it?
>>
>> A pointer to allocated storage is more flexible (because you have
>> control over the lifetime) and the function as given is almost identical
>> to a simple expression: (struct toto){i, f, p}.
>>
>
> Sorry, Ben. I've approached this in my head in four ways:
>
> 1. (Non-preferred; must be wrong because of lvalue conversion)
>
> 'res', before lvalue conversion, has a compatible type with the return
> type of the function, so "the value is converted as if by assignment
> to an object having the return type of the function" does not apply,
> and "the value of" 'res' "is returned to the caller as the value of
> the function call expression"
>
> 2. (More preferred than #1)
>
> 'res' undergoes lvalue conversion and yields an unqualified type with
> the value. This type is incompatible with the return type of the
> function, so "the value is converted as if by assignment to an object
> having the return type of the function", but the footnote reminds us
> that "The return statement is not an assignment." So there might be
> one or more differences.
>
> Looking at 6.5.16p1, it cannot apply as it is, since "an object having
> the return type of the function" isn't the same as "a modifiable
> lvalue designating an object having the return type of the function."
> We need to twist it a bit. There's also no direct discussion of
> conversion for the RHS operand... That's "2 strikes". So what if we
> drop that bit and move on to 6.5.16.1?
>
> Alternatively to moving on, there's a constraint violation (as you've
> mentioned) based on "modifiable". But why pick "modifiable" and not
> "lvalue"? :)
>
> Looking at 6.5.16.1p1, the return type of 'foo' and the unqualified
> type of rvalue from 'res' satisfy the second bullet. Then p2 does
> indeed refer back to 6.5.16p2, but only insofar as the type of the
> assignment-expression. The type of the assignment-expression so
> happens to be the unqualified type of 'struct toto', which is the same
> type as the rvalue from 'res', so there's actually no conversion for
> the rvalue from 'res'.
>
> 3. (Preferred)
>
> 6.7.3p4: "The properties associated with qualified types are
> meaningful only for expressions that are lvalues.132)" But "the value
> of the function call expression" is never an lvalue, so perhaps the
> return type of a function is never qualified.
>
> In that case, the lvalue conversion of 'res' yields an rvalue whose
> type is already compatible with the return type, so "the value is
> converted as if by assignment to an object having the return type of
> the function" does not apply, and "the value of" 'res' "is returned to
> the caller as the value of the function call expression".
>
> If #3 is true, the wording could be a bit clearer.
>
> 4. (D'oh!)
>
> Unfortunately, I don't think any of #1, #2, #3 is true, due to
> 6.7.3p9: "...If the specification of a function type includes any type
> qualifiers, the behavior is undefined.136)" (Since at least C90.) I
> think that means that 'foo' can't be declared that way.
You wrote eight paragraphs of stuff that you don't think is true?
How do you interpret 6.7.3 p9 so that the function above is undefined,
but const char *int_to_str(int) is not?
> (This is Ike Naar's 'foo', obviously. Citations relative to N1570.)
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-23 00:07 -0500 |
| Message-ID | <kdnr7f$4g1$1@dont-email.me> |
| In reply to | #30555 |
On 1/22/2013 23:28, Ben Bacarisse wrote:
> Shao Miller <sha0.miller@gmail.com> writes:
>
>> On 1/22/2013 17:37, Ben Bacarisse wrote:
>>> Shao Miller <sha0.miller@gmail.com> writes:
>>>
>>>> On 1/22/2013 16:02, Ben Bacarisse wrote:
>>>>> Ike Naar <ike@sverige.freeshell.org> writes:
>>>>>
>>>>>> On 2013-01-22, Noob <root@127.0.0.1> wrote:
>>>
>>> <snipping has lost the fact that struct toto has const qualified members>
>>>
>>>>>> And how about returning by value?
>>>>>>
>>>>>> struct toto foo(int i, float f, void *p)
>>>>>> {
>>>>>> struct toto res = {i, f, p};
>>>>>> return res;
>>>>>> }
>>>>>
>>>>> This limits what you can do with it for the same reason. You can't
>>>>> assign a strust toto because of its const members.
>>>>
>>>> Are you sure about that? 'res' undergoes lvalue conversion and no
>>>> longer has qualified type.
>>>
>>> Am I sure about what? I think you know that you can't assign to a
>>> struct toto object, so are you saying if I am sure that returning this
>>> struct type limits what one can do with it?
>>>
>>> A pointer to allocated storage is more flexible (because you have
>>> control over the lifetime) and the function as given is almost identical
>>> to a simple expression: (struct toto){i, f, p}.
>>>
>>
>> Sorry, Ben. I've approached this in my head in four ways:
>>
>> 1. (Non-preferred; must be wrong because of lvalue conversion)
>>
>> 'res', before lvalue conversion, has a compatible type with the return
>> type of the function, so "the value is converted as if by assignment
>> to an object having the return type of the function" does not apply,
>> and "the value of" 'res' "is returned to the caller as the value of
>> the function call expression"
>>
>> 2. (More preferred than #1)
>>
>> 'res' undergoes lvalue conversion and yields an unqualified type with
>> the value. This type is incompatible with the return type of the
>> function, so "the value is converted as if by assignment to an object
>> having the return type of the function", but the footnote reminds us
>> that "The return statement is not an assignment." So there might be
>> one or more differences.
>>
>> Looking at 6.5.16p1, it cannot apply as it is, since "an object having
>> the return type of the function" isn't the same as "a modifiable
>> lvalue designating an object having the return type of the function."
>> We need to twist it a bit. There's also no direct discussion of
>> conversion for the RHS operand... That's "2 strikes". So what if we
>> drop that bit and move on to 6.5.16.1?
>>
>> Alternatively to moving on, there's a constraint violation (as you've
>> mentioned) based on "modifiable". But why pick "modifiable" and not
>> "lvalue"? :)
>>
>> Looking at 6.5.16.1p1, the return type of 'foo' and the unqualified
>> type of rvalue from 'res' satisfy the second bullet. Then p2 does
>> indeed refer back to 6.5.16p2, but only insofar as the type of the
>> assignment-expression. The type of the assignment-expression so
>> happens to be the unqualified type of 'struct toto', which is the same
>> type as the rvalue from 'res', so there's actually no conversion for
>> the rvalue from 'res'.
>>
>> 3. (Preferred)
>>
>> 6.7.3p4: "The properties associated with qualified types are
>> meaningful only for expressions that are lvalues.132)" But "the value
>> of the function call expression" is never an lvalue, so perhaps the
>> return type of a function is never qualified.
>>
>> In that case, the lvalue conversion of 'res' yields an rvalue whose
>> type is already compatible with the return type, so "the value is
>> converted as if by assignment to an object having the return type of
>> the function" does not apply, and "the value of" 'res' "is returned to
>> the caller as the value of the function call expression".
>>
>> If #3 is true, the wording could be a bit clearer.
>>
>> 4. (D'oh!)
>>
>> Unfortunately, I don't think any of #1, #2, #3 is true, due to
>> 6.7.3p9: "...If the specification of a function type includes any type
>> qualifiers, the behavior is undefined.136)" (Since at least C90.) I
>> think that means that 'foo' can't be declared that way.
>
> You wrote eight paragraphs of stuff that you don't think is true?
>
Well I was hopeful for #3, but seemed to recall having previously read
some other bit of Standard text contradicting it. When I went looking,
I came across 6.7.3p9 and it looked like it was the antagonist. Perhaps
that wasn't it, after all.
> How do you interpret 6.7.3 p9 so that the function above is undefined,
> but const char *int_to_str(int) is not?
>
>> (This is Ike Naar's 'foo', obviously. Citations relative to N1570.)
>
Well I was thinking along the lines of the qualification of the return
type's type category, but maybe not...
Have you any thoughts about #1, #2, #3?
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-01-23 14:04 +0000 |
| Message-ID | <0.b1d1296e8b8710c29a0e.20130123140415GMT.87txq80zds.fsf@bsb.me.uk> |
| In reply to | #30559 |
Shao Miller <sha0.miller@gmail.com> writes:
> On 1/22/2013 23:28, Ben Bacarisse wrote:
>> Shao Miller <sha0.miller@gmail.com> writes:
>>
>>> On 1/22/2013 17:37, Ben Bacarisse wrote:
>>>> Shao Miller <sha0.miller@gmail.com> writes:
>>>>
>>>>> On 1/22/2013 16:02, Ben Bacarisse wrote:
>>>>>> Ike Naar <ike@sverige.freeshell.org> writes:
>>>>>>
>>>>>>> On 2013-01-22, Noob <root@127.0.0.1> wrote:
>>>>
>>>> <snipping has lost the fact that struct toto has const qualified members>
>>>>
>>>>>>> And how about returning by value?
>>>>>>>
>>>>>>> struct toto foo(int i, float f, void *p)
>>>>>>> {
>>>>>>> struct toto res = {i, f, p};
>>>>>>> return res;
>>>>>>> }
>>>>>>
>>>>>> This limits what you can do with it for the same reason. You can't
>>>>>> assign a strust toto because of its const members.
>>>>>
>>>>> Are you sure about that? 'res' undergoes lvalue conversion and no
>>>>> longer has qualified type.
>>>>
>>>> Am I sure about what? I think you know that you can't assign to a
>>>> struct toto object, so are you saying if I am sure that returning this
>>>> struct type limits what one can do with it?
>>>>
>>>> A pointer to allocated storage is more flexible (because you have
>>>> control over the lifetime) and the function as given is almost identical
>>>> to a simple expression: (struct toto){i, f, p}.
>>>>
>>>
>>> Sorry, Ben. I've approached this in my head in four ways:
>>>
>>> 1. (Non-preferred; must be wrong because of lvalue conversion)
>>>
>>> 'res', before lvalue conversion, has a compatible type with the return
>>> type of the function, so "the value is converted as if by assignment
>>> to an object having the return type of the function" does not apply,
>>> and "the value of" 'res' "is returned to the caller as the value of
>>> the function call expression"
>>>
>>> 2. (More preferred than #1)
>>>
>>> 'res' undergoes lvalue conversion and yields an unqualified type with
>>> the value. This type is incompatible with the return type of the
>>> function, so "the value is converted as if by assignment to an object
>>> having the return type of the function", but the footnote reminds us
>>> that "The return statement is not an assignment." So there might be
>>> one or more differences.
>>>
>>> Looking at 6.5.16p1, it cannot apply as it is, since "an object having
>>> the return type of the function" isn't the same as "a modifiable
>>> lvalue designating an object having the return type of the function."
>>> We need to twist it a bit. There's also no direct discussion of
>>> conversion for the RHS operand... That's "2 strikes". So what if we
>>> drop that bit and move on to 6.5.16.1?
>>>
>>> Alternatively to moving on, there's a constraint violation (as you've
>>> mentioned) based on "modifiable". But why pick "modifiable" and not
>>> "lvalue"? :)
>>>
>>> Looking at 6.5.16.1p1, the return type of 'foo' and the unqualified
>>> type of rvalue from 'res' satisfy the second bullet. Then p2 does
>>> indeed refer back to 6.5.16p2, but only insofar as the type of the
>>> assignment-expression. The type of the assignment-expression so
>>> happens to be the unqualified type of 'struct toto', which is the same
>>> type as the rvalue from 'res', so there's actually no conversion for
>>> the rvalue from 'res'.
>>>
>>> 3. (Preferred)
>>>
>>> 6.7.3p4: "The properties associated with qualified types are
>>> meaningful only for expressions that are lvalues.132)" But "the value
>>> of the function call expression" is never an lvalue, so perhaps the
>>> return type of a function is never qualified.
>>>
>>> In that case, the lvalue conversion of 'res' yields an rvalue whose
>>> type is already compatible with the return type, so "the value is
>>> converted as if by assignment to an object having the return type of
>>> the function" does not apply, and "the value of" 'res' "is returned to
>>> the caller as the value of the function call expression".
>>>
>>> If #3 is true, the wording could be a bit clearer.
>>>
>>> 4. (D'oh!)
>>>
>>> Unfortunately, I don't think any of #1, #2, #3 is true, due to
>>> 6.7.3p9: "...If the specification of a function type includes any type
>>> qualifiers, the behavior is undefined.136)" (Since at least C90.) I
>>> think that means that 'foo' can't be declared that way.
>>
>> You wrote eight paragraphs of stuff that you don't think is true?
>>
>
> Well I was hopeful for #3, but seemed to recall having previously read
> some other bit of Standard text contradicting it. When I went
> looking, I came across 6.7.3p9 and it looked like it was the
> antagonist. Perhaps that wasn't it, after all.
>
>> How do you interpret 6.7.3 p9 so that the function above is undefined,
>> but const char *int_to_str(int) is not?
>>
>>> (This is Ike Naar's 'foo', obviously. Citations relative to N1570.)
>
> Well I was thinking along the lines of the qualification of the return
> type's type category, but maybe not...
I don't know what a type's type category is so I can't comment here.
> Have you any thoughts about #1, #2, #3?
The return type is the same as that of the function so no conversion
takes place. The value of res is the value returned. It does not seem
to be complicated to me.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Noob <root@localhost> |
|---|---|
| Date | 2013-01-22 22:10 +0100 |
| Message-ID | <50ff0051$0$2273$426a34cc@news.free.fr> |
| In reply to | #30511 |
Ike Naar wrote:
> On 2013-01-22, Noob wrote:
>> #include <stdlib.h>
>> #include <string.h>
>> struct toto *foo(int i, float f, void *p)
>> {
>> struct toto s = { i, f, p };
>> struct toto *res = malloc(sizeof *res);
>> if (res != NULL) memcpy(res, &s, sizeof s);
>
> Why memcpy instead of an assignment?
> if (res != NULL) *res = s;
Right... I'll have to try that, and see what gcc thinks.
> And how about returning by value?
>
> struct toto foo(int i, float f, void *p)
> {
> struct toto res = {i, f, p};
> return res;
> }
This won't work for me, I have to manage the struct's
lifetime by hand, using dynamic allocation. (See my reply
to Shao for a complete description.)
Regards.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-01-22 21:13 +0000 |
| Message-ID | <0.7432cc83d523a65ab134.20130122211350GMT.87ehhc53ap.fsf@bsb.me.uk> |
| In reply to | #30504 |
Noob <root@127.0.0.1> writes:
> Is it possible, in standard C89 and C99, to initialize a
> struct whose fields are const with values only known at
> run-time?
>
> For example, consider:
>
> struct toto { const int i; const float f; const void *p; };
>
> Is it possible to portably implement:
>
> struct toto *foo(int i, float f, void *p);
>
> which allocates space for a "struct toto", initializes it
> with i, f, p and returns the address of this struct?
>
> The best I could come up with is:
>
> #include <stdlib.h>
> #include <string.h>
> struct toto *foo(int i, float f, void *p)
> {
> struct toto s = { i, f, p };
> struct toto *res = malloc(sizeof *res);
> if (res != NULL) memcpy(res, &s, sizeof s);
> return res;
> }
>
> which has several defects:
>
> 1) Apparently, C89 does not allow one to use elements "not computable
> at load time" in an initialization list. However, it is allowed both
> in C99 (right?) and in gnu89.
Yes, it's fine in C99 and later. I'm not sure about gnu89 but I would
not be surprised.
BTW, in C99 you don't even need a declaration:
if (res != NULL) memcpy(res, &(struct toto){i, f, p}, sizeof *res);
> 2) I'm not sure it is well-defined to memcpy stuff into some const
> fields. Does it tickle the cranky UB gods?
No, I think it's fine. You are not modifying anything that is const.
malloced storage has no declared type and the memcpy probably makes the
effective type a byte array.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-22 16:25 -0500 |
| Message-ID | <kdn050$nbj$1@dont-email.me> |
| In reply to | #30528 |
On 1/22/2013 16:13, Ben Bacarisse wrote:
> Noob <root@127.0.0.1> writes:
>
>> Is it possible, in standard C89 and C99, to initialize a
>> struct whose fields are const with values only known at
>> run-time?
>>
>> For example, consider:
>>
>> struct toto { const int i; const float f; const void *p; };
>>
>> Is it possible to portably implement:
>>
>> struct toto *foo(int i, float f, void *p);
>>
>> which allocates space for a "struct toto", initializes it
>> with i, f, p and returns the address of this struct?
>>
>> The best I could come up with is:
>>
>> #include <stdlib.h>
>> #include <string.h>
>> struct toto *foo(int i, float f, void *p)
>> {
>> struct toto s = { i, f, p };
>> struct toto *res = malloc(sizeof *res);
>> if (res != NULL) memcpy(res, &s, sizeof s);
>> return res;
>> }
>>
>> which has several defects:
>>
>> 1) Apparently, C89 does not allow one to use elements "not computable
>> at load time" in an initialization list. However, it is allowed both
>> in C99 (right?) and in gnu89.
>
> Yes, it's fine in C99 and later. I'm not sure about gnu89 but I would
> not be surprised.
>
Oops. To Noob: Sorry about providing the wrong answer for this one,
earlier. I hope the rest of that post helped.
> BTW, in C99 you don't even need a declaration:
>
> if (res != NULL) memcpy(res, &(struct toto){i, f, p}, sizeof *res);
>
>> 2) I'm not sure it is well-defined to memcpy stuff into some const
>> fields. Does it tickle the cranky UB gods?
>
> No, I think it's fine. You are not modifying anything that is const.
> malloced storage has no declared type and the memcpy probably makes the
> effective type a byte array.
>
To Ben: I think the effective type would be 'struct toto', as 'memcpy'
is included in 6.5p6.
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-01-22 22:21 +0000 |
| Message-ID | <0.d2e7f56aa0cd14ff0996.20130122222150GMT.871udc505d.fsf@bsb.me.uk> |
| In reply to | #30531 |
Shao Miller <sha0.miller@gmail.com> writes: > On 1/22/2013 16:13, Ben Bacarisse wrote: >> Noob <root@127.0.0.1> writes: <snip> >>> 2) I'm not sure it is well-defined to memcpy stuff into some const >>> fields. Does it tickle the cranky UB gods? >> >> No, I think it's fine. You are not modifying anything that is const. >> malloced storage has no declared type and the memcpy probably makes the >> effective type a byte array. > > To Ben: I think the effective type would be 'struct toto', as 'memcpy' > is included in 6.5p6. Interesting! My recollection was that memcpy would treat the destination as a char array but would then set the effective type for subsequent accesses, but the text says it sets the effective type "for that access and for subsequent accesses". However, I think the conclusion is still valid. To be more specific, I think the effective type is a red herring -- I don't think it matters when determining what can and can't be modified here. The closest approach to UB that I can find is this (7.1.4 p1): "Each of the following statements applies unless explicitly stated otherwise in the detailed descriptions that follow: If an argument to a function has an invalid value (such as [...] a pointer to non-modifiable storage when the corresponding parameter is not const-qualified) ..." But that does not apply here -- the argument is a pointer to modifiable storage no matter what it's (effective) type is about to become. Of course, there may be some other reason why it's UB, but I can't see one. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | William Ahern <william@wilbur.25thandClement.com> |
|---|---|
| Date | 2013-01-22 13:32 -0800 |
| Message-ID | <e4d3t9-6br.ln1@wilbur.25thandClement.com> |
| In reply to | #30528 |
Ben Bacarisse <ben.usenet@bsb.me.uk> wrote: > Noob <root@127.0.0.1> writes: <snip> > > 2) I'm not sure it is well-defined to memcpy stuff into some const > > fields. Does it tickle the cranky UB gods? > No, I think it's fine. You are not modifying anything that is const. > malloced storage has no declared type and the memcpy probably makes the > effective type a byte array. C99 (N1256) 6.5p6: If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one. I guess the effective type arises only after memcpy completes.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-01-23 03:50 +0000 |
| Message-ID | <0.eca86cfb8d6573d9a86a.20130123035028GMT.87k3r436d7.fsf@bsb.me.uk> |
| In reply to | #30535 |
William Ahern <william@wilbur.25thandClement.com> writes: > Ben Bacarisse <ben.usenet@bsb.me.uk> wrote: >> Noob <root@127.0.0.1> writes: > <snip> >> > 2) I'm not sure it is well-defined to memcpy stuff into some const >> > fields. Does it tickle the cranky UB gods? > >> No, I think it's fine. You are not modifying anything that is const. >> malloced storage has no declared type and the memcpy probably makes the >> effective type a byte array. > > C99 (N1256) 6.5p6: > > If a value is copied into an object having no declared type using > memcpy or memmove, or is copied as an array of character type, then > the effective type of the modified object for that access and for > subsequent accesses that do not modify the value is the effective > type of the object from which the value is copied, if it has one. > > I guess the effective type arises only after memcpy completes. I'd say that "for that access and for subsequent accesses" includes the memcpy itself, though my memory of that paragraph was as you describe -- some sort of byte array copy and only subsequently a new effective type. Anyway, I suspect the effective type is a red herring. I don't see any problems arising from this aspect of the code. -- Ben.
[toc] | [prev] | [next] | [standalone]
Page 3 of 4 — ← Prev page 1 2 [3] 4 Next page →
Back to top | Article view | comp.lang.c
csiph-web