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


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

sizeof object got by dereferencing uniniitalized pointer

Started by"V.Subramanian, India" <subramanian100in@yahoo.com>
First post2019-11-28 05:20 -0800
Last post2019-11-30 15:28 -0800
Articles 20 on this page of 35 — 12 participants

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


Contents

  sizeof object got by dereferencing uniniitalized pointer "V.Subramanian, India" <subramanian100in@yahoo.com> - 2019-11-28 05:20 -0800
    Re: sizeof object got by dereferencing uniniitalized pointer Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2019-11-28 05:37 -0800
      Re: sizeof object got by dereferencing uniniitalized pointer mark.bluemel@gmail.com - 2019-11-28 05:59 -0800
        Re: sizeof object got by dereferencing uniniitalized pointer David Brown <david.brown@hesbynett.no> - 2019-11-28 15:51 +0100
          Re: sizeof object got by dereferencing uniniitalized pointer Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2019-11-28 07:27 -0800
            Re: sizeof object got by dereferencing uniniitalized pointer Herbert Rosenau <nospam@hrosenau.de> - 2019-11-28 17:28 +0100
              Re: sizeof object got by dereferencing uniniitalized pointer Thiago Adams <thiago.adams@gmail.com> - 2019-11-28 08:51 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-28 17:36 +0000
                  Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-28 16:37 -0800
                    Re: sizeof object got by dereferencing uniniitalized pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-29 01:27 +0000
                      Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-28 17:47 -0800
                        Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-28 21:16 -0500
                          Re: sizeof object got by dereferencing uniniitalized pointer Keith Thompson <kst-u@mib.org> - 2019-11-29 00:38 -0800
                            Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-29 09:03 -0500
                              Re: sizeof object got by dereferencing uniniitalized pointer Keith Thompson <kst-u@mib.org> - 2019-11-29 13:15 -0800
                                Re: sizeof object got by dereferencing uniniitalized pointer Keith Thompson <kst-u@mib.org> - 2019-11-29 13:38 -0800
                            Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-29 07:09 -0800
                          Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-29 06:10 -0800
                            Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-29 11:12 -0500
                              Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-12-01 09:32 -0800
                      Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-29 07:39 -0800
                        Re: sizeof object got by dereferencing uniniitalized pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-29 22:00 +0000
                          Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-29 22:40 -0500
                            Re: sizeof object got by dereferencing uniniitalized pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-30 11:19 +0000
                              Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-30 09:01 -0500
                          Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-12-01 10:28 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-28 12:49 -0500
                  Re: sizeof object got by dereferencing uniniitalized pointer Thiago Adams <thiago.adams@gmail.com> - 2019-11-28 11:26 -0800
                    Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-28 17:19 -0500
                      Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-28 17:26 -0800
                  Re: sizeof object got by dereferencing uniniitalized pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-28 22:34 +0000
            Re: sizeof object got by dereferencing uniniitalized pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-28 17:34 +0000
        You gotta wonder why people say things like this! (Was: sizeof object got by dereferencing uniniitalized pointer) gazelle@shell.xmission.com (Kenny McCormack) - 2019-11-28 17:19 +0000
      Re: sizeof object got by dereferencing uniniitalized pointer Keith Thompson <kst-u@mib.org> - 2019-11-28 14:55 -0800
        Re: sizeof object got by dereferencing uniniitalized pointer "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2019-11-30 15:28 -0800

Page 1 of 2  [1] 2  Next page →


#148186 — sizeof object got by dereferencing uniniitalized pointer

From"V.Subramanian, India" <subramanian100in@yahoo.com>
Date2019-11-28 05:20 -0800
Subjectsizeof object got by dereferencing uniniitalized pointer
Message-ID<21e377ab-2a49-4f7e-bc18-72f1cee63204@googlegroups.com>
Hi,
I was trying to solve the questions related to pointers at the
following site:

https://www.geeksforgeeks.org/c-language-2-gq/advanced-pointer-c-gq/

The following is the second question:

Assume sizeof an integer and a pointer is 4 byte. Output?

#include <stdio.h>

#define R 10
#define C 20
 
int main()
{
   int (*p)[R][C];
   printf("%d",  sizeof(*p));
   getchar();
   return 0;
}

In this program, I thought sizeof(*p) is wrong because 'p' is not.
initialized and we cannot dereference p.
 However the answer was given as 800

Am I wrong ? Please explain.

Thanks
V.Subramanian

[toc] | [next] | [standalone]


