Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #148186 > unrolled thread
| Started by | "V.Subramanian, India" <subramanian100in@yahoo.com> |
|---|---|
| First post | 2019-11-28 05:20 -0800 |
| Last post | 2019-11-30 15:28 -0800 |
| Articles | 20 on this page of 35 — 12 participants |
Back to article view | Back to comp.lang.c
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 →
| From | "V.Subramanian, India" <subramanian100in@yahoo.com> |
|---|---|
| Date | 2019-11-28 05:20 -0800 |
| Subject | sizeof 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]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2019-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]
| From | mark.bluemel@gmail.com |
|---|---|
| Date | 2019-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-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]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2019-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]
| From | Herbert Rosenau <nospam@hrosenau.de> |
|---|---|
| Date | 2019-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]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2019-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2019-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2019-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2019-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2019-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]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2019-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2019-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]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2019-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2019-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2019-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2019-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2019-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]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2019-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2019-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