Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #30504 > unrolled thread

Initializing a malloc'ed struct whose fields are const with run-time values

Started byNoob <root@127.0.0.1>
First post2013-01-22 16:36 +0100
Last post2013-01-22 20:48 -0800
Articles 20 on this page of 64 — 13 participants

Back to article view | Back to comp.lang.c


Contents

  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 →


#30621 — Re: Initializing a malloc'ed struct whose fields are const with run-time values

FromTim Rentsch <txr@alumni.caltech.edu>
Date2013-01-24 13:58 -0800
SubjectRe: 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]


#30537 — Re: Initializing a malloc'ed struct whose fields are const with run-time values

FromJames Kuyper <jameskuyper@verizon.net>
Date2013-01-22 16:37 -0500
SubjectRe: 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]


#30560 — Re: Initializing a malloc'ed struct whose fields are const with run-time values

FromTim Rentsch <txr@alumni.caltech.edu>
Date2013-01-22 21:22 -0800
SubjectRe: 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]


#30558 — Re: Initializing a malloc'ed struct whose fields are const with run-time values

FromTim Rentsch <txr@alumni.caltech.edu>
Date2013-01-22 21:06 -0800
SubjectRe: 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]


#30562 — Re: Initializing a malloc'ed struct whose fields are const with run-time values

FromIan Collins <ian-news@hotmail.com>
Date2013-01-23 19:55 +1300
SubjectRe: 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]


#30565 — Re: Initializing a malloc'ed struct whose fields are const with run-time values

FromTim Rentsch <txr@alumni.caltech.edu>
Date2013-01-23 00:48 -0800
SubjectRe: 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]


#30567 — Re: Initializing a malloc'ed struct whose fields are const with run-time values

FromIan Collins <ian-news@hotmail.com>
Date2013-01-23 23:06 +1300
SubjectRe: 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]


#30523

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2013-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]


#30527

FromShao Miller <sha0.miller@gmail.com>
Date2013-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]


#30547

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2013-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]


#30551

FromShao Miller <sha0.miller@gmail.com>
Date2013-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]


#30555

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2013-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]


#30559

FromShao Miller <sha0.miller@gmail.com>
Date2013-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]


#30574

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2013-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]


#30526

FromNoob <root@localhost>
Date2013-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]


#30528

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2013-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]


#30531

FromShao Miller <sha0.miller@gmail.com>
Date2013-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]


#30545

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2013-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]


#30535

FromWilliam Ahern <william@wilbur.25thandClement.com>
Date2013-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]


#30553

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2013-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