#148187

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2019-11-28 05:37 -0800
Message-ID<9d5ee6d4-607b-405f-83d9-afbe2b073cac@googlegroups.com>
In reply to#148186
On Thursday, 28 November 2019 13:20:59 UTC, V.Subramanian, India  wrote:
> Hi,
> I was trying to solve the questions related to pointers at the
> following site:
> 
> https://www.geeksforgeeks.org/c-language-2-gq/advanced-pointer-c-gq/
> 
> The following is the second question:
> 
> Assume sizeof an integer and a pointer is 4 byte. Output?
> 
> #include <stdio.h>
> 
> #define R 10
> #define C 20
>  
> int main()
> {
>    int (*p)[R][C];
>    printf("%d",  sizeof(*p));
>    getchar();
>    return 0;
> }
> 
> In this program, I thought sizeof(*p) is wrong because 'p' is not.
> initialized and we cannot dereference p.
>  However the answer was given as 800
> 
> Am I wrong ? Please explain.
> 
The sizeof keyword looks like a function, but it is in fact a built-in
operator. You are not really derefencing the pointer when you pass it *p,
you are telling it, at compile time, to take the size of the type p
points to.

This is undesireable, and my view is that the form sizeof(*p) should be
avoided. Some people recommend it because the code won't break if the
type p points to changes. However you will certainly need to review every
use of p in this case anyway, so I stick to my advice.

[toc] | [prev] | [next] | [standalone]


#148188

Frommark.bluemel@gmail.com
Date2019-11-28 05:59 -0800
Message-ID<76a74489-4a1f-4561-a01b-b2962a10bae4@googlegroups.com>
In reply to#148187
On Thursday, 28 November 2019 13:37:52 UTC, Malcolm McLean  wrote:
> On Thursday, 28 November 2019 13:20:59 UTC, V.Subramanian, India  wrote:
> > Hi,
> > I was trying to solve the questions related to pointers at the
> > following site:
> > 
> > https://www.geeksforgeeks.org/c-language-2-gq/advanced-pointer-c-gq/
> > 
> > The following is the second question:
> > 
> > Assume sizeof an integer and a pointer is 4 byte. Output?
> > 
> > #include <stdio.h>
> > 
> > #define R 10
> > #define C 20
> >  
> > int main()
> > {
> >    int (*p)[R][C];
> >    printf("%d",  sizeof(*p));
> >    getchar();
> >    return 0;
> > }
> > 
> > In this program, I thought sizeof(*p) is wrong because 'p' is not.
> > initialized and we cannot dereference p.
> >  However the answer was given as 800
> > 
> > Am I wrong ? Please explain.
> > 
> The sizeof keyword looks like a function, but it is in fact a built-in
> operator. You are not really derefencing the pointer when you pass it *p,
> you are telling it, at compile time, to take the size of the type p
> points to.

In this case (when you are asking the size of an expression), you don't have
to express it like a function.

#include <stdio.h>
#define R 10
#define C 20
int main(){
   int (*p)[R][C];
   printf("%d\n",  sizeof *p);
   return 0;
}

Which is sightly less confusing. The other way to avoid confusion is to
read a decent description of sizeof. 
<https://docs.microsoft.com/en-us/cpp/c-language/sizeof-operator-c?view=vs-2019>
isn't the standard, but it's clear and, I believe, accurate.

> This is undesireable, and my view is that the form sizeof(*p) should be
> avoided. 

It's perhaps worth mentioning that Malcolm's view isn't universally held.

[toc] | [prev] | [next] | [standalone]


#148189

FromDavid Brown <david.brown@hesbynett.no>
Date2019-11-28 15:51 +0100
Message-ID<qromtr$3o3$1@dont-email.me>
In reply to#148188
On 28/11/2019 14:59, mark.bluemel@gmail.com wrote:
> On Thursday, 28 November 2019 13:37:52 UTC, Malcolm McLean  wrote:
>> On Thursday, 28 November 2019 13:20:59 UTC, V.Subramanian, India  wrote:
>>> Hi,
>>> I was trying to solve the questions related to pointers at the
>>> following site:
>>>
>>> https://www.geeksforgeeks.org/c-language-2-gq/advanced-pointer-c-gq/
>>>

I had a brief look at that page, and was not impressed.

>>>
>>> In this program, I thought sizeof(*p) is wrong because 'p' is not.
>>> initialized and we cannot dereference p.
>>>  However the answer was given as 800
>>>
>>> Am I wrong ? Please explain.

The key point here is that the operand to "sizeof" is not evaluated - it
is only the type that is important.  So since the address "p" is not
dereferenced, there is no problem.  Any C "tutorial" that talks about
"type-cast" is immediately suspect.  And beyond question 2, the
questions just get sillier and sillier as they leave behind all traces
of realism.  They are like trying to test mathematical ability by asking
for you to calculate 19482957156 / 927590, and then adding more digits
for the next question.

>>>
>> The sizeof keyword looks like a function, but it is in fact a built-in
>> operator. You are not really derefencing the pointer when you pass it *p,
>> you are telling it, at compile time, to take the size of the type p
>> points to.
> 
> In this case (when you are asking the size of an expression), you don't have
> to express it like a function.
> 
> #include <stdio.h>
> #define R 10
> #define C 20
> int main(){
>    int (*p)[R][C];
>    printf("%d\n",  sizeof *p);
>    return 0;
> }
> 
> Which is sightly less confusing.

Personally, I dislike writing "sizeof *p" - to me, it looks like a
multiplication.  I'd rather have it looking like a function, even though
it is not really like a function - I'd write "sizeof(*p)".  Of course,
when learning C you need to understand both forms no matter which you
prefer to write.  (And I am fully aware that my view is not universally
held!)

> The other way to avoid confusion is to
> read a decent description of sizeof. 
> <https://docs.microsoft.com/en-us/cpp/c-language/sizeof-operator-c?view=vs-2019>
> isn't the standard, but it's clear and, I believe, accurate.
> 

Another fine source of reference is the "cppreference.com" site:

<https://en.cppreference.com/w/c/language/sizeof>

They try to be accurate to the standards, but are a bit easier to
navigate and they are clear about which versions of the standards are
relevant for each feature.

>> This is undesireable, and my view is that the form sizeof(*p) should be
>> avoided. 
> 
> It's perhaps worth mentioning that Malcolm's view isn't universally held.
> 

[toc] | [prev] | [next] | [standalone]


#148190

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2019-11-28 07:27 -0800
Message-ID<2119c5dc-fc01-4a74-93f4-8027c7cc210e@googlegroups.com>
In reply to#148189
On Thursday, 28 November 2019 14:51:48 UTC, David Brown  wrote:
> 
> 
> Personally, I dislike writing "sizeof *p" - to me, it looks like a
> multiplication.  I'd rather have it looking like a function, even though
> it is not really like a function - I'd write "sizeof(*p)".  
>
Also, you frequently need the size of an array of objects. So the
form

sizeof *p * N

is very common. 

[toc] | [prev] | [next] | [standalone]


#148191

FromHerbert Rosenau <nospam@hrosenau.de>
Date2019-11-28 17:28 +0100
Message-ID<c97a16bb-4384-5e83-2c2f-1099b62be653@hrosenau.de>
In reply to#148190
Am 28.11.19 um 16:27 schrieb Malcolm McLean:
> On Thursday, 28 November 2019 14:51:48 UTC, David Brown  wrote:
>>
>>
>> Personally, I dislike writing "sizeof *p" - to me, it looks like a
>> multiplication.  I'd rather have it looking like a function, even though
>> it is not really like a function - I'd write "sizeof(*p)".
>>
> Also, you frequently need the size of an array of objects. So the
> form
> 
> sizeof *p * N
> 
> is very common.
> 

sifeof p /* gives the size of p, the pointer p can point to */
sizeof *p /* gives the size of a type p can point to */

[toc] | [prev] | [next] | [standalone]


#148192

FromThiago Adams <thiago.adams@gmail.com>
Date2019-11-28 08:51 -0800
Message-ID<43093894-ed52-47de-85f4-eadd92a1499e@googlegroups.com>
In reply to#148191
On Thursday, November 28, 2019 at 1:28:13 PM UTC-3, Herbert Rosenau wrote:
> Am 28.11.19 um 16:27 schrieb Malcolm McLean:
> > On Thursday, 28 November 2019 14:51:48 UTC, David Brown  wrote:
> >>
> >>
> >> Personally, I dislike writing "sizeof *p" - to me, it looks like a
> >> multiplication.  I'd rather have it looking like a function, even though
> >> it is not really like a function - I'd write "sizeof(*p)".
> >>
> > Also, you frequently need the size of an array of objects. So the
> > form
> > 
> > sizeof *p * N
> > 
> > is very common.
> > 
> 
> sifeof p /* gives the size of p, the pointer p can point to */
> sizeof *p /* gives the size of a type p can point to */

Only when applied to variably types, sizeof is in runtime.

  int n = 10;
  
  int(*buf)[n] = malloc(sizeof(int) * n);
  
  printf("sizeof buf=%d", (int)(sizeof * buf)); //prints 40

[toc] | [prev] | [next] | [standalone]


#148195

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2019-11-28 17:36 +0000
Message-ID<877e3j52do.fsf@bsb.me.uk>
In reply to#148192
Thiago Adams <thiago.adams@gmail.com> writes:
<cut>
> Only when applied to variably types, sizeof is in runtime.
>
>   int n = 10;
>   
>   int(*buf)[n] = malloc(sizeof(int) * n);

Why would you not write

   int (*buf)[n] = malloc(sizof *buf);

?

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#148206

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-11-28 16:37 -0800
Message-ID<86eexr8qlh.fsf@linuxsc.com>
In reply to#148195
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Thiago Adams <thiago.adams@gmail.com> writes:
> <cut>
>
>> Only when applied to variably types, sizeof is in runtime.
>>
>>   int n = 10;
>>
>>   int(*buf)[n] = malloc(sizeof(int) * n);
>
> Why would you not write
>
>    int (*buf)[n] = malloc(sizof *buf);
>
> ?

Perhaps because, technically speaking, the right-hand side here
has undefined behavior?

[toc] | [prev] | [next] | [standalone]


#148210

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2019-11-29 01:27 +0000
Message-ID<87v9r33211.fsf@bsb.me.uk>
In reply to#148206
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>
>> Thiago Adams <thiago.adams@gmail.com> writes:
>> <cut>
>>
>>> Only when applied to variably types, sizeof is in runtime.
>>>
>>>   int n = 10;
>>>
>>>   int(*buf)[n] = malloc(sizeof(int) * n);
>>
>> Why would you not write
>>
>>    int (*buf)[n] = malloc(sizof *buf);
>>
>> ?
>
> Perhaps because, technically speaking, the right-hand side here
> has undefined behavior?

Yes, it has.  That has always puzzled me.  Do you think that this usage
was specifically being ruled out, or is it a casualty of having made an
overly simple decision[1]?

This whole areas makes me uneasy.  I've never been able to find a
reasonable example where an expression operand of sizeof needs to be
evaluated[2] (as the standard mandates) but most compilers evaluate f in

  sizeof (int[f()])

despite the standard not explaining what it means to evaluate a type
(though it's not hard to guess what is intended).  Do the rules make
sense to you?

[1] Somewhat like the simple type compatibility rule about const that
prohibits (without a cast) a few safe conversions which C++'s more
complex rules allow.

[2] I suppose reasonable is up for debate, but the sort of thing I am
(personally) ruling out is

  int n = 10, a[n], b[n/2];
  ... sizeof _Generic(1, int: a, default: b) ...

where the _Generic expression, technically, has to be evaluated but it's
going to be removed at compile-time.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#148211

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-11-28 17:47 -0800
Message-ID<861rtr8ndf.fsf@linuxsc.com>
In reply to#148210
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>
>>> Thiago Adams <thiago.adams@gmail.com> writes:
>>> <cut>
>>>
>>>> Only when applied to variably types, sizeof is in runtime.
>>>>
>>>>   int n = 10;
>>>>
>>>>   int(*buf)[n] = malloc(sizeof(int) * n);
>>>
>>> Why would you not write
>>>
>>>    int (*buf)[n] = malloc(sizof *buf);
>>>
>>> ?
>>
>> Perhaps because, technically speaking, the right-hand side here
>> has undefined behavior?
>
> Yes, it has.  That has always puzzled me.  Do you think that this usage
> was specifically being ruled out, or is it a casualty of having made an
> overly simple decision[1]?

Short answer:  overly simple decision casualty.  But that is just
a guess, if I have time I will try to give a more thoughtful
answer later.

[toc] | [prev] | [next] | [standalone]


#148212

FromRichard Damon <Richard@Damon-Family.org>
Date2019-11-28 21:16 -0500
Message-ID<Hb%DF.30271$s93.29962@fx19.iad>
In reply to#148211
On 11/28/19 8:47 PM, Tim Rentsch wrote:
> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> 
>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>
>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>
>>>> Thiago Adams <thiago.adams@gmail.com> writes:
>>>> <cut>
>>>>
>>>>> Only when applied to variably types, sizeof is in runtime.
>>>>>
>>>>>   int n = 10;
>>>>>
>>>>>   int(*buf)[n] = malloc(sizeof(int) * n);
>>>>
>>>> Why would you not write
>>>>
>>>>    int (*buf)[n] = malloc(sizof *buf);
>>>>
>>>> ?
>>>
>>> Perhaps because, technically speaking, the right-hand side here
>>> has undefined behavior?
>>
>> Yes, it has.  That has always puzzled me.  Do you think that this usage
>> was specifically being ruled out, or is it a casualty of having made an
>> overly simple decision[1]?
> 
> Short answer:  overly simple decision casualty.  But that is just
> a guess, if I have time I will try to give a more thoughtful
> answer later.
> 

I had always read the phrase from 6.5.3.4p2

The sizeof operator yields the size (in bytes) of its operand, which may
be an expression or the parenthesized name of a type. The size is
determined from the type of the operand. The result is an integer. If
the type of the operand is a variable length array type, the operand is
evaluated; otherwise, the operand is not evaluated and the result is an
integer constant.

As referring to if the operand WAS a variable length array type, but the
wording doesn't quite say that. My guess is that is what was intended.

[toc] | [prev] | [next] | [standalone]


#148277

FromKeith Thompson <kst-u@mib.org>
Date2019-11-29 00:38 -0800
Message-ID<lnlfrzulg0.fsf@kst-u.example.com>
In reply to#148212
Richard Damon <Richard@Damon-Family.org> writes:
[...]
> I had always read the phrase from 6.5.3.4p2
>
> The sizeof operator yields the size (in bytes) of its operand, which may
> be an expression or the parenthesized name of a type. The size is
> determined from the type of the operand. The result is an integer. If
> the type of the operand is a variable length array type, the operand is
> evaluated; otherwise, the operand is not evaluated and the result is an
> integer constant.
>
> As referring to if the operand WAS a variable length array type, but the
> wording doesn't quite say that. My guess is that is what was intended.

I *think* you're saying that the "operand is evaluated" clause is meant
to apply to `sizeof (vla_type)` but not to `sizeof vla_object`.  Is that
what you meant?  I don't agree that that's what the wording in the
standard says, but I do agree that it could be a more reasonable rule.

Off the top of my head, I can't think of a case where `sizeof expr`,
where expr is of VLA type, actually needs to evaluate expr to
determine its size.  (I'd be interested in seeing an example.)
But the standard seems to require it to be evaluated anyway, and
most compilers follow that.

An example:

#include <stdio.h>

int ident(int n) {
    printf("ident(%d)\n", n);
    return n;
}

int main(void) {
    int dim = 42;
    int vla[dim][dim];
    printf("sizeof vla[ident(10)] = %zu\n", sizeof vla[ident(10)]);
}

The size can be determined without calling ident(10), but gcc,
clang, and icc (correctly following the standard, I think) generate
a call, i.e., they evaluate (part of) the operand of the sizeof.
(tcc doesn't, but I don't expect tcc to be fully conforming.)

A painfully literal reading of "the operand is evaluated" could
mean that it has to evaluate the value of the array object vla[10],
which would mean evaluating the value of each of its 42 elements.
That's clearly unnecessary, and surely was not the intent.

In general `sizeof vla_expression` requires evaluating *something* at
run time, typically retrieving the value of an anonymous object that
holds the array length or size, and possibly doing some arithmetic on
it.  But that doesn't evaluate, or require evaluating, the operand.

On the other hand, if the operand is a parenthesized type name,
the standard doesn't tell us what "evaluating" a type name means.
Only expressions are evaluated.  It could mean evaluating
any expressions contained within the type name (as in `sizeof
(int[func()])` -- note that evaluating `func()` is actually
necessary to determine the size).  I think the standard could be
improved by making that clearer.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#148286

FromRichard Damon <Richard@Damon-Family.org>
Date2019-11-29 09:03 -0500
Message-ID<Zy9EF.120213$P37.66802@fx33.iad>
In reply to#148277
On 11/29/19 3:38 AM, Keith Thompson wrote:
> Richard Damon <Richard@Damon-Family.org> writes:
> [...]
>> I had always read the phrase from 6.5.3.4p2
>>
>> The sizeof operator yields the size (in bytes) of its operand, which may
>> be an expression or the parenthesized name of a type. The size is
>> determined from the type of the operand. The result is an integer. If
>> the type of the operand is a variable length array type, the operand is
>> evaluated; otherwise, the operand is not evaluated and the result is an
>> integer constant.
>>
>> As referring to if the operand WAS a variable length array type, but the
>> wording doesn't quite say that. My guess is that is what was intended.
> 
> I *think* you're saying that the "operand is evaluated" clause is meant
> to apply to `sizeof (vla_type)` but not to `sizeof vla_object`.  Is that
> what you meant?  I don't agree that that's what the wording in the
> standard says, but I do agree that it could be a more reasonable rule.
> 
> Off the top of my head, I can't think of a case where `sizeof expr`,
> where expr is of VLA type, actually needs to evaluate expr to
> determine its size.  (I'd be interested in seeing an example.)
> But the standard seems to require it to be evaluated anyway, and
> most compilers follow that.
> 
> An example:
> 
> #include <stdio.h>
> 
> int ident(int n) {
>     printf("ident(%d)\n", n);
>     return n;
> }
> 
> int main(void) {
>     int dim = 42;
>     int vla[dim][dim];
>     printf("sizeof vla[ident(10)] = %zu\n", sizeof vla[ident(10)]);
> }
> 
> The size can be determined without calling ident(10), but gcc,
> clang, and icc (correctly following the standard, I think) generate
> a call, i.e., they evaluate (part of) the operand of the sizeof.
> (tcc doesn't, but I don't expect tcc to be fully conforming.)
> 
> A painfully literal reading of "the operand is evaluated" could
> mean that it has to evaluate the value of the array object vla[10],
> which would mean evaluating the value of each of its 42 elements.
> That's clearly unnecessary, and surely was not the intent.
> 
> In general `sizeof vla_expression` requires evaluating *something* at
> run time, typically retrieving the value of an anonymous object that
> holds the array length or size, and possibly doing some arithmetic on
> it.  But that doesn't evaluate, or require evaluating, the operand.
> 
> On the other hand, if the operand is a parenthesized type name,
> the standard doesn't tell us what "evaluating" a type name means.
> Only expressions are evaluated.  It could mean evaluating
> any expressions contained within the type name (as in `sizeof
> (int[func()])` -- note that evaluating `func()` is actually
> necessary to determine the size).  I think the standard could be
> improved by making that clearer.
> 

Yes, I agree that isn't what it SAYS, but it could be what they meant to
say, but didn't word it right, for some of the reasons you mention.

Yes, we don't evaluate a type, but a variable modified type by
definition has an expression in it that isn't a constant, so needs to be
evaluated, and that would need to be evaluated by sizeof.

Also, generally the type of an expression is easily known even without
knowing the value of any of the objects in an expression, which is what
I think they meant to use in the statement. I think there may be a way
to use a compound literal expression to create a new type in an
expression, and then that type would need to be 'evaluated'

[toc] | [prev] | [next] | [standalone]


#148301

FromKeith Thompson <kst-u@mib.org>
Date2019-11-29 13:15 -0800
Message-ID<lntv6m1j1k.fsf@kst-u.example.com>
In reply to#148286
Richard Damon <Richard@Damon-Family.org> writes:
> On 11/29/19 3:38 AM, Keith Thompson wrote:
>> Richard Damon <Richard@Damon-Family.org> writes:
>> [...]
>>> I had always read the phrase from 6.5.3.4p2
>>>
>>> The sizeof operator yields the size (in bytes) of its operand, which may
>>> be an expression or the parenthesized name of a type. The size is
>>> determined from the type of the operand. The result is an integer. If
>>> the type of the operand is a variable length array type, the operand is
>>> evaluated; otherwise, the operand is not evaluated and the result is an
>>> integer constant.
>>>
>>> As referring to if the operand WAS a variable length array type, but the
>>> wording doesn't quite say that. My guess is that is what was intended.
>> 
>> I *think* you're saying that the "operand is evaluated" clause is meant
>> to apply to `sizeof (vla_type)` but not to `sizeof vla_object`.  Is that
>> what you meant?  I don't agree that that's what the wording in the
>> standard says, but I do agree that it could be a more reasonable rule.

[...]

> Yes, I agree that isn't what it SAYS, but it could be what they meant to
> say, but didn't word it right, for some of the reasons you mention.

That doesn't seem plausible to me.  The current wording explicitly says
that `sizeof vla_expression` evaluates `vla_expression`.  I think it
would have been worded quite differently if the evaluation were meant to
apply only to an operand that's a parenthesized type name.  Multiple
compilers generate code that evaluates the expression, examples (some
contrived) are well known, and as far as I know nobody on the committee
has spoken up to say "That's not what we meant".

It's plausible that the rule *could* be that `sizeof vla_expression`
doesn't evaluate `vla_expression`, but I don't think it's plausible that
the committee didn't intend `vla_expression` to be evaluated (though
it's possible they didn't sufficiently think through what that means).

> Yes, we don't evaluate a type, but a variable modified type by
> definition has an expression in it that isn't a constant, so needs to be
> evaluated, and that would need to be evaluated by sizeof.

To be clear, it's not the *type* that has an expression in it, it's the
*type-name* that's the operand (in parentheses) of the sizeof operator.

> Also, generally the type of an expression is easily known even without
> knowing the value of any of the objects in an expression, which is what
> I think they meant to use in the statement.

That's true "generally"in the sense that it's *usually* known, but not
"generally" in the sense that it's *always* known.  And of course the
standard has to cover all defined cases.

>                                             I think there may be a way
> to use a compound literal expression to create a new type in an
> expression, and then that type would need to be 'evaluated'

Not directly, since the type name in a compound literal cannot be a VLA
type.  But as Tim points out, it can be done by dereferencing a compound
literal of a pointer-to-VLA type.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#148302

FromKeith Thompson <kst-u@mib.org>
Date2019-11-29 13:38 -0800
Message-ID<lnk17i1hym.fsf@kst-u.example.com>
In reply to#148301
Keith Thompson <kst-u@mib.org> writes:
> Richard Damon <Richard@Damon-Family.org> writes:
[...]
>> Yes, I agree that isn't what it SAYS, but it could be what they meant to
>> say, but didn't word it right, for some of the reasons you mention.
>
[...]
>
> It's plausible that the rule *could* be that `sizeof vla_expression`
> doesn't evaluate `vla_expression`, but I don't think it's plausible that
> the committee didn't intend `vla_expression` to be evaluated (though
> it's possible they didn't sufficiently think through what that means).

Correction: Since there are cases (see below) where `sizeof vla_expression`
actually has to evaluate `vla_expression` (or at least part of it) to
determine the size, simply saying that it's not evaluated wouldn't work.

[...]

>>                                             I think there may be a way
>> to use a compound literal expression to create a new type in an
>> expression, and then that type would need to be 'evaluated'
>
> Not directly, since the type name in a compound literal cannot be a VLA
> type.  But as Tim points out, it can be done by dereferencing a compound
> literal of a pointer-to-VLA type.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#148294

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-11-29 07:09 -0800
Message-ID<86o8wu7m8z.fsf@linuxsc.com>
In reply to#148277
Keith Thompson <kst-u@mib.org> writes:

> Richard Damon <Richard@Damon-Family.org> writes:
> [...]
>
>> I had always read the phrase from 6.5.3.4p2
>>
>> The sizeof operator yields the size (in bytes) of its operand, which may
>> be an expression or the parenthesized name of a type.  The size is
>> determined from the type of the operand.  The result is an integer.  If
>> the type of the operand is a variable length array type, the operand is
>> evaluated;  otherwise, the operand is not evaluated and the result is an
>> integer constant.
>>
>> As referring to if the operand WAS a variable length array type, but the
>> wording doesn't quite say that.  My guess is that is what was intended.
>
> I *think* you're saying that the "operand is evaluated" clause is meant
> to apply to `sizeof (vla_type)` but not to `sizeof vla_object`.  Is that
> what you meant?

That is how I took his comment.

> I don't agree that that's what the wording in the
> standard says, but I do agree that it could be a more reasonable rule.
>
> Off the top of my head, I can't think of a case where `sizeof expr`,
> where expr is of VLA type, actually needs to evaluate expr to
> determine its size.  (I'd be interested in seeing an example.)
> But the standard seems to require it to be evaluated anyway, and
> most compilers follow that.
>
> An example:
>
> #include <stdio.h>
>
> int ident(int n) {
>     printf("ident(%d)\n", n);
>     return n;
> }
>
> int main(void) {
>     int dim = 42;
>     int vla[dim][dim];
>     printf("sizeof vla[ident(10)] = %zu\n", sizeof vla[ident(10)]);
> }
>
> The size can be determined without calling ident(10), but gcc,
> clang, and icc (correctly following the standard, I think) generate
> a call, i.e., they evaluate (part of) the operand of the sizeof.
> (tcc doesn't, but I don't expect tcc to be fully conforming.)
>
> A painfully literal reading of "the operand is evaluated" could
> mean that it has to evaluate the value of the array object vla[10],
> which would mean evaluating the value of each of its 42 elements.
> That's clearly unnecessary, and surely was not the intent.

The Standard specifically excludes that possibility, in section
6.3.2.1 p2.

    Except when it is the operand of the sizeof operator [or
    other exceptions], an lvalue that does not have array type
    is converted to the value stored in the designated object
    (and is no longer an lvalue) [...]

> In general `sizeof vla_expression` requires evaluating *something* at
> run time, typically retrieving the value of an anonymous object that
> holds the array length or size, and possibly doing some arithmetic on
> it.  But that doesn't evaluate, or require evaluating, the operand.

The Standard says it does evaluate the operand.

Moreover there are cases where evaluating the operand is necessary
to determine the size:

    int foo = sizeof *(int (*)[ ident( 1 ) ]){ &something };

This expression needs to evaluate the sizeof operand expression
to determine the value to assign to foo.

> On the other hand, if the operand is a parenthesized type name,
> the standard doesn't tell us what "evaluating" a type name means.

In a sense it does, in 6.7.6.2 p5, talking about array declarators.
That section concerns declaring variables, but a type name is like a
variable declaration except it omits the variable identifier.  It
seems reasonable to infer that type names are evaluated like their
variable declarator counterparts.

> Only expressions are evaluated.  It could mean evaluating
> any expressions contained within the type name (as in `sizeof
> (int[func()])` -- note that evaluating `func()` is actually
> necessary to determine the size).  I think the standard could be
> improved by making that clearer.

It's true that only expressions are evaluated, but any type name
that is part of an expression is an operand in the expression
and so must be evaluated (according to the semantics).  Type
names can appear in expressions outside of 'sizeof' expressions,
in particular in cast expressions.  They also appear in compound
literals (a compound literal may not have a variable length array
type, but it may have a variably modified type, causing evaluation
of the bound expression(s) in any contained VLA types).

I agree the Standard would benefit from a more explicit statement
about the semantics of evaluating a type name.

[toc] | [prev] | [next] | [standalone]


#148288

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-11-29 06:10 -0800
Message-ID<86sgm67oyi.fsf@linuxsc.com>
In reply to#148212
Richard Damon <Richard@Damon-Family.org> writes:

> On 11/28/19 8:47 PM, Tim Rentsch wrote:
>
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>
>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>
>>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>>
>>>>> Thiago Adams <thiago.adams@gmail.com> writes:
>>>>> <cut>
>>>>>
>>>>>> Only when applied to variably types, sizeof is in runtime.
>>>>>>
>>>>>>   int n = 10;
>>>>>>
>>>>>>   int(*buf)[n] = malloc(sizeof(int) * n);
>>>>>
>>>>> Why would you not write
>>>>>
>>>>>    int (*buf)[n] = malloc(sizof *buf);
>>>>>
>>>>> ?
>>>>
>>>> Perhaps because, technically speaking, the right-hand side here
>>>> has undefined behavior?
>>>
>>> Yes, it has.  That has always puzzled me.  Do you think that this usage
>>> was specifically being ruled out, or is it a casualty of having made an
>>> overly simple decision[1]?
>>
>> Short answer:  overly simple decision casualty.  But that is just
>> a guess, if I have time I will try to give a more thoughtful
>> answer later.
>
> I had always read the phrase from 6.5.3.4p2
>
> The sizeof operator yields the size (in bytes) of its operand, which may
> be an expression or the parenthesized name of a type.  The size is
> determined from the type of the operand.  The result is an integer.  If
> the type of the operand is a variable length array type, the operand is
> evaluated;  otherwise, the operand is not evaluated and the result is an
> integer constant.
>
> As referring to if the operand WAS a variable length array type, but the
> wording doesn't quite say that.  My guess is that is what was intended.

Is this just supposition on your part?  Or do you have some sort
of confirmation based on other sources?

[toc] | [prev] | [next] | [standalone]


#148296

FromRichard Damon <Richard@Damon-Family.org>
Date2019-11-29 11:12 -0500
Message-ID<esbEF.139166$Ys1.126074@fx42.iad>
In reply to#148288
On 11/29/19 9:10 AM, Tim Rentsch wrote:
> Richard Damon <Richard@Damon-Family.org> writes:
>>
>> I had always read the phrase from 6.5.3.4p2
>>
>> The sizeof operator yields the size (in bytes) of its operand, which may
>> be an expression or the parenthesized name of a type.  The size is
>> determined from the type of the operand.  The result is an integer.  If
>> the type of the operand is a variable length array type, the operand is
>> evaluated;  otherwise, the operand is not evaluated and the result is an
>> integer constant.
>>
>> As referring to if the operand WAS a variable length array type, but the
>> wording doesn't quite say that.  My guess is that is what was intended.
> 
> Is this just supposition on your part?  Or do you have some sort
> of confirmation based on other sources?
> 

Purely interpretation on my own part. The way my brain works I tend to
parse things to get intended meaning and distill down to essence. This
makes me bad a 'rules lawyering', i.e. detecting minute corner cases is
rules.

I've always seen the C Standard as a bit pragmatically worded, that at
times when they couldn't get some wording exactly right, they just
settled for good enough and left the corner cases exposed (and by
leaving the corner cases as UB, a good implementation can still do the
'Right Thing')

I think this is one example, it wasn't worth their effort to try and
precisely define what needed to be evaluated to determine the type, so
they erred on the side of letting the compiler be allowed to do more
than needed (since it can almost always not do it by the as-if rule)
then not let the compiler do something it needs to in order to process
the statement and have an error in the language.

[toc] | [prev] | [next] | [standalone]


#148327

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-12-01 09:32 -0800
Message-ID<867e3g6jew.fsf@linuxsc.com>
In reply to#148296
Richard Damon <Richard@Damon-Family.org> writes:

> On 11/29/19 9:10 AM, Tim Rentsch wrote:
>
>> Richard Damon <Richard@Damon-Family.org> writes:
>>
>>> I had always read the phrase from 6.5.3.4p2
>>>
>>> The sizeof operator yields the size (in bytes) of its operand, which may
>>> be an expression or the parenthesized name of a type.  The size is
>>> determined from the type of the operand.  The result is an integer.  If
>>> the type of the operand is a variable length array type, the operand is
>>> evaluated;  otherwise, the operand is not evaluated and the result is an
>>> integer constant.
>>>
>>> As referring to if the operand WAS a variable length array type, but the
>>> wording doesn't quite say that.  My guess is that is what was intended.
>>
>> Is this just supposition on your part?  Or do you have some sort
>> of confirmation based on other sources?
>
> Purely interpretation on my own part.  The way my brain works I tend to
> parse things to get intended meaning and distill down to essence.  This
> makes me bad a 'rules lawyering', i.e. detecting minute corner cases is
> rules.
>
> I've always seen the C Standard as a bit pragmatically worded, that at
> times when they couldn't get some wording exactly right, they just
> settled for good enough and left the corner cases exposed (and by
> leaving the corner cases as UB, a good implementation can still do the
> 'Right Thing')
>
> I think this is one example, it wasn't worth their effort to try and
> precisely define what needed to be evaluated to determine the type, so
> they erred on the side of letting the compiler be allowed to do more
> than needed (since it can almost always not do it by the as-if rule)
> then not let the compiler do something it needs to in order to process
> the statement and have an error in the language.

I sort of agree with you.  The determination may have been, not
that it wasn't worth their effort, but that having a more exact
but more complicated rule would have a negative ROI as far as
readers of the Standard are concerned.  Except for that one minor
difference, I think we are pretty much on the same page.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web