Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sizeof(arr[0])

342 views
Skip to first unread message

kuzneco...@gmail.com

unread,
Jun 10, 2015, 3:39:05 PM6/10/15
to
There is a well know pattern of figuring out array length:
int arr[10];
size_t len = sizeof(arr) / sizeof(arr[0]);
assert(len == 10);

This pattern applies to static arrays and auto arrays of constant size. It also applies to variable length arrays in C99.

I want to apply similar idea for figuring out dynamic array size in bytes:
size_t known_len = 10;
int *ptr = malloc(known_len);
size_t size = known_len * sizeof(ptr[0]);
assert(size == known_len * sizeof(int));

This is nicer than "known_len * sizeof(int)" because "sizeof(ptr[0])" doesn't refer to actual array element type. Hence it doesn't require reader of the code to know the type.

However it is unclear to me whether expression "sizeof(ptr[0])" can lead to undefined behavior. As it is expanded:
sizeof(ptr[0]) -> sizeof(*((ptr) + (0))) -> sizeof(*ptr)
The result expression is questionable in case if ptr is 0:
sizeof(*((int*) 0))

According to a C99 standard:
~~~
(C99, 6.3.2.3p3 ): "An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant."
Dereferencing a null pointer is undefined behavior.

(C99, 6.5.3.2.p4) "If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.87)"
and

87): "Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime."
~~~

But it's never specified whether sizeof of such expression can lead to undefined behavior. In fact such sizeof should be evaluated at compile time.

My questions are:
- Can the expression "sizeof(ptr[0])" be used in the code when type of ptr is known and the value of ptr is not known?
- Can such use be justified according to C99 standard? GNU GCC spec?

James Kuyper

unread,
Jun 10, 2015, 4:00:23 PM6/10/15
to
On 06/10/2015 03:38 PM, kuzneco...@gmail.com wrote:
> There is a well know pattern of figuring out array length:
> int arr[10];
> size_t len = sizeof(arr) / sizeof(arr[0]);
> assert(len == 10);
>
> This pattern applies to static arrays and auto arrays of constant size. It also applies to variable length arrays in C99.
>
> I want to apply similar idea for figuring out dynamic array size in bytes:
> size_t known_len = 10;
> int *ptr = malloc(known_len);

You've told malloc() to allocate 10 bytes of space.

> size_t size = known_len * sizeof(ptr[0]);

You're calculating the size of 10 'int' objects. Unless sizeof ptr[0] ==
1, that's at least 10 bytes longer than the size of the object that was
allocated by your call to malloc().

> assert(size == known_len * sizeof(int));
>
> This is nicer than "known_len * sizeof(int)" because "sizeof(ptr[0])" doesn't refer to actual array element type. Hence it doesn't require reader of the code to know the type.
>
> However it is unclear to me whether expression "sizeof(ptr[0])" can lead to undefined behavior. As it is expanded:
> sizeof(ptr[0]) -> sizeof(*((ptr) + (0))) -> sizeof(*ptr)
> The result expression is questionable in case if ptr is 0:
> sizeof(*((int*) 0))

ptr is a pointer object. It cannot have a value of 0, because 0 is an
arithmetic value, and ptr can only store pointer values. It can be a
null pointer, which could be result of writing

ptr = 0;

but that works only because, in that context, '0' gets interpreted as a
null pointer constant, and then converted into a null pointer of the
same type as 'ptr', before being assigned to 'ptr'. That pointer might
or might not point at address 0. It might or might not be represented by
having all bits of 'ptr' set to 0. The only things guaranteed by the
standard is that after that assignment statement, ptr will compare equal
to all other null pointers (regardless of representation), and will
compare unequal to all non-null pointers.

> But it's never specified whether sizeof of such expression can lead to undefined behavior. In fact such sizeof should be evaluated at compile time.

One of the very most important things to know about the sizeof operator
is that "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." (6.5.3.4p2).
ptr[0] is an int, not a variable length array. It is therefore NOT
evaluated when the sizeof operator is applied to it.

> My questions are:
> - Can the expression "sizeof(ptr[0])" be used in the code when type of ptr is known and the value of ptr is not known?

Yes, since the value is not used. Only the type of the expression matters.

> - Can such use be justified according to C99 standard? GNU GCC spec?

Yes. C90 had similar wording, except that there was no exception for
variable length arrays, because those didn't exist in C90.

kuzneco...@gmail.com

unread,
Jun 10, 2015, 4:11:42 PM6/10/15
to
On Wednesday, June 10, 2015 at 12:39:05 PM UTC-7, kuzneco...@gmail.com wrote:
> There is a well know pattern of figuring out array length:
> int arr[10];
> size_t len = sizeof(arr) / sizeof(arr[0]);
> assert(len == 10);
>
> This pattern applies to static arrays and auto arrays of constant size. It also applies to variable length arrays in C99.
>
> I want to apply similar idea for figuring out dynamic array size in bytes:
> size_t known_len = 10;
> int *ptr = malloc(known_len);
> size_t size = known_len * sizeof(ptr[0]);
> assert(size == known_len * sizeof(int));
>
My apologies for the typo. Of course malloc should be:
int *ptr = malloc(known_len * sizeof(int));

Ben Bacarisse

unread,
Jun 10, 2015, 4:21:53 PM6/10/15
to
kuzneco...@gmail.com writes:

> There is a well know pattern of figuring out array length:
> int arr[10];
> size_t len = sizeof(arr) / sizeof(arr[0]);
> assert(len == 10);
>
> This pattern applies to static arrays and auto arrays of constant
> size. It also applies to variable length arrays in C99.
>
> I want to apply similar idea for figuring out dynamic array size in bytes:
> size_t known_len = 10;
> int *ptr = malloc(known_len);
> size_t size = known_len * sizeof(ptr[0]);
> assert(size == known_len * sizeof(int));

I don't know what this is supposed to do. The main problem I see is
that the malloc call asks for less memory than you seem to need. A
common idiom is

int *ptr = malloc(known_len * sizeof *ptr);

Maybe you intended to write that, but then I don't know what all the
rest is about... (And remember to check that the allocation succeeded!)

<snip>
> My questions are:
> - Can the expression "sizeof(ptr[0])" be used in the code when type
> of ptr is known and the value of ptr is not known?

Yes, the operand of sizeof is not evaluated in this case.

> - Can such use be justified according to C99 standard? GNU GCC spec?

It's standard C99 and C11 (6.5.2.4 p2).

--
Ben.

Richard Heathfield

unread,
Jun 10, 2015, 5:09:07 PM6/10/15
to
On 10/06/15 21:21, Ben Bacarisse wrote:
> kuzneco...@gmail.com writes:
>
<snip>
>> My questions are:
>> - Can the expression "sizeof(ptr[0])" be used in the code when type
>> of ptr is known and the value of ptr is not known?
>
> Yes, the operand of sizeof is not evaluated in this case.
>
>> - Can such use be justified according to C99 standard? GNU GCC spec?
>
> It's standard C99 and C11 (6.5.2.4 p2).

It is also standard C90 and C95.

I would draw the OP's attention to the omission of parentheses from the
operand of sizeof:

ptr = malloc(n * sizeof *ptr);

There is no more need to write sizeof(*ptr) than there is to write +(x).

--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

kuzneco...@gmail.com

unread,
Jun 10, 2015, 5:53:59 PM6/10/15
to
On Wednesday, June 10, 2015 at 1:00:23 PM UTC-7, James Kuyper wrote:
> On 06/10/2015 03:38 PM, kuzneco...@gmail.com wrote:
> > There is a well know pattern of figuring out array length:
> > int arr[10];
> > size_t len = sizeof(arr) / sizeof(arr[0]);
> > assert(len == 10);
> >
> > This pattern applies to static arrays and auto arrays of constant size. It also applies to variable length arrays in C99.
> >
> > I want to apply similar idea for figuring out dynamic array size in bytes:
> > size_t known_len = 10;
> > int *ptr = malloc(known_len);
>
> You've told malloc() to allocate 10 bytes of space.
>
> > size_t size = known_len * sizeof(ptr[0]);
>
> You're calculating the size of 10 'int' objects. Unless sizeof ptr[0] ==
> 1, that's at least 10 bytes longer than the size of the object that was
> allocated by your call to malloc().
>
Correct. Sample code has an error.
Thanks! That's what I was looking for.

kuzneco...@gmail.com

unread,
Jun 10, 2015, 5:56:46 PM6/10/15
to
On Wednesday, June 10, 2015 at 1:21:53 PM UTC-7, Ben Bacarisse wrote:
> kuzneco...@gmail.com writes:
>
> > There is a well know pattern of figuring out array length:
> > int arr[10];
> > size_t len = sizeof(arr) / sizeof(arr[0]);
> > assert(len == 10);
> >
> > This pattern applies to static arrays and auto arrays of constant
> > size. It also applies to variable length arrays in C99.
> >
> > I want to apply similar idea for figuring out dynamic array size in bytes:
> > size_t known_len = 10;
> > int *ptr = malloc(known_len);
> > size_t size = known_len * sizeof(ptr[0]);
> > assert(size == known_len * sizeof(int));
Correct. There is an error in example.
>
> I don't know what this is supposed to do. The main problem I see is
> that the malloc call asks for less memory than you seem to need. A
> common idiom is
>
> int *ptr = malloc(known_len * sizeof *ptr);
The question was about that exact idiom.

Ben Bacarisse

unread,
Jun 10, 2015, 6:53:40 PM6/10/15
to
kuzneco...@gmail.com writes:

> On Wednesday, June 10, 2015 at 1:21:53 PM UTC-7, Ben Bacarisse wrote:
<snip>
>> int *ptr = malloc(known_len * sizeof *ptr);
> The question was about that exact idiom.

I thought so, and I did answer it, though I did not stress that it's
fine in all versions of C. I was rather too specific in answering your
exact question:

>> > My questions are:
>> > - Can the expression "sizeof(ptr[0])" be used in the code when type
>> > of ptr is known and the value of ptr is not known?
>>
>> Yes, the operand of sizeof is not evaluated in this case.
>>
>> > - Can such use be justified according to C99 standard? GNU GCC spec?
>>
>> It's standard C99 and C11 (6.5.2.4 p2).

... and in C90 ("ANSI C") and in old K&R C as well.

--
Ben.

Andrew Cooper

unread,
Jun 10, 2015, 7:30:12 PM6/10/15
to
On 10/06/2015 22:08, Richard Heathfield wrote:
> I would draw the OP's attention to the omission of parentheses from the
> operand of sizeof:
>
> ptr = malloc(n * sizeof *ptr);
>
> There is no more need to write sizeof(*ptr) than there is to write +(x).
>

While true, it quickly gets deceptive for more complicated expressions
such as 'sizeof(*p)->foo', where sizeof evaluates to the size of foo,
rather than the size of the object pointed to by p.

You owe it to anyone who reads your code, not to add to the cognitive
load of attempting to interpret it.

~Andrew

Bartc

unread,
Jun 10, 2015, 7:33:17 PM6/10/15
to
On 10/06/2015 22:56, kuzneco...@gmail.com wrote:
> On Wednesday, June 10, 2015 at 1:21:53 PM UTC-7, Ben Bacarisse wrote:
>> kuzneco...@gmail.com writes:
>>
>>> There is a well know pattern of figuring out array length:
>>> int arr[10];
>>> size_t len = sizeof(arr) / sizeof(arr[0]);
>>> assert(len == 10);
>>>
>>> This pattern applies to static arrays and auto arrays of constant
>>> size. It also applies to variable length arrays in C99.
>>>
>>> I want to apply similar idea for figuring out dynamic array size in bytes:
>>> size_t known_len = 10;
>>> int *ptr = malloc(known_len);
>>> size_t size = known_len * sizeof(ptr[0]);
>>> assert(size == known_len * sizeof(int));
> Correct. There is an error in example.

You might think about using calloc() which makes this kind of error
harder to make:

int *ptr = calloc(known_len, sizeof(int));

as you need to supply two arguments. (I think calloc also clears the
memory, which also help with certain others or least makes them more
repeatable. But you need to check the Docs as there might be other
differences from malloc.

It is very easy however to create your own wrapper around malloc which
behaves exactly as your want.)

--
Bartc

Richard Heathfield

unread,
Jun 10, 2015, 7:34:29 PM6/10/15
to
On 11/06/15 00:27, Andrew Cooper wrote:
> On 10/06/2015 22:08, Richard Heathfield wrote:
>> I would draw the OP's attention to the omission of parentheses from the
>> operand of sizeof:
>>
>> ptr = malloc(n * sizeof *ptr);
>>
>> There is no more need to write sizeof(*ptr) than there is to write +(x).
>>
>
> While true, it quickly gets deceptive for more complicated expressions
> such as 'sizeof(*p)->foo', where sizeof evaluates to the size of foo,
> rather than the size of the object pointed to by p.

I don't see why this is deceptive, any more than +(*p)->foo is deceptive
in comparison to +(*p)->foo.

Could you please explain why you think it's deceptive?

> You owe it to anyone who reads your code, not to add to the cognitive
> load of attempting to interpret it.

I would agree with you that the code should be as easy to read as is
reasonably possible. I don't agree that adding redundant parentheses
necessarily improves readability.

Richard Heathfield

unread,
Jun 10, 2015, 7:37:34 PM6/10/15
to
On 11/06/15 00:33, Bartc wrote:

<snip>

> You might think about using calloc() which makes this kind of error
> harder to make:
>
> int *ptr = calloc(known_len, sizeof(int));

...or, to preserve the idiom under discussion:

int *ptr = calloc(known_len, sizeof *ptr);

> as you need to supply two arguments. (I think calloc also clears the
> memory,

It sets all bits to zero. That doesn't necessarily represent default
static initialiser values (for example, a null pointer might have some
of the high bits set), so calloc isn't as useful as it should be.

<snip>

Richard Heathfield

unread,
Jun 10, 2015, 7:38:24 PM6/10/15
to
On 11/06/15 00:34, Richard Heathfield wrote:

>
> I don't see why this is deceptive, any more than +(*p)->foo is deceptive
> in comparison to +(*p)->foo.

Oops. Of course I meant "in comparison to +((*p)->foo)".
Message has been deleted

Lew Pitcher

unread,
Jun 10, 2015, 9:17:03 PM6/10/15
to
On Wednesday June 10 2015 20:38, in comp.lang.c, "Stefan Ram"
<r...@zedat.fu-berlin.de> wrote:
[snip]
> So they now even write:
>
> while(( *p++ = *q++ )){ ; }

I sometimes write for() or while() loops with an empty compound statement, to
make the fact that the loop performs all the useful work more apparent.

For example, this code fragment searches an array for an element that matches
a specific value, and stops when either the matching element is found, or the
the end of the array has been reached:
for (related = 0;
related < nXref && this->SourceRecipeID != xref[related].pRB_RecipeId;
++related)
{/*NOP*/}

The next statement tests the termination condition, and performs the
appropriate activity

In this pattern, the loop contains all the necessary logic, and the "looped"
statement is superfluous. I /could/ have just used a null-statement (;) but
the compound statement (with the embedded NOP comment) is a much-better
eyecatcher.


--
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request

Richard Heathfield

unread,
Jun 10, 2015, 9:35:32 PM6/10/15
to
On 11/06/15 01:38, Stefan Ram wrote:
> Richard Heathfield <r...@cpax.org.uk> writes:
>>I would agree with you that the code should be as easy to read as is
>>reasonably possible. I don't agree that adding redundant parentheses
>>necessarily improves readability.
>
> We are living in dumbed-down times!
>
> Use »i++« in JavaScript, and »jslint« by Crockford will tell
> you that this is »excessive trickiness«.

That's a curious way to describe something as bland as ++. I'd have
thought the word "idiomatic" would be more appropriate.

> A student in my Java course told me that he was not given a
> job because in the interview he used »?:«, and the company
> believed that this was unreadable (probably in their opinion
> because nobody knows such »obscure operators«). (And they
> also expected him to know this style rule of the company by
> mind reading.)

A narrow escape.

> They think »if« is much more readable for beginners than »?:«.
> But whenever I show the following to beginners:
>
> char const * english( int const a )
> { char const * result;
> if( a == 0 )result = "zero";
> if( a == 1 )result = "one";
> if( a == 2 )result = "two";
> if( a == 3 )result = "three";
> else result = "four";
> return result; }

You telegraphed it, so it was easy to spot. Whether it would have been
quite so obvious if we hadn't been primed, I don't know.
<snip>

> . When someone can't even read »?:« or »x++«, how do you expect
> him to write any piece of non-trivial code, say code for OCR,
> a compiler, or code to navigate a car through the streets?

Or indeed to tie his own shoelaces.

> Or people writing
>
> while(( *p++ = *q++ ));
>
> where the double parentheses are intended to avoid a warning message,
> or even people saying that each inner statement in a while needs braces.
> So they now even write:
>
> while(( *p++ = *q++ )){ ; }
>
> because they believe that this will help someone who might insert
> another statement into the loop not to forget the braces!

That one's not quite as ridiculous as you are trying to make it sound.
In that particular case, you have a mild point, but in general there is
actually a danger that this:

while(foo(bar) > baz)
quux = quuux(quuuux);

could be edited into this:

while(foo(bar) > baz)
initquuuux(&quuuux);
quux = quuux(quuuux);

The probability that this mistake will occur does of course depend on
the programmer, but the consequences if it does happen could be quite
troublesome. It is not difficult to contrive circumstances in which the
probability is increased:

* an editor that doesn't do line-wrap
* a while condition that stretches right across the visible window
* a programmer who is accustomed to a layout style that puts opening
braces (and perhaps even closing braces) at the ends of lines
* a single-statement loop body that spans multiple lines

None of these conditions is particularly unlikely, and the combination
could lead to an occurrence of this bug:

while((currdate = convert_date_to_julian(fund->pro| <- screen edge
fund->projection->projected_balance += interest_|
is_triversary(fund->projection_date) * fund->tri|
is_charge_date(currdate) * fund->projection->ann|

Contrived? Of course. Possible? Certainly.

I habitually use braces even for single-statement loop bodies, to the
point where I don't even think about it (except when hacking up a
ten-liner, maybe, in which case I might stretch a point, but a quick
review of a bunch of programs in my scratch directory would suggest that
I don't stretch that point very far or very often).

I'm not actually all that worried about stopping bugs in this way,
though. I got into the habit because I used to catch myself muttering
whenever I was maintaining old code and had to add the braces, so I
started putting them in 'up front' instead, which cured the muttering
problem (for no logical reason that I can think of - after all, it takes
just as long to put the braces in during initial development as it would
during maintenance, so it hasn't actually saved me any time... unless,
of course, it has stopped me from suffering instances of the bug
mentioned above (and there's no way to tell that, one way or the other).

Bartc

unread,
Jun 11, 2015, 6:17:08 AM6/11/15
to
On 11/06/2015 02:35, Richard Heathfield wrote:
> On 11/06/15 01:38, Stefan Ram wrote:
>> Richard Heathfield <r...@cpax.org.uk> writes:
>>> I would agree with you that the code should be as easy to read as is
>>> reasonably possible. I don't agree that adding redundant parentheses
>>> necessarily improves readability.
>>
>> We are living in dumbed-down times!
>>
>> Use »i++« in JavaScript, and »jslint« by Crockford will tell
>> you that this is »excessive trickiness«.
>
> That's a curious way to describe something as bland as ++. I'd have
> thought the word "idiomatic" would be more appropriate.

++ and --, when used inside expressions at least, I've always found
fiddly to implement. They don't seem quite right to use either.

I do still use them, but it feels nearly as unsatisfactory as using goto.

For example, in constructions such as this:

a[++n] = 0;
b[n] = 0;
c[n] = 0;

You have to be careful to increment n just once. If you start with
a[++n]=0 and decide you need b[] updated too, you can't just copy that
line and replace a with b; you have to fix that ++n.

And if you later decide you don't need a[] updated after all, that ++n
now has to be inherited by the next line. Or if there is only a[], but
you still need n incremented, now you need ++n. Or you want to assign
c[n[ first. etc.

It's all a lot less troublesome just writing:

++n; // apt comment that is out of place next to a[++n]
a[n] = 0;
b[n] = 0;
c[n] = 0;

The assignments are more balanced too.

--
Bartc

Bartc

unread,
Jun 11, 2015, 6:29:27 AM6/11/15
to
On 11/06/2015 01:38, Stefan Ram wrote:

> char const * english( int const a )
> { char const * result;
> if( a == 0 )result = "zero";
> if( a == 1 )result = "one";
> if( a == 2 )result = "two";
> if( a == 3 )result = "three";
> else result = "four";
> return result; }
>
> void print( int const a ){ puts( english( a )); }
>
> int main( void )
> { print( 0 ); print( 1 ); print( 2 ); print( 3 ); print( 4 ); }
>
> , they tell me that it will print »zero«, »one«, »two«,
> »three«, »four«! Can you all spot why it will not?
>
> It's actually harder to make that mistake with »?:«;
> and it's shorter:
>
> char const * english( int const a )
> { return
> a == 0 ? "zero" :
> a == 1 ? "one" :
> a == 2 ? "two" :
> a == 3 ? "three" :
> "four"; }


You think this is clearer? The correct way of writing your example is
like this, if you only want one return point (and where actual code
couldn't be better expressed as a switch or table look-up):

if ( a == 0 ) result = "zero";
else if( a == 1 ) result = "one";
else if( a == 2 ) result = "two";
else if( a == 3 ) result = "three";
else result = "four";
return result;

IMO, ?: should be used sparingly, and rarely nested, not if you want to
make it obvious what is being done.

Your use of it in a large multi-line expression following the 'return'
would raise a few eyebrows I think, when people have eventually spotted
the return at the top of the function rather than at the end as is
customary!

> . When someone can't even read »?:« or »x++«, how do you expect
> him to write any piece of non-trivial code, say code for OCR,
> a compiler, or code to navigate a car through the streets?

I'm sure all those have been done by people who have no idea what ?: is
at all.

--
Bartc

Kenny McCormack

unread,
Jun 11, 2015, 7:43:23 AM6/11/15
to
In article <mlbnrj$qnj$1...@dont-email.me>, Bartc <b...@freeuk.com> wrote:
...
>You think this is clearer? The correct way of writing your example is
>like this, if you only want one return point (and where actual code
>couldn't be better expressed as a switch or table look-up):
>
> if ( a == 0 ) result = "zero";
> else if( a == 1 ) result = "one";
> else if( a == 2 ) result = "two";
> else if( a == 3 ) result = "three";
> else result = "four";
> return result;

No, the *right* way to do this is:

/* Initializations of "numstrings" array not shown */

return numstrings[a];

That's the way I usually end up organizing these sorts of problems.

--

There are many self-professed Christians who seem to think that because
they believe in Jesus' sacrifice they can reject Jesus' teachings about
how we should treat others. In this country, they show that they reject
Jesus' teachings by voting for Republicans.

Paul N

unread,
Jun 14, 2015, 4:13:42 PM6/14/15
to
On Thursday, 11 June 2015 00:34:29 UTC+1, Richard Heathfield wrote:
> On 11/06/15 00:27, Andrew Cooper wrote:
> > On 10/06/2015 22:08, Richard Heathfield wrote:
> >> I would draw the OP's attention to the omission of parentheses from the
> >> operand of sizeof:
> >>
> >> ptr = malloc(n * sizeof *ptr);
> >>
> >> There is no more need to write sizeof(*ptr) than there is to write +(x).
> >>
> >
> > While true, it quickly gets deceptive for more complicated expressions
> > such as 'sizeof(*p)->foo', where sizeof evaluates to the size of foo,
> > rather than the size of the object pointed to by p.
>
> I don't see why this is deceptive, any more than +(*p)->foo is deceptive
> in comparison to +(*p)->foo.
>
> Could you please explain why you think it's deceptive?

If I saw 'sizeof(*p)->foo', my first thought would be along the lines of "That's wrong! Sizeof returns a size_t, how on earth can you feed that into a -> ?". I would tend to expect size_of(summat) to return the size of whatever summat was.
Message has been deleted
Message has been deleted

Philip Lantz

unread,
Jun 14, 2015, 8:52:35 PM6/14/15
to
Stefan Ram wrote:
> So, it's »deceptive« to people who don't know C.
>
> What about people who know C?

Not deceptive. However, I would prefer it with a space after sizeof.

Bill Cunningham

unread,
Jun 15, 2015, 2:26:54 PM6/15/15
to

"Richard Heathfield" <r...@cpax.org.uk> wrote in message
news:mlahfh$6b8$1...@dont-email.me...

> I would agree with you that the code should be as easy to read as is
> reasonably possible. I don't agree that adding redundant parentheses
> necessarily improves readability.

Indeed. For the earlier code I think *p is a int * isn't it? That
wouldn't need parenthesis at all I wouldn't think. Isn't it not really a
built in type? Like sizeof (int p);

Bill


Richard Heathfield

unread,
Jun 15, 2015, 2:34:51 PM6/15/15
to
On 15/06/15 19:26, Bill Cunningham wrote:
> "Richard Heathfield" <r...@cpax.org.uk> wrote in message
> news:mlahfh$6b8$1...@dont-email.me...
>
>> I would agree with you that the code should be as easy to read as is
>> reasonably possible. I don't agree that adding redundant parentheses
>> necessarily improves readability.
>
> Indeed. For the earlier code I think *p is a int * isn't it?

In the original code, p is an int *, so *p is an int. But it hardly
matters - it could be any complete object type. In fact, that's the
whole point. The pattern:

T *new = malloc(n * sizeof *new);

works correctly, whether T is int, float, time_t, or struct { char ch;
long i; double d; int (*func)(const char *); }

> That
> wouldn't need parenthesis at all I wouldn't think. Isn't it not really a
> built in type? Like sizeof (int p);

int is indeed a built-in type, but sizeof (int p) is merely a syntax
error. If you mean the size of p, use sizeof p. If you mean the size of
the type of object pointed to by p, use sizeof *p.

Bill Cunningham

unread,
Jun 15, 2015, 2:55:16 PM6/15/15
to

"Richard Heathfield" <r...@cpax.org.uk> wrote in message
news:mln5pk$2vb$1...@dont-email.me...

> int is indeed a built-in type, but sizeof (int p) is merely a syntax
> error. If you mean the size of p, use sizeof p. If you mean the size of
> the type of object pointed to by p, use sizeof *p.

I thought sizeof (int p) kind of looked funny. One could use sizeof
(int) too I would suppose. So sizeof *p is saying sizeof the "point to int"
or is the * a dereference here? But he's wanting a "dynamic array" so the
size needs to change in the code at the applicable place.

That bring up to me something else. What about sizeof (int *) is that
valid? I know I should know, but I have so many other things to do too.

Bill


Melzzzzz

unread,
Jun 15, 2015, 2:59:32 PM6/15/15
to
sizeof is runtime evaluated only on VLA's.

Richard Heathfield

unread,
Jun 15, 2015, 3:11:39 PM6/15/15
to
On 15/06/15 19:55, Bill Cunningham wrote:
> "Richard Heathfield" <r...@cpax.org.uk> wrote in message
> news:mln5pk$2vb$1...@dont-email.me...
>
>> int is indeed a built-in type, but sizeof (int p) is merely a syntax
>> error. If you mean the size of p, use sizeof p. If you mean the size of
>> the type of object pointed to by p, use sizeof *p.
>
> I thought sizeof (int p) kind of looked funny. One could use sizeof
> (int) too I would suppose. So sizeof *p is saying sizeof the "point to int"

sizeof *p means "the size of the type of object pointed to by p".

> or is the * a dereference here?

Notionally, yes, but no evaluation takes place (unless p is a
variable-length array, which it isn't in this case). The expression
sizeof *p can be thought of as: "for a pointer type p, consider the type
of the object to which p can point - what is the size of that object in
bytes?"


> But he's wanting a "dynamic array" so the
> size needs to change in the code at the applicable place.

He is *calculating* the amount of storage required for n items of a size
appropriate for storing items of the type pointed to by p. The size of
the type pointed to by p is garnered from sizeof *p, and multiplying
this by n gives the total amount of storage to be requested from malloc.

> That bring up to me something else. What about sizeof (int *) is that
> valid? I know I should know, but I have so many other things to do too.

Yes, sizeof (int *) is valid too, although I would not recommend it. It
yields the number of bytes required to store a pointer-to-int. The
problem with it is as follows:

int *p;
p = malloc(n * sizeof(int *));
if(p != NULL)
{
start filling p[0] to p[n - 1] with ints

All well and good, until the programmer decides that he actually meant
for p to be a double* instead. If he or she forgets to change the malloc
line to sizeof(double *), there may well not be enough storage to hold n
lots of double (and in fact there almost certainly won't be).

By writing:

p = malloc(n * sizeof *p);

instead, the programmer guards against this possibility because, if the
programmer changes the type of p in the declaration, the amount of
storage allocated will automatically change in line with the type change.

Bill Cunningham

unread,
Jun 15, 2015, 3:22:55 PM6/15/15
to

"Richard Heathfield" <r...@cpax.org.uk> wrote in message
news:mln7ui$c88$1...@dont-email.me...
Got it. Now if I can just remeber this if I ever need it ;)

Bill


Philip Lantz

unread,
Jun 16, 2015, 3:12:14 AM6/16/15
to
Richard Heathfield wrote:
> Bill Cunningham wrote:
> > That bring up to me something else. What about sizeof (int *) is that
> > valid? I know I should know, but I have so many other things to do too.
>
> Yes, sizeof (int *) is valid too, although I would not recommend it. It
> yields the number of bytes required to store a pointer-to-int. The
> problem with it is as follows:
>
> int *p;
> p = malloc(n * sizeof(int *));
> if(p != NULL)
> {
> start filling p[0] to p[n - 1] with ints
>
> All well and good, until the programmer decides that he actually meant
> for p to be a double* instead. If he or she forgets to change the malloc
> line to sizeof(double *), there may well not be enough storage to hold n
> lots of double (and in fact there almost certainly won't be).
>
> By writing:
>
> p = malloc(n * sizeof *p);
>
> instead, the programmer guards against this possibility because, if the
> programmer changes the type of p in the declaration, the amount of
> storage allocated will automatically change in line with the type change.

Not to mention the fact that you allocated space for n pointers to int
but filled it with n ints.


Richard Heathfield

unread,
Jun 16, 2015, 5:12:57 AM6/16/15
to
Er, yes, I did, didn't I? See how easily it goes wrong when one departs
from well-established coding practices?

Philip Lantz

unread,
Jun 16, 2015, 12:12:53 PM6/16/15
to
It is such an excellent demonstration of the point that I wasn't
completely sure you hadn't done it on purpose.

Richard Heathfield

unread,
Jun 16, 2015, 12:32:39 PM6/16/15
to
On 16/06/15 17:12, Philip Lantz wrote:
> Richard Heathfield wrote:
>> Philip Lantz wrote:
>> >
>> > Not to mention the fact that you allocated space for n pointers to int
>> > but filled it with n ints.
>>
>> Er, yes, I did, didn't I? See how easily it goes wrong when one departs
>> from well-established coding practices?
>
> It is such an excellent demonstration of the point that I wasn't
> completely sure you hadn't done it on purpose.

I suppose it's a little late to claim that I had? :-)

David Kleinecke

unread,
Jun 16, 2015, 12:51:42 PM6/16/15
to
One way to think of it is that "sizeof (int)" is the sizeof operator
acting on a type cast and "sizeof x" is the operator acting on a
variable (like "& x") - and to forget that "sizeof (x)" is possible.

Rick C. Hodgin

unread,
Jun 16, 2015, 1:51:27 PM6/16/15
to
On Tuesday, June 16, 2015 at 12:51:42 PM UTC-4, David Kleinecke wrote:
> One way to think of it is that "sizeof (int)" is the sizeof operator
> acting on a type cast and "sizeof x" is the operator acting on a
> variable (like "& x") - and to forget that "sizeof (x)" is possible.

It's why sizeof should always be sizeof(), and never sizeof. I feel
the same way about return (it should always be return() rather than
return, and the same for other similar keywords).

Enclosing in parentheses removes ambiguity and helps document exactly
what's happening without needing to have a comprehensive understanding
of the peculiarities of syntax on certain compiler keywords.

Best regards,
Rick C. Hodgin

Keith Thompson

unread,
Jun 16, 2015, 2:05:49 PM6/16/15
to
David Kleinecke <dklei...@gmail.com> writes:
[...]
> One way to think of it is that "sizeof (int)" is the sizeof operator
> acting on a type cast and "sizeof x" is the operator acting on a
> variable (like "& x") - and to forget that "sizeof (x)" is possible.

That is, in my humble opinion, a misleading way to think about it.

A cast operator and the sizeof operator applied to a type name
both happen to use a similar syntax, a type name in parentheses,
but in very different contexts. (Compound literals also use a
type name in parentheses, but it's neither preceded by a `sizeof`
operator nor followed by an expression.)

In `sizeof (int)`, the `(int)` is not a cast operator, any more than
the comma in `func(x, y)` is a comma operator or the `*` in `*ptr`
is a multiplication operator. C re-uses punctuation characters in
diferent contexts, and their meaning is highly context-specific.

As for `sizeof x`, that's a `sizeof` operator applied to an
*expression* (specifically, the grammar requires a *unary-expression*
in that context). In this case, the expression happens to be the
name of an object, but for example `sizeof 42` is equally valid.
A parenthesized expression is a unary-expression, so `sizeof (x)`
is also valid, but personally I prefer to add parentheses only
when they're necessary for grouping or when they improve clarity.
I probably wouldn't write `sizeof x ++`, but if I felt the need to
do so I might write it as `sizeof (x++)` just to make it obvious
what the `sizeof` applies to.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Richard Heathfield

unread,
Jun 16, 2015, 2:14:50 PM6/16/15
to
On 16/06/15 18:51, Rick C. Hodgin wrote:
> On Tuesday, June 16, 2015 at 12:51:42 PM UTC-4, David Kleinecke wrote:
>> One way to think of it is that "sizeof (int)" is the sizeof operator
>> acting on a type cast and "sizeof x" is the operator acting on a
>> variable (like "& x") - and to forget that "sizeof (x)" is possible.
>
> It's why sizeof should always be sizeof(), and never sizeof.

The sizeof operator is an operator, not a function call. It is almost
never necessary to use parentheses for sizeof in well-written C code. It
adds no value, and distracts the reader. You are entitled to your
opinion, of course, but I can't say I find it a helpful one.

> I feel
> the same way about return (it should always be return() rather than
> return, and the same for other similar keywords).

Again I must disagree. For one thing, it doesn't work in void functions;
return() is a syntax error. So you /can't/ always use return(). What's
more, it adds no value, and distracts the reader. Again, you are
entitled to your opinion, but it is not one to which I could subscribe.

> Enclosing in parentheses removes ambiguity and helps document exactly
> what's happening without needing to have a comprehensive understanding
> of the peculiarities of syntax on certain compiler keywords.

There is no particularly significant peculiarity of syntax in either
sizeof or return. The only very minor peculiarity of sizeof is that it
accepts a parenthesised type as an operand. But the parentheses /are/
the oddity. If you take the size of objects rather than types, the
peculiarity almost never appears.

There is a case for using parentheses to make the intended
operand-operator groupings clearer to the reader where the precedence
isn't necessarily one that is widely memorised:

w = x << y | z; /* clear */
w = (x << y) | z; /* clearER, if the reader's in a hurry */

But parenthesising operands for the sake of it:

++(i);

is just silly.

James Kuyper

unread,
Jun 16, 2015, 2:15:19 PM6/16/15
to
On 06/16/2015 02:05 PM, Keith Thompson wrote:
> David Kleinecke <dklei...@gmail.com> writes:
> [...]
>> One way to think of it is that "sizeof (int)" is the sizeof operator
>> acting on a type cast and "sizeof x" is the operator acting on a
>> variable (like "& x") - and to forget that "sizeof (x)" is possible.
>
> That is, in my humble opinion, a misleading way to think about it.

The key thing about it that is misleading is that a cast operator can
only occur as part of a cast expression, and must therefore always be
followed by either a unary-expression or another cast-expression
(6.5.4p1). When occurring in a sizeof-expression, the parenthesized type
name must NOT be followed by a unary- or cast-expression. If it were, it
would be a syntax error (6.5.3p1).

Ben Bacarisse

unread,
Jun 16, 2015, 2:15:27 PM6/16/15
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:

> On Tuesday, June 16, 2015 at 12:51:42 PM UTC-4, David Kleinecke wrote:
>> One way to think of it is that "sizeof (int)" is the sizeof operator
>> acting on a type cast and "sizeof x" is the operator acting on a
>> variable (like "& x") - and to forget that "sizeof (x)" is possible.
>
> It's why sizeof should always be sizeof(), and never sizeof. I feel
> the same way about return (it should always be return() rather than
> return, and the same for other similar keywords).

Do you write long(x); ++(p) and/or *(p) all the time?

> Enclosing in parentheses removes ambiguity and helps document exactly
> what's happening without needing to have a comprehensive understanding
> of the peculiarities of syntax on certain compiler keywords.

What possible ambiguity is there in return 42; that is dispelled by
writing return(42);? (Or pick your own example if I've
over-simplified.)

--
Ben.

Rick C. Hodgin

unread,
Jun 16, 2015, 2:35:05 PM6/16/15
to
On Tuesday, June 16, 2015 at 2:15:27 PM UTC-4, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
>
> > On Tuesday, June 16, 2015 at 12:51:42 PM UTC-4, David Kleinecke wrote:
> >> One way to think of it is that "sizeof (int)" is the sizeof operator
> >> acting on a type cast and "sizeof x" is the operator acting on a
> >> variable (like "& x") - and to forget that "sizeof (x)" is possible.
> >
> > It's why sizeof should always be sizeof(), and never sizeof. I feel
> > the same way about return (it should always be return() rather than
> > return, and the same for other similar keywords).
>
> Do you write long(x); ++(p) and/or *(p) all the time?

Yes. Every time. :-)

No, of course not. But I do write it on things like sizeof(), and
other similar things because I do look at them as a type of function.

These operators take some input and return a value there in immediate
context. They do so with a name and not a character or character set.
And just because they don't go through runtime code is of no real
difference to me because from a source code point of view I am giving
sizeof some input, and it is giving me some output. As such ... function,
just one that happens to be a compile-time function, rather than runtime.

> > Enclosing in parentheses removes ambiguity and helps document exactly
> > what's happening without needing to have a comprehensive understanding
> > of the peculiarities of syntax on certain compiler keywords.
>
> What possible ambiguity is there in return 42; that is dispelled by
> writing return(42);? (Or pick your own example if I've
> over-simplified.)

None. There's also no ambiguity in return x; or return result; I
prefer for it to be return(42);, return(x), and return(result). I
view those also as functions because I am giving it some input, and
it is giving me an output (which happens to be the same value, though
in some cases it is cast through a function, such as "return(2);" when
2 must be translated to a float. As such ... function, just one that
happens to be a compile-time function, rather than runtime.

It's my personal taste on this matter, but I believe there's some real
foundation there as these various named things actually can perform
functions.

Kenny McCormack

unread,
Jun 16, 2015, 2:38:28 PM6/16/15
to
In article <d880c856-c620-47d3...@googlegroups.com>,
Leader Kiki is not going to like this.

--
One of the best lines I've heard lately:

Obama could cure cancer tomorrow, and the Republicans would be
complaining that he had ruined the pharmaceutical business.

(Heard on Stephanie Miller = but the sad thing is that there is an awful lot
of direct truth in it. We've constructed an economy in which eliminating
cancer would be a horrible disaster. There are many other such examples.)

Rick C. Hodgin

unread,
Jun 16, 2015, 2:43:32 PM6/16/15
to
On Tuesday, June 16, 2015 at 2:14:50 PM UTC-4, Richard Heathfield wrote:
> On 16/06/15 18:51, Rick C. Hodgin wrote:
> > On Tuesday, June 16, 2015 at 12:51:42 PM UTC-4, David Kleinecke wrote:
> >> One way to think of it is that "sizeof (int)" is the sizeof operator
> >> acting on a type cast and "sizeof x" is the operator acting on a
> >> variable (like "& x") - and to forget that "sizeof (x)" is possible.
> >
> > It's why sizeof should always be sizeof(), and never sizeof.
>
> The sizeof operator is an operator, not a function call. It is almost
> never necessary to use parentheses for sizeof in well-written C code. It
> adds no value, and distracts the reader. You are entitled to your
> opinion, of course, but I can't say I find it a helpful one.
>
> > I feel
> > the same way about return (it should always be return() rather than
> > return, and the same for other similar keywords).
>
> Again I must disagree. For one thing, it doesn't work in void functions;
> return() is a syntax error. So you /can't/ always use return(). What's
> more, it adds no value, and distracts the reader. Again, you are
> entitled to your opinion, but it is not one to which I could subscribe.
>
> > Enclosing in parentheses removes ambiguity and helps document exactly
> > what's happening without needing to have a comprehensive understanding
> > of the peculiarities of syntax on certain compiler keywords.
>
> There is no particularly significant peculiarity of syntax in either
> sizeof or return.

The example above explains it all:

sizeof(*p)->x

A person reading that would cringe (at least they should). It's one of
those C quirks along the lines of *tnX++; where tnX is an int*. :-)

> The only very minor peculiarity of sizeof is that it
> accepts a parenthesised type as an operand. But the parentheses /are/
> the oddity. If you take the size of objects rather than types, the
> peculiarity almost never appears.

In my code they are not an oddity. They are the norm. If I ever came
across a sizeof() without parenthesis, I would quickly fix the bug and
wonder in the back of my mind what's wrong with the compiler that it
did not generate an error on that clearly incorrect line of code I'd
written in what was obviously a lucid-free moment. :-)

> There is a case for using parentheses to make the intended
> operand-operator groupings clearer to the reader where the precedence
> isn't necessarily one that is widely memorised:
>
> w = x << y | z; /* clear */
> w = (x << y) | z; /* clearER, if the reader's in a hurry */

I disagree that the first one is clear. It requires that someone know
the order of operations. In the second example, a person does not need
to know the order of operations and will still be able to realize that
the (x << y) must be computed first, even if they still don't know what
the << is.

> But parenthesising operands for the sake of it:
> ++(i);
> is just silly.

Agreed. However, this is always much clearer:

((a) ? b : c)

This type of expression must always be surrounded with parenthesis.
It's just the way it goes in C. To do otherwise is to do otherwise.
:-)

Rick C. Hodgin

unread,
Jun 16, 2015, 2:45:13 PM6/16/15
to
On Tuesday, June 16, 2015 at 2:38:28 PM UTC-4, Kenny McCormack wrote:
> Leader Kiki is not going to like this.

Who's Kiki? Is Kiki the "K" in this "K&R" I've been reading about? :-)

Richard Heathfield

unread,
Jun 16, 2015, 3:04:05 PM6/16/15
to
On 16/06/15 19:43, Rick C. Hodgin wrote:

<snip>

> The example above explains it all:
>
> sizeof(*p)->x
>
> A person reading that would cringe (at least they should).

I don't see why. It seems pretty clear to me. p is a pointer to a
pointer to struct. We want to deref the "outer" pointer to get at the
inner pointer, deref that using -> to get an object x, and find that
object's size. That C can say such a complicated thing so easily is a
good thing. I am not convinced that sizeof((*p)->x) is clearer!

> It's one of
> those C quirks along the lines of *tnX++; where tnX is an int*. :-)

Well, it's certainly true that it is legal, in C, to produce a result
that you then don't use. This is sometimes useful for the side effects
(for example, when calling printf, we rarely bother to use the value it
returns). But in *tnX++; the * is of course without merit.

>
>> The only very minor peculiarity of sizeof is that it
>> accepts a parenthesised type as an operand. But the parentheses /are/
>> the oddity. If you take the size of objects rather than types, the
>> peculiarity almost never appears.
>
> In my code they are not an oddity. They are the norm.

Since I don't anticipate that either of us is likely to be maintaining
the other's code any time soon, I don't suppose that's a problem. :-)


> If I ever came
> across a sizeof() without parenthesis, I would quickly fix the bug

And if I ever came across a sizeof /with/ parentheses, I would pause to
make sure I could safely remove them (which, in almost all cases in my
own code, I could), and /then/ fix what you would refuse to envisage as
a bug.

>> There is a case for using parentheses to make the intended
>> operand-operator groupings clearer to the reader where the precedence
>> isn't necessarily one that is widely memorised:
>>
>> w = x << y | z; /* clear */
>> w = (x << y) | z; /* clearER, if the reader's in a hurry */
>
> I disagree that the first one is clear. It requires that someone know
> the order of operations.

That's why the second one is clearER.

> In the second example, a person does not need
> to know the order of operations and will still be able to realize that
> the (x << y) must be computed first, even if they still don't know what
> the << is.

If they don't know what << is, they've got no business editing
production code. But they can be forgiven for not memorising the
relative precedence of << and |.

>> But parenthesising operands for the sake of it:
>> ++(i);
>> is just silly.
>
> Agreed. However, this is always much clearer:
>
> ((a) ? b : c)

I'd /almost/ agree with you there. I just wouldn't go quite so far as to
say "always".

Ben Bacarisse

unread,
Jun 16, 2015, 3:28:32 PM6/16/15
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:

> On Tuesday, June 16, 2015 at 2:15:27 PM UTC-4, Ben Bacarisse wrote:
>> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
>>
>> > On Tuesday, June 16, 2015 at 12:51:42 PM UTC-4, David Kleinecke wrote:
>> >> One way to think of it is that "sizeof (int)" is the sizeof operator
>> >> acting on a type cast and "sizeof x" is the operator acting on a
>> >> variable (like "& x") - and to forget that "sizeof (x)" is possible.
>> >
>> > It's why sizeof should always be sizeof(), and never sizeof. I feel
>> > the same way about return (it should always be return() rather than
>> > return, and the same for other similar keywords).
>>
>> Do you write long(x); ++(p) and/or *(p) all the time?
>
> Yes. Every time. :-)
>
> No, of course not. But I do write it on things like sizeof(), and
> other similar things because I do look at them as a type of function.
>
> These operators take some input and return a value there in immediate
> context. They do so with a name and not a character or character set.
> And just because they don't go through runtime code is of no real
> difference to me because from a source code point of view I am giving
> sizeof some input, and it is giving me some output. As such ... function,
> just one that happens to be a compile-time function, rather than
> runtime.

Would it be fair, then, to say that it's just because sizeof is an
operator written using letters that you want to write it like a function
call?

For me, the very fact that it is so different to a function call is the
reason I've moved more and more towards not writing like one.

>> > Enclosing in parentheses removes ambiguity and helps document
>> > exactly what's happening without needing to have a comprehensive
>> > understanding of the peculiarities of syntax on certain compiler
>> > keywords.
>>
>> What possible ambiguity is there in return 42; that is dispelled by
>> writing return(42);? (Or pick your own example if I've
>> over-simplified.)
>
> None.

OK, but you can see, I hope, why I might have thought otherwise. You
said, after all, "Enclosing in parentheses removes ambiguity" so it not
unreasonable of me to think you though the ()s removed some ambiguity.

> There's also no ambiguity in return x; or return result; I
> prefer for it to be return(42);, return(x), and return(result). I
> view those also as functions because I am giving it some input, and
> it is giving me an output (which happens to be the same value, though
> in some cases it is cast through a function, such as "return(2);" when
> 2 must be translated to a float. As such ... function, just one that
> happens to be a compile-time function, rather than runtime.

Ah. If you think of return as a function we are on different planets.

> It's my personal taste on this matter, but I believe there's some real
> foundation there as these various named things actually can perform
> functions.

Yes, of course. I ask simply because I am so often surprised by the
distance between plants.

--
Ben.

James Kuyper

unread,
Jun 16, 2015, 3:42:36 PM6/16/15
to
On 06/16/2015 03:28 PM, Ben Bacarisse wrote:
...
> Would it be fair, then, to say that it's just because sizeof is an
> operator written using letters that you want to write it like a function
> call?
>
> For me, the very fact that it is so different to a function call is the
> reason I've moved more and more towards not writing like one.

All of the following keywords introduced in C2011 use the same type of
syntax as a function call, but none of them are functions as far as C is
concerned. How do you feel about them? _Alignas, _Alignof, _Atomic,
_Generic, _Static_assert.

_Alignof is the only one of those that is described as an operator. Only
_Alignof and _Generic form expressions.

glen herrmannsfeldt

unread,
Jun 16, 2015, 3:45:52 PM6/16/15
to
Ben Bacarisse <ben.u...@bsb.me.uk> wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
(snip, someone wrote)
>>> Do you write long(x); ++(p) and/or *(p) all the time?

>> Yes. Every time. :-)

>> No, of course not. But I do write it on things like sizeof(), and
>> other similar things because I do look at them as a type of function.

(snip)

> Would it be fair, then, to say that it's just because sizeof is an
> operator written using letters that you want to write it like a function
> call?

Having written both C and Fortran, it isn't so obvious what should
be a function and what should be an operator.

Fortran has the MOD function, C has the % operator.

Fortran has the ** operator, C has the pow() function.

And, for that matter, Fortran now has the C_SIZEOF function.

-- glen

Rick C. Hodgin

unread,
Jun 16, 2015, 4:03:35 PM6/16/15
to
On Tuesday, June 16, 2015 at 3:28:32 PM UTC-4, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> > These operators take some input and return a value there in immediate
> > context. They do so with a name and not a character or character set.
> > And just because they don't go through runtime code is of no real
> > difference to me because from a source code point of view I am giving
> > sizeof some input, and it is giving me some output. As such ... function,
> > just one that happens to be a compile-time function, rather than
> > runtime.
>
> Would it be fair, then, to say that it's just because sizeof is an
> operator written using letters that you want to write it like a function
> call?

It's because of its operation, and because it's written using letters.
I don't think of typedef as a function, for example, though I do think
the syntax for typedef is confusing and I always find myself thinking
my way through non-trivial typedefs rather than garnering their meaning
at a glance.

This would make more sense to me:

typedef (struct R_) R;
typedef (unsigned char) u8;

Than this:

typedef struct R_ R;
typedef unsigned char u8;

At a glance my brain isolates the components of the first, whereas I
must read through the second, and it's just more difficult for me.

As it is I use this to accomplish the same thing (a visual cue to
help my brain isolate the two at a glance):

typedef struct R_ R;
typedef unsigned char u8;

It now automatically groups things into columns, more easily
identifying subtle differences on each line.

> For me, the very fact that it is so different to a function call is the
> reason I've moved more and more towards not writing like one.

I don't think it's really that different from a function call. I think
it's only different when you don't use its function call-like syntax
form, and then it's nothing like a function call, and, in my opinion,
crosses the line into ambiguity land.

I just like to see input and output. I don't like those things to have
other meanings, but to be visualized mentally as real "machines" doing
"real work."

> >> > Enclosing in parentheses removes ambiguity and helps document
> >> > exactly what's happening without needing to have a comprehensive
> >> > understanding of the peculiarities of syntax on certain compiler
> >> > keywords.
> >>
> >> What possible ambiguity is there in return 42; that is dispelled by
> >> writing return(42);? (Or pick your own example if I've
> >> over-simplified.)
> >
> > None.
>
> OK, but you can see, I hope, why I might have thought otherwise. You
> said, after all, "Enclosing in parentheses removes ambiguity" so it not
> unreasonable of me to think you though the ()s removed some ambiguity.

I would argue that "return(42);" does remove ambiguity over "return 42;".
It's just that the level of ambiguity on that single source code line
containing "remove 42;" is very very low, and well below the threshold
of needing any kind of parenthesis prop. However, "return(42);" is still
less ambiguous in my opinion.

As a result, I use return(x); everywhere in source code.

> > There's also no ambiguity in return x; or return result; I
> > prefer for it to be return(42);, return(x), and return(result). I
> > view those also as functions because I am giving it some input, and
> > it is giving me an output (which happens to be the same value, though
> > in some cases it is cast through a function, such as "return(2);" when
> > 2 must be translated to a float. As such ... function, just one that
> > happens to be a compile-time function, rather than runtime.
>
> Ah. If you think of return as a function we are on different planets.

Same planet. Different points of view looking at the same thing.

I place greater emphasis on the thing than on the convention. The
fact is return does operate on the input provided to it, potentially
converting it into something else. I view that as a function, because
in order to conduct that translation, some function is performed on my
source code. Whether it happens at runtime or compile-time is not
really something I need to care about. I just expect it to work as I've
indicated by source code, and to that end for ease of human reading, I
use parentheses.

> > It's my personal taste on this matter, but I believe there's some real
> > foundation there as these various named things actually can perform
> > functions.
>
> Yes, of course. I ask simply because I am so often surprised by the
> distance between plants.

Plants or planets? I ask because they're on much different scales,
and in reading your reply I'm trying to determine if it's centimeters
or AUs which surprise you. I hope it's not centimeters because I could
envision you then walking around, seeing the various things move all
around you, and then (because of the endless state of surprise) not
getting much done.

-----
FWIW, Ben, I really enjoy your posts. You have a keen knowledge and
insight and I appreciate it. I feel the same way about several people
in this group, not the least of which is Keith Thompson (who I believe
has me on a news reader blacklist LOL!).

Keith Thompson

unread,
Jun 16, 2015, 4:18:59 PM6/16/15
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:
> On Tuesday, June 16, 2015 at 2:15:27 PM UTC-4, Ben Bacarisse wrote:
>> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
>>
>> > On Tuesday, June 16, 2015 at 12:51:42 PM UTC-4, David Kleinecke wrote:
>> >> One way to think of it is that "sizeof (int)" is the sizeof operator
>> >> acting on a type cast and "sizeof x" is the operator acting on a
>> >> variable (like "& x") - and to forget that "sizeof (x)" is possible.
>> >
>> > It's why sizeof should always be sizeof(), and never sizeof. I feel
>> > the same way about return (it should always be return() rather than
>> > return, and the same for other similar keywords).
>>
>> Do you write long(x); ++(p) and/or *(p) all the time?
>
> Yes. Every time. :-)
>
> No, of course not. But I do write it on things like sizeof(), and
> other similar things because I do look at them as a type of function.

Well there's your problem right there.

'sizeof" is not a function (nor is it a macro). It's an operator
whose symbol happens to be a keyword. It behaves in a number of
ways that are very different from the way functions behave: the
operand is usually not evaluated, the result depends only on the
type of the operand, and so forth.

The only things that's special about `sizeof` relative to other
operators are that (a) its symbol happens to be a keyword rather
than punctuation, and (b) its operand (not argument) can be either
an expression or a parenthesized type name (note that functions
cannot take type names as arguments).

Imagine a language that's identical to C, except that it spells
`sizeof` as `$"` Would you still insist on writing `$(x)`, or
would you be willing to write `$ x` or `$x`?

You can construct a mental model that treats "sizeof" as if it
were a function. If you do so carefully enough, and keep in mind
the special cases that result from the inconsistencies between
that model and reality, you can write consistent and correct code.
But IMHO that's a lot more effort than just learning what "sizeof"
really is. To do it reliably, you have to understand both your
mental model and the actual syntax and semantics of the language,
so you can avoid the inconsistencies.

[...]

> None. There's also no ambiguity in return x; or return result; I
> prefer for it to be return(42);, return(x), and return(result). I
> view those also as functions because I am giving it some input, and
> it is giving me an output (which happens to be the same value, though
> in some cases it is cast through a function, such as "return(2);" when
> 2 must be translated to a float. As such ... function, just one that
> happens to be a compile-time function, rather than runtime.

Similarly, "return" is a keyword, not a function, and it's used
as part of a "return statement", which has its own unique syntax
that's not related to function call syntax.

A return statement, unlike a function call, doesn't yield a result;
you can't write `x = return 42;`. It causes the function in which
it occurs to return a result, which then becomes the value yielded
by the function call expression. *Very* different.

[...]

Keith Thompson

unread,
Jun 16, 2015, 4:22:42 PM6/16/15
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:
> On Tuesday, June 16, 2015 at 2:38:28 PM UTC-4, Kenny McCormack wrote:
>> Leader Kiki is not going to like this.
>
> Who's Kiki? Is Kiki the "K" in this "K&R" I've been reading about? :-)

"Kiki" seems to be this troll's childish nickname for me. He's been
trying to bully me for years. I suggest ignoring him.

Richard Heathfield

unread,
Jun 16, 2015, 4:30:31 PM6/16/15
to
On 16/06/15 21:18, Keith Thompson wrote:

<snip>

> Similarly, "return" is a keyword, not a function, and it's used
> as part of a "return statement", which has its own unique syntax
> that's not related to function call syntax.

In fact, we run into considerable difficulties if we consider "return"
to be a function. A function returns either void (nothing) or a value of
a particular type. What type, then, does return() have? If it returns
void, then it cannot achieve its (general) purpose, which is to provide
the return value for a function that calls it. But if it returns any
other type, we have to answer the question of what type it should
return, and there does not seem to be a single suitable type.

And we also encounter another problem. Since return() is the mechanism
by which functions return, return() must itself call return(), and there
is no base case - it's return()s all the way down.

Keith Thompson

unread,
Jun 16, 2015, 4:35:29 PM6/16/15
to
They don't really have the same syntax as a function call.

For example, _Alignof (unlike sizeof) can only be applied to a
parenthesized type name. _Atomic can be used either by itself (as a
type specifier like "const") or followed by a parenthesized type name
(which makes it a type specifier); neither is particularly
function-like. _Generic is followed by some stuff in parentheses, but
that stuff is not a sequence of expressions separated by commas. And so
forth.

Rick C. Hodgin

unread,
Jun 16, 2015, 4:43:12 PM6/16/15
to
On Tuesday, June 16, 2015 at 4:18:59 PM UTC-4, Keith Thompson wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> > On Tuesday, June 16, 2015 at 2:15:27 PM UTC-4, Ben Bacarisse wrote:
> >> Do you write long(x); ++(p) and/or *(p) all the time?
> > No, of course not. But I do write it on things like sizeof(), and
> > other similar things because I do look at them as a type of function.
>
> Well there's your problem right there.
>
> 'sizeof" is not a function (nor is it a macro). It's an operator
> whose symbol happens to be a keyword. It behaves in a number of
> ways that are very different from the way functions behave: the
> operand is usually not evaluated, the result depends only on the
> type of the operand, and so forth.
>
> The only things that's special about `sizeof` relative to other
> operators are that (a) its symbol happens to be a keyword rather
> than punctuation, and (b) its operand (not argument) can be either
> an expression or a parenthesized type name (note that functions
> cannot take type names as arguments).
>
> Imagine a language that's identical to C, except that it spells
> `sizeof` as `$"` Would you still insist on writing `$(x)`, or
> would you be willing to write `$ x` or `$x`?

I would write this every time:

$((*p)->x)

Every time. Without reservation. Unless I was threatened in some
way, in which case I would probably yield.

> You can construct a mental model that treats "sizeof" as if it
> were a function. If you do so carefully enough, and keep in mind
> the special cases that result from the inconsistencies between
> that model and reality, you can write consistent and correct code.
> But IMHO that's a lot more effort than just learning what "sizeof"
> really is. To do it reliably, you have to understand both your
> mental model and the actual syntax and semantics of the language,
> so you can avoid the inconsistencies.

I have never found an inconsistency in using that form. I'd be curious
to hear of one which could exist, after which I will likely explain
further how I would never code in that way. :-)

> > None. There's also no ambiguity in return x; or return result; I
> > prefer for it to be return(42);, return(x), and return(result). I
> > view those also as functions because I am giving it some input, and
> > it is giving me an output (which happens to be the same value, though
> > in some cases it is cast through a function, such as "return(2);" when
> > 2 must be translated to a float. As such ... function, just one that
> > happens to be a compile-time function, rather than runtime.
>
> Similarly, "return" is a keyword, not a function, and it's used
> as part of a "return statement", which has its own unique syntax
> that's not related to function call syntax.
>
> A return statement, unlike a function call, doesn't yield a result;
> you can't write `x = return 42;`. It causes the function in which
> it occurs to return a result, which then becomes the value yielded
> by the function call expression. *Very* different.

I see it as not different, because ... the "x = return 42;" operation
you state here really does exist, but it comes in the form "x = f();"
where the last thing done in f() for source code is "return 42;" which
then does assign to the value x and initiates whatever machine
mechanics are required to return from the function call, so as to
return control to the remainder of the mechanics first initiated in
the mechanics of executing f(), to then use that value for the
assignment.

"return" mechanically prepares something in a particular way so that
it can be received at the left-side of the thing which called it,
which is itself part of a mechanical process of execution. It is
all part of the same thing, and it is all some kind of logical
function.

I view it very much as a function because instead of taking a and b
and performing some discrete operation on it which yields an immediate
result, it takes input and executes several steps (some exposed only
internally within the machine, some externally in assembly opcodes),
to take that input value and wield it in such a way that it is then
usable beyond.

I've gotten by 45 years thinking and writing code this way ... well,
probably only 25 years or so because there was that time in there
before I'd ever heard of C, let alone coded in it.

BTW, 42 was Jackie Robinson's jersey number. I've often wondered if
that wasn't Adams' impetus in using that number for the answer to
why the universe exists ... ie, breaking down barriers, working
together, and doing our best.

Richard Heathfield

unread,
Jun 16, 2015, 4:52:43 PM6/16/15
to
On 16/06/15 21:43, Rick C. Hodgin wrote:
> On Tuesday, June 16, 2015 at 4:18:59 PM UTC-4, Keith Thompson wrote:

<snip>

>> You can construct a mental model that treats "sizeof" as if it
>> were a function. If you do so carefully enough, and keep in mind
>> the special cases that result from the inconsistencies between
>> that model and reality, you can write consistent and correct code.
>> But IMHO that's a lot more effort than just learning what "sizeof"
>> really is. To do it reliably, you have to understand both your
>> mental model and the actual syntax and semantics of the language,
>> so you can avoid the inconsistencies.
>
> I have never found an inconsistency in using that form. I'd be curious
> to hear of one which could exist, after which I will likely explain
> further how I would never code in that way. :-)

If you treat sizeof like a function, you can't pass it a type name as an
argument, because functions don't accept type names as arguments. So, to
be consistent in treating sizeof as a function, you would have to
refrain from "passing" type names to it (in which case, by the by, the
parentheses are never, ever required).

<snip>

> BTW, 42 was Jackie Robinson's jersey number. I've often wondered if
> that wasn't Adams' impetus in using that number for the answer to
> why the universe exists ... ie, breaking down barriers, working
> together, and doing our best.

He is on record as saying that he picked 42 merely because it was a
perfectly ordinary number, a number that you could, without
embarrassment, take home to meet your parents. I doubt whether he'd ever
heard of Jackie Robinson, who retired from playing baseball when DNA was
about 4 years old. In fact, it's probably fair to say that only a tiny
minority of English people have ever heard of Jackie Robinson, of which
minority I was not a member until just now.

Rick C. Hodgin

unread,
Jun 16, 2015, 4:53:25 PM6/16/15
to
On Tuesday, June 16, 2015 at 4:30:31 PM UTC-4, Richard Heathfield wrote:
> On 16/06/15 21:18, Keith Thompson wrote:
>
> <snip>
>
> > Similarly, "return" is a keyword, not a function, and it's used
> > as part of a "return statement", which has its own unique syntax
> > that's not related to function call syntax.
>
> In fact, we run into considerable difficulties if we consider "return"
> to be a function. A function returns either void (nothing) or a value of
> a particular type. What type, then, does return() have? If it returns
> void, then it cannot achieve its (general) purpose, which is to provide
> the return value for a function that calls it.

That is not its function. That is one form of its function. It has
another function (overloaded) which allows it to execute the same
mechanics that are required to return control to the caller, but without
preparing the return value. And I'd wager that there are flavors of C
out there that, were we to examine the assembly code they generate,
actually do return an implicit 0 value in the case of a void return,
which is then simply discarded by the caller.

> But if it returns any
> other type, we have to answer the question of what type it should
> return, and there does not seem to be a single suitable type.

Overloading. A function created at compile-time by the compiler to
conduct those various tasks.

> And we also encounter another problem. Since return() is the mechanism
> by which functions return, return() must itself call return(), and there
> is no base case - it's return()s all the way down.

Nonsense. :-) Return is called, which interrogates the machine in the
manner required to execute the functionality of the return() function,
which is to leave this place and go back to where it came from. That
is a function as much as cos(x) is a function.

cos(x) will load some value x into the machine's hardware, or into the
software emulation load value, interrogate the machine to compute the
result, and store that result in the location that machine uses to
convey values through expressions.

return() will load some value x into the machine's hardware, or not if
it's void, and then interrogate the machine to execute the hard return
back to the caller, which completes its part of the transaction which
then completes upon return where that value is then possibly retrieved,
but ultimately employed in whatever way is required to proceed through
the expression, just as in cos(x).

cos(x) calls a function which may translate into direct machine hardware
instructions (assembly, load x, cos, store t).

return(x) calls a function which does translate into direct machine
hardware instructions, optionally storing the result given it as input,
and then interrogating the machine to perform the hard return.

I see it as a full function, but with one limitation: It is terminal.
It cannot be used as:

y = cos(return(42));

...because the return function will preclude the continuation of that
code, and therefore must generate a syntax error in this case because
the surrounding expression cannot be executed with the mechanical
limitations of that which return does.

James Kuyper

unread,
Jun 16, 2015, 4:59:22 PM6/16/15
to
On 06/16/2015 04:35 PM, Keith Thompson wrote:
> James Kuyper <james...@verizon.net> writes:
>> On 06/16/2015 03:28 PM, Ben Bacarisse wrote:
...
>>> For me, the very fact that it is so different to a function call is the
>>> reason I've moved more and more towards not writing like one.
>>
>> All of the following keywords introduced in C2011 use the same type of
>> syntax as a function call, but none of them are functions as far as C is
>> concerned. How do you feel about them? _Alignas, _Alignof, _Atomic,
>> _Generic, _Static_assert.
>>
>> _Alignof is the only one of those that is described as an operator. Only
>> _Alignof and _Generic form expressions.
>
> They don't really have the same syntax as a function call.
>
> For example, _Alignof (unlike sizeof) can only be applied to a
> parenthesized type name. _Atomic can be used either by itself (as a
> type specifier like "const") or followed by a parenthesized type name
> (which makes it a type specifier); neither is particularly
> function-like. _Generic is followed by some stuff in parentheses, but
> that stuff is not a sequence of expressions separated by commas. And so
> forth.

True. However, someone who can look at sizeof(int) and conclude that it
"looks like a function" can only have done so by concentrating his
attention on the '(' and ')', and ignoring everything that occurs
between them. The same "analysis" applied to _Alignof() and _Generic()
should therefore reach the same conclusion.

In order to conclude that _Alignas() or _Atomic() "looks like a
function", you'd also have to ignore the fact that they don't have a
value, and can only be used as declaration specifiers. In order to reach
that conclusion about _Static_assert(), you'd have to ignore the fact
that it considered to be a declaration. However, I have confidence that
most people who would think that sizeof(long double) looks like a
function call could manage somehow to consider those to be function
calls as well.

Rick C. Hodgin

unread,
Jun 16, 2015, 5:01:16 PM6/16/15
to
On Tuesday, June 16, 2015 at 4:52:43 PM UTC-4, Richard Heathfield wrote:
> On 16/06/15 21:43, Rick C. Hodgin wrote:
> > On Tuesday, June 16, 2015 at 4:18:59 PM UTC-4, Keith Thompson wrote:
> >> You can construct a mental model that treats "sizeof" as if it
> >> were a function. If you do so carefully enough, and keep in mind
> >> the special cases that result from the inconsistencies between
> >> that model and reality, you can write consistent and correct code.
> >> But IMHO that's a lot more effort than just learning what "sizeof"
> >> really is. To do it reliably, you have to understand both your
> >> mental model and the actual syntax and semantics of the language,
> >> so you can avoid the inconsistencies.
> >
> > I have never found an inconsistency in using that form. I'd be curious
> > to hear of one which could exist, after which I will likely explain
> > further how I would never code in that way. :-)
>
> If you treat sizeof like a function, you can't pass it a type name as an
> argument, because functions don't accept type names as arguments. So, to
> be consistent in treating sizeof as a function, you would have to
> refrain from "passing" type names to it (in which case, by the by, the
> parentheses are never, ever required).

The built-in functions allow for more non-variable input than do user
functions because they are computed at compile-time when everything is
known.

I don't view that as an inconsistency because it's merely a rule, like
"int f(int a)" being unable to receive a char* as input. In that case,
it would be tested at compile-time and fail.

With sizeof(), passing a type is not against its rule.

> <snip>
>
> > BTW, 42 was Jackie Robinson's jersey number. I've often wondered if
> > that wasn't Adams' impetus in using that number for the answer to
> > why the universe exists ... ie, breaking down barriers, working
> > together, and doing our best.
>
> He is on record as saying that he picked 42 merely because it was a
> perfectly ordinary number, a number that you could, without
> embarrassment, take home to meet your parents. I doubt whether he'd ever
> heard of Jackie Robinson, who retired from playing baseball when DNA was
> about 4 years old. In fact, it's probably fair to say that only a tiny
> minority of English people have ever heard of Jackie Robinson, of which
> minority I was not a member until just now.

Well ... *bang* goes that line of thinking. :-)

Dr Nick

unread,
Jun 16, 2015, 5:03:33 PM6/16/15
to
Keith Thompson <ks...@mib.org> writes:

> James Kuyper <james...@verizon.net> writes:
>> On 06/16/2015 03:28 PM, Ben Bacarisse wrote:
>> ...
>>> Would it be fair, then, to say that it's just because sizeof is an
>>> operator written using letters that you want to write it like a function
>>> call?
>>>
>>> For me, the very fact that it is so different to a function call is the
>>> reason I've moved more and more towards not writing like one.
>>
>> All of the following keywords introduced in C2011 use the same type of
>> syntax as a function call, but none of them are functions as far as C is
>> concerned. How do you feel about them? _Alignas, _Alignof, _Atomic,
>> _Generic, _Static_assert.
>>
>> _Alignof is the only one of those that is described as an operator. Only
>> _Alignof and _Generic form expressions.
>
> They don't really have the same syntax as a function call.
>
> For example, _Alignof (unlike sizeof) can only be applied to a
> parenthesized type name. [snip]

Out of sheer curiosity, why is that? Is there a reason why it couldn't
work like sizeof? After all, every expression has a type, so must also
have the alignment of that type.

Keith Thompson

unread,
Jun 16, 2015, 5:16:49 PM6/16/15
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:
> On Tuesday, June 16, 2015 at 4:18:59 PM UTC-4, Keith Thompson wrote:
[...]
>> Imagine a language that's identical to C, except that it spells
>> `sizeof` as `$"` Would you still insist on writing `$(x)`, or
>> would you be willing to write `$ x` or `$x`?
>
> I would write this every time:
>
> $((*p)->x)
>
> Every time. Without reservation. Unless I was threatened in some
> way, in which case I would probably yield.

I didn't ask about `(*p)->x` as the operand; in that moderately complex
case, parentheses might be justifed for clarity. I asked about `x` as
the operand.

Again, assuming a C-like language that spells `sizeof` as `$`. It's one
of several unary operators, all of which have punctuation characters as
their symbols. For which of the following would you feel the need to
add parentheses, and why? Assume in each case that x is of an
appropriate type. Remember, the operand is literally the identifier
`x`; that's not a stand-in for some more complicated expression.

& x
* x
+ x
- x
~ x
! x

>> You can construct a mental model that treats "sizeof" as if it
>> were a function. If you do so carefully enough, and keep in mind
>> the special cases that result from the inconsistencies between
>> that model and reality, you can write consistent and correct code.
>> But IMHO that's a lot more effort than just learning what "sizeof"
>> really is. To do it reliably, you have to understand both your
>> mental model and the actual syntax and semantics of the language,
>> so you can avoid the inconsistencies.
>
> I have never found an inconsistency in using that form. I'd be curious
> to hear of one which could exist, after which I will likely explain
> further how I would never code in that way. :-)

Do you never apply sizeof to a type? Or do you think of `sizeof(int)`
as a function call, even though `func_name(x)` would be a syntax error?

[...]

>> Similarly, "return" is a keyword, not a function, and it's used
>> as part of a "return statement", which has its own unique syntax
>> that's not related to function call syntax.
>>
>> A return statement, unlike a function call, doesn't yield a result;
>> you can't write `x = return 42;`. It causes the function in which
>> it occurs to return a result, which then becomes the value yielded
>> by the function call expression. *Very* different.
>
> I see it as not different, because ... the "x = return 42;" operation
> you state here really does exist, but it comes in the form "x = f();"
> where the last thing done in f() for source code is "return 42;" which
> then does assign to the value x and initiates whatever machine
> mechanics are required to return from the function call, so as to
> return control to the remainder of the mechanics first initiated in
> the mechanics of executing f(), to then use that value for the
> assignment.

If you stretch things enough, you can think of just about anything as a
"function". A switch statement is a "function" that takes two
arguments, an expression and a statement. A struct definition is a
function that takes a list of member declarations as arguments, with a
funny syntax. I'm sure a Lisp programmer could come up with more
examples.

I prefer to think of things that the C standard actually calls
"functions" as functions. It's a lot less effort.

Kenny McCormack

unread,
Jun 16, 2015, 5:25:59 PM6/16/15
to
In article <ln8ubjm...@nuthaus.mib.org>,
Keith Thompson <ks...@mib.org> wrote:
>"Rick C. Hodgin" <rick.c...@gmail.com> writes:
>> On Tuesday, June 16, 2015 at 2:38:28 PM UTC-4, Kenny McCormack wrote:
>>> Leader Kiki is not going to like this.
>>
>> Who's Kiki? Is Kiki the "K" in this "K&R" I've been reading about? :-)
>
>"Kiki" seems to be this troll's childish nickname for me. He's been
>trying to bully me for years. I suggest ignoring him.

I didn't invent it. It was in common usage for quite a while before I
adopted it.

--
Mike Huckabee has yet to consciously uncouple from Josh Duggar.

Keith Thompson

unread,
Jun 16, 2015, 5:27:45 PM6/16/15
to
I don't know.

I asked about it on comp.std.c a while ago, and the response from
Larry Jones was "_Alignof came from C++, so you'd have to ask them.".
C++ has "alignof" as a keyword and permits only a parenthesized
type name.

Incidentally, parts of the N1570 draft of the C++ 11 standard
incorrectly assumed that _Alignof *can* be applied to an expression
(it lists it as one of the cases where an array expression is
not converted to a pointer). That was corrected in the published
C11 standard.

Rick C. Hodgin

unread,
Jun 16, 2015, 5:39:13 PM6/16/15
to
On Tuesday, June 16, 2015 at 5:16:49 PM UTC-4, Keith Thompson wrote:
> > "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> Again, assuming a C-like language that spells `sizeof` as `$`. It's one
> of several unary operators, all of which have punctuation characters as
> their symbols. For which of the following would you feel the need to
> add parentheses, and why? Assume in each case that x is of an
> appropriate type. Remember, the operand is literally the identifier
> `x`; that's not a stand-in for some more complicated expression.
>
> & x
> * x
> + x
> - x
> ~ x
> ! x

I sometimes put a parenthesis around bitwise operations. Probably not
ever on the other ones.

> > I have never found an inconsistency in using that form. I'd be curious
> > to hear of one which could exist, after which I will likely explain
> > further how I would never code in that way. :-)
>
> Do you never apply sizeof to a type? Or do you think of `sizeof(int)`
> as a function call, even though `func_name(x)` would be a syntax error?

I hadn't considered that to be an inconsistency with other functions, but
rather a nuance of its base ability being properly applied and exposed
through its syntax.

> If you stretch things enough, you can think of just about anything as a
> "function". A switch statement is a "function" that takes two
> arguments, an expression and a statement. A struct definition is a
> function that takes a list of member declarations as arguments, with a
> funny syntax. I'm sure a Lisp programmer could come up with more
> examples.

That's actually an interesting way to think of that process. Same
with switch. I've never thought of it that way before. Interesting.

> I prefer to think of things that the C standard actually calls
> "functions" as functions. It's a lot less effort.

I understand where you're coming from. I often look at things differently.
I recognize that sizeof() can take as input types and not generate a
syntax error. I view that as its allowance of input, just as int f(int a)
can receive a wide range of input values which are all legal, but it
won't receive a char*, for example, just as it won't receive "int".

I prefer to think of things as they are rather than how they've been
conveyed by (often legacy) convention over time. It is a more effort,
but it results in a much more philosophical understanding of the thing,
and a less mechanical view of the thing.

It also comes with some detraction because such a person is often
isolated within their philosophy, which may seem fundamentally
divergent from mainstream ideas, and therefore kept at or beyond
arm's length. In short: it's lonely.

David Brown

unread,
Jun 16, 2015, 5:49:37 PM6/16/15
to
Although I am not English, I too had to look up Jackie Robinson - Rick's
post made it look like he was someone important or famous. It turns out
he played in American-only sports. I cannot imagine why anyone would
think there was a connection here with Douglas Adams, especially as he
liked the English bat-and-ball game, cricket. DNA was famous for
marvelling in the ordinary and everyday - people who did anything
special or unusual he mostly found boring.

Rick C. Hodgin

unread,
Jun 16, 2015, 5:58:26 PM6/16/15
to
He was a significant person in common U.S. history. He broke down race
barriers for the mainstream populace at a point in our history where
race was a real issue.

In 2013 they made a movie about him with a budget of $40 million:

https://en.wikipedia.org/wiki/42_%28film%29

My thinking in Adams' using his number as that answer was because of
what he had done -- brought people together in spite of adversity.
It seems to be a good answer to why the universe exists.

Ben Bacarisse

unread,
Jun 16, 2015, 8:23:04 PM6/16/15
to
James Kuyper <james...@verizon.net> writes:

> On 06/16/2015 03:28 PM, Ben Bacarisse wrote:
> ...
>> Would it be fair, then, to say that it's just because sizeof is an
>> operator written using letters that you want to write it like a function
>> call?
>>
>> For me, the very fact that it is so different to a function call is the
>> reason I've moved more and more towards not writing like one.
>
> All of the following keywords introduced in C2011 use the same type of
> syntax as a function call, but none of them are functions as far as C is
> concerned. How do you feel about them? _Alignas, _Alignof, _Atomic,
> _Generic, _Static_assert.

They don't share much syntax with a function call but insofar as they do
I think it's unfortunate. In some cases, it may be that the convenience
of capturing the syntax with a macro might have been appealing (and part
of the reason for the syntax) but I'm not sure how much of a practical
advantage this really is.

Anyway, since I write function calls like this: f(x), I can at least add
a space to write _Generic (x, int: 1, default: 0). I'd probably have
chosen _Generic (x) { int: 1; default: 0 } (but I've not given it much
thought).

> _Alignof is the only one of those that is described as an operator. Only
> _Alignof and _Generic form expressions.

--
Ben.

Dr Nick

unread,
Jun 17, 2015, 2:05:37 AM6/17/15
to
I don't think I care that much. Thanks!

> Incidentally, parts of the N1570 draft of the C++ 11 standard
> incorrectly assumed that _Alignof *can* be applied to an expression
> (it lists it as one of the cases where an array expression is
> not converted to a pointer). That was corrected in the published
> C11 standard.

Which makes it look clearly like a conscious decision and not an
oversight. Not that I've ever used it, and probably wouldn't want to use
it with an expression, but it seems pointlessly inconsistent.

Ben Bacarisse

unread,
Jun 17, 2015, 5:58:56 AM6/17/15
to
So your answer to "what possible ambiguity is there in return 42; that
is dispelled by writing return(42);" is "none", but you would, none the
less, "argue that return(42); does remove ambiguity over return 42;".

Do you mean that there is no ambiguity but, despite that, you would
argue that there was simply for the sake of arguing?

<snip>
>> Ah. If you think of return as a function we are on different planets.
>
> Same planet. Different points of view looking at the same thing.

The analogy is intended to highlight the great distance between these
vantage points.

<snip>
--
Ben.

David Brown

unread,
Jun 17, 2015, 8:10:50 AM6/17/15
to
Race is still a "real issue" in much of the USA. But while I am sure he
made his mark here, he was just one of many black Americans who refused
to be treated as second-class humans - and he was not one that was
famous enough or important enough to be known outside the USA. (I don't
mean to belittle the man or his achievements, but he simply is not
internationally known in the way Malcolm X, Martin Luther King, Mohammed
Ali or Rosa Parks are.)

Perhaps this is because his sport, baseball, is hugely popular in the
USA and almost totally irrelevant elsewhere (in the UK, it is something
kids might play in the playground between classes - called "rounders" or
"softball" - it is not something people take seriously).

>
> In 2013 they made a movie about him with a budget of $40 million:
>
> https://en.wikipedia.org/wiki/42_%28film%29
>
> My thinking in Adams' using his number as that answer was because of
> what he had done -- brought people together in spite of adversity.

That is not something that DNA was especially interested in. He liked
to tell entertaining stories about ordinary people doing extraordinary
things, and to let his imagination run wild.

(As a side note, the book which Douglas Adams wanted most to be
remembered for is not "The Hitchhikers' Guide to the Galaxy", but "Last
Chance to See" about endangered species.)

> It seems to be a good answer to why the universe exists.
>

DNA was an atheist - he was never interested in finding out why the
universe exists, and certainly would not have thought it was something
revolving around humans. A key concept of THGTTG was that the earth was
made by interstellar mice so that /they/ could find the real question to
fit the answer to life, the universe and everything. He was interested
in the question and what people think of it, and was mocking those that
took the question too seriously - but he did not think that there was
any "answer" or any point in looking for an answer.

Richard Heathfield

unread,
Jun 17, 2015, 8:20:29 AM6/17/15
to
On 17/06/15 13:10, David Brown wrote:

[Re: Jackie Robinson]

> Perhaps this is because his sport, baseball, is hugely popular in the
> USA and almost totally irrelevant elsewhere (in the UK, it is something
> kids might play in the playground between classes - called "rounders" or
> "softball" - it is not something people take seriously).

I simply *must* take issue with this. The folks at Bletchley Park took
their games of rounders *very* seriously. Disputed decisions were
commonplace, and were discussed with all the gravity normally reserved
for cracking Nazi ciphers.

Rick C. Hodgin

unread,
Jun 17, 2015, 8:58:35 AM6/17/15
to
On Wednesday, June 17, 2015 at 5:58:56 AM UTC-4, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> > I would argue that "return(42);" does remove ambiguity over "return
> > 42;".
>
> So your answer to "what possible ambiguity is there in return 42; that
> is dispelled by writing return(42);" is "none", but you would, none the
> less, "argue that return(42); does remove ambiguity over return 42;".

I can see how that would be confusing. I explained it in a later post.
"None" there means "below threshold," but not exactly 0, just not enough
to warrant any need for parenthesis. However, using parenthesis does
make it clearer.

At least that's my opinion. Add that to $1 and you could get yourself
a cup of coffee. Maybe. :-)

> Do you mean that there is no ambiguity but, despite that, you would
> argue that there was simply for the sake of arguing?

No. I apologize for my wording. I hope it's clear now.

> <snip>
> >> Ah. If you think of return as a function we are on different planets.
> > Same planet. Different points of view looking at the same thing.
>
> The analogy is intended to highlight the great distance between these
> vantage points.

Agreed. But the interesting thing about being on different planets, is
that each has its own flavor, its own atmosphere, its own history, its
own culture (or cultures). They grew up differently, but yet are both
planets. Equal in status, but different in fundamentals. And that's
okay you see, for it is the way of the entire universe.

Rick C. Hodgin

unread,
Jun 17, 2015, 9:06:03 AM6/17/15
to
David, Richard,

RE: Jackie Robinson and 42...

I apologize to you both, and to anyone else. It was a sidelong thought
which occurred to me while watching the Ken Burns series on Baseball.

For the record, I was born in 1969 and grew up hearing about Jackie
Robinson. I didn't know who he was. I didn't know he was black. I knew
that people talked about him and held him in high regard. He wasn't
talked about as often as the president, or other various things, but
he was involved in the common knowledge of that day, and in many of us
who are probably 40 or over, he is still there.

I didn't really learn about what he did until I was in my 40s, nor the
significant impact he'd had on the culture of that time. I also learned
something similar about Nichelle Nichols (Uhura from the original Star
Trek series). She also broke down barriers at a time when having a black
officer on the deck of the Federation flagship was almost unthinkable in
our culture.

These things changed our society. The altered American fundamentally at
the people level. That is why he is remembered to this day, and honored
with a movie decades after his death.

In any event, you've told me more about Douglas Adams in this thread
than I ever knew about him. I only knew he was the author of the HHGTTG
"trilogy," and that he was alive after Jackie played. When I saw
Jackie's jersey number while watching the Ken Burns baseball series, I
immediately thought to myself, "Interesting. I wonder if..." and have
come back to that though a dozen times since then.

Now that you've set me straight, I recognize I was wrong. And I again
apologize to you both, and to everyone else I might've offended with
my reference to 42 and Jackie Robinson.

I'm sorry. I hope I didn't cause you too much stress. I hope I didn't
cause you to be sad. Or angry. Or to waver in your sleep patterns. If
I did, please know that it was not my intention on this matter. It was
only my intention to throw out a thought which still, even in light of
all this "evidence" regarding Adams, seems plausible.

I hope this clears up the matter. It will likely be my last post on the
subject. I hope it will be yours as well.

David Brown

unread,
Jun 17, 2015, 10:07:22 AM6/17/15
to
On 17/06/15 15:05, Rick C. Hodgin wrote:
> David, Richard,
>
> RE: Jackie Robinson and 42...
>
> I apologize to you both, and to anyone else. It was a sidelong thought
> which occurred to me while watching the Ken Burns series on Baseball.
>

There is absolutely no reason to apologize - it should be obvious that
neither Richard nor I take any of this very seriously, nor did we expect
/you/ to take it seriously. Everyone gets ideas for about connections
when they see a coincidence, even if there is no real connection behind
it - it's human nature. All we did was let you know that it is nothing
more than coincidence, pass on some interesting trivia, and indulge in a
bit of typically British humour about sports.

> For the record, I was born in 1969 and grew up hearing about Jackie
> Robinson. I didn't know who he was. I didn't know he was black. I knew
> that people talked about him and held him in high regard. He wasn't
> talked about as often as the president, or other various things, but
> he was involved in the common knowledge of that day, and in many of us
> who are probably 40 or over, he is still there.
>
> I didn't really learn about what he did until I was in my 40s, nor the
> significant impact he'd had on the culture of that time. I also learned
> something similar about Nichelle Nichols (Uhura from the original Star
> Trek series). She also broke down barriers at a time when having a black
> officer on the deck of the Federation flagship was almost unthinkable in
> our culture.
>
> These things changed our society. The altered American fundamentally at
> the people level. That is why he is remembered to this day, and honored
> with a movie decades after his death.

It can be difficult for non-Americans to appreciate the importance of
this sort of thing. I am only a couple of years younger than you (still
over 40), but from when I was growing up there was nothing unusual about
black (or any other colour) people on TV or sports. It would never have
occurred to me that there could be something unusual about a Star Trek
officer happening to be black.

There are still some aspects of British society in which non-whites are
heavily under-represented, but I think that is more from social and
economic class than race (i.e., some jobs and positions in society are
dominated by the traditional upper class, or by "old money" - these are
out of reach to most people).

>
> In any event, you've told me more about Douglas Adams in this thread
> than I ever knew about him. I only knew he was the author of the HHGTTG
> "trilogy," and that he was alive after Jackie played. When I saw
> Jackie's jersey number while watching the Ken Burns baseball series, I
> immediately thought to myself, "Interesting. I wonder if..." and have
> come back to that though a dozen times since then.
>
> Now that you've set me straight, I recognize I was wrong. And I again
> apologize to you both, and to everyone else I might've offended with
> my reference to 42 and Jackie Robinson.
>
> I'm sorry. I hope I didn't cause you too much stress. I hope I didn't
> cause you to be sad. Or angry. Or to waver in your sleep patterns. If
> I did, please know that it was not my intention on this matter. It was
> only my intention to throw out a thought which still, even in light of
> all this "evidence" regarding Adams, seems plausible.

Don't worry so much! If anyone gave offence in this discussion, it
could only be me with my comments on baseball - I know some Americans
view it as something holy.

>
> I hope this clears up the matter. It will likely be my last post on the
> subject. I hope it will be yours as well.
>

If these discussions have woken an interest in Douglas Adams, then I
strongly recommend you read his books.

Don't watch the film version of HHGTTG - DNA spent a lot of effort
trying to stop Hollywood from ruining the job, which is why there was no
film version during his lifetime (DNA wanted a film version to be made -
just not the sort of crap that Hollywood ended up with). Adam's ashes
were barely cold before Hollywood started work on the film that almost,
but not quite, entirely missed the humour and point of the book.

But the BBC TV series is worth watching.

Richard Heathfield

unread,
Jun 17, 2015, 10:13:36 AM6/17/15
to
On 17/06/15 14:05, Rick C. Hodgin wrote:

<snip>

> Now that you've set me straight, I recognize I was wrong. And I again
> apologize to you both, and to everyone else I might've offended with
> my reference to 42 and Jackie Robinson.

Is this tongue-in-cheek? (Apologies if it isn't.) You make too much of a
trifle. I doubt very much whether anyone was offended. I certainly
wasn't. A correction was inevitable, because comp.lang.c is full of
pedants (i.e. people who care about getting it right), but I can't
imagine why anyone would have taken actual umbrage at what you wrote.

Having said that, one of the most important things I learned from
comp.lang.c is that, when you[generic] get it wrong, the smart thing is
to admit the fact sooner rather than later. (Which you did on this
occasion.)

Anyway, all's well that ends well.

<snip>

Ben Bacarisse

unread,
Jun 17, 2015, 10:46:44 AM6/17/15
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:

> On Wednesday, June 17, 2015 at 5:58:56 AM UTC-4, Ben Bacarisse wrote:
>> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
>> > I would argue that "return(42);" does remove ambiguity over "return
>> > 42;".
>>
>> So your answer to "what possible ambiguity is there in return 42; that
>> is dispelled by writing return(42);" is "none", but you would, none the
>> less, "argue that return(42); does remove ambiguity over return 42;".
>
> I can see how that would be confusing. I explained it in a later post.
> "None" there means "below threshold," but not exactly 0, just not enough
> to warrant any need for parenthesis. However, using parenthesis does
> make it clearer.

But neither "none" nor "none above the threshold" (whatever that is)
answers the question to which "none" what the answer. What is the
ambiguity you spoke of that is removed by adding the parentheses? I get
that you might simply have misspoken and meant to say "I like them" or
something like that, but you spoke of and ambiguity being removed, and I
can't see one, even if it is "below" some threshold -- I can't see it at
all -- nada.

One thing you may not know: the ()s were once required in a return
statement. Seeing them makes me think the author is using an ancient
dialect of C, and that makes go check a few things to be sure they are
not. In that rather specialised way they confuse matters for me.

<snip>
--
Ben.

Rick C. Hodgin

unread,
Jun 17, 2015, 11:14:22 AM6/17/15
to
On Wednesday, June 17, 2015 at 10:46:44 AM UTC-4, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> > On Wednesday, June 17, 2015 at 5:58:56 AM UTC-4, Ben Bacarisse wrote:
> >> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> >> > I would argue that "return(42);" does remove ambiguity over "return
> >> > 42;".
> >>
> >> So your answer to "what possible ambiguity is there in return 42; that
> >> is dispelled by writing return(42);" is "none", but you would, none the
> >> less, "argue that return(42); does remove ambiguity over return 42;".
> >
> > I can see how that would be confusing. I explained it in a later post.
> > "None" there means "below threshold," but not exactly 0, just not enough
> > to warrant any need for parenthesis. However, using parenthesis does
> > make it clearer.
>
> But neither "none" nor "none above the threshold" (whatever that is)
> answers the question to which "none" what the answer.

What is the chance of rain today?
None.
Really?
Yes, the weather forecast says no change of rain. Sunny all day.
What about meteors?
What?
Suppose a meteor comes by and alters the atmosphere in some way?
I suppose...

What about earthquakes? Volcanoes? Something that we hadn't taken
into account in our initial assessment of weather analysis?

I see your point. Okay, the chance of rain is "None," which could
of course mean there is a chance of rain in certain circumstances,
or if something unlikely happens.

So is it really "None?"
No, not really. But for all practical purposes, yes. Yes it is.
I understand.

> What is the
> ambiguity you spoke of that is removed by adding the parentheses?

It just conveys completely that the value 42 is being input into the
return, whereas "return 42;" probably conveys that meaning, and it
would be natural to conclude it does, but there's no way to be 100%
sure. It could be something like RET 42 in x86 assembly, which returns
and pops 42 bytes off the stack in the process (though I suppose one
could argue that return(42); could do the same thing).

> I get
> that you might simply have misspoken and meant to say "I like them" or
> something like that, but you spoke of and ambiguity being removed, and I
> can't see one, even if it is "below" some threshold -- I can't see it at
> all -- nada.

That's okay. Chocolate. Vanilla. They both exist for a reason.

> One thing you may not know: the ()s were once required in a return
> statement. Seeing them makes me think the author is using an ancient
> dialect of C, and that makes go check a few things to be sure they are
> not. In that rather specialised way they confuse matters for me.

I did not know that. Interesting. I know that many C compilers today
allow for the trailing , in a list because it's easier for generated
code to not remove that trailing comma and just leave it there. I
disagree with that as well because someone following along after in
that code for maintenance would wonder "Did the original developer
leave off some more data?" The same with not using the keyword "void"
in something like "int f()" instead of "int f(void)" because it's
much more difficult to accidentally type void than it is to
accidentally leave it blank. And seeing it blank also begs the
question, "Was the developer finished here? Did they mean to leave
it blank, or is this placeholder code not yet developed?"

My opinions.

> <snip>
> --
> Ben.

I also have many tools in my arsenal. Parentheses is one of them. I also
use horizontal character spacing, and vertical line spacing, and some
type of text formatting in nearby comments to draw attention, etc.

On the whole, I use parentheses far more places than they're needed
by syntax, and I do it to make it more clear in source code what's
transpiring.

I use return(42); and am happy. I use sizeof(x) and am happy. I use
other such things with parentheses and am happy. If you're happy
without them, then I'm also happy for you. Happiness all around! :-)

Rick C. Hodgin

unread,
Jun 17, 2015, 11:23:13 AM6/17/15
to
On Wednesday, June 17, 2015 at 10:07:22 AM UTC-4, David Brown wrote:
> It can be difficult for non-Americans to appreciate the importance of
> this sort of thing. I am only a couple of years younger than you (still
> over 40), but from when I was growing up there was nothing unusual about
> black (or any other colour) people on TV or sports. It would never have
> occurred to me that there could be something unusual about a Star Trek
> officer happening to be black.

When I grew up it was the same, because I came after it, after the change
had been made. However, my mother and father were born in the early 40s,
and to them it was shocking. I can remember my mother specifically talking
about "a black com officer, a Russian navigator, an Asian helmsman, an
alien science officer, and several female officers walking in and out of
various scenes almost as background personnel ... Rick, it was amazing.

I recently read a review about the latest Star Trek Continues episode,
called "The White Iris," and the reviewer prefixed his review by explaining
that he, being about 70 yrs old, had gone through those same things my
mother went through. He commented about how revolutionary it was to see
those things at that time, and how much it has changed society. And then
he went on to say that STC E04: The White Iris was fantastic. I agree.
It deals with the loneliness of command. And whereas I am "in command"
of my little software projects, and nothing involving people in general,
I still also feel that loneliness.

> There are still some aspects of British society in which non-whites are
> heavily under-represented, but I think that is more from social and
> economic class than race (i.e., some jobs and positions in society are
> dominated by the traditional upper class, or by "old money" - these are
> out of reach to most people).

It seems to be the mainstream media which is propagating the race issue
in America today. I know of very few people who still hold such views.
And a recent video from Answers in Genesis has really shed light on the
whole idea for me, "One Blood, One Race":

https://www.youtube.com/watch?v=_OfcbXkOtX0

> If these discussions have woken an interest in Douglas Adams, then I
> strongly recommend you read his books.

I have read them years ago. Brilliant humor. "The ships hung in the
sky in much the same way bricks don't."

I've never seen any of the TV shows, and likely won't. In my mind are
how the characters look. And that's good enough for me. :-)

Ben Bacarisse

unread,
Jun 17, 2015, 12:58:31 PM6/17/15
to
Eh? In what way is return(42); like weather? Saying there is no
ambiguity does not mean there is none, barring asteroids, it means none.
The analogy does not help me one bit -- i still have no idea what you
meant to say.

If all that was to illustrate the difference between the first answer,
"none", and what you meant "none above threshold" then it was not
needed. I get the difference -- I just don't know what the threshold is
(but I also don't care so there's no need to explain it).

>> What is the
>> ambiguity you spoke of that is removed by adding the parentheses?
>
> It just conveys completely that the value 42 is being input into the
> return, whereas "return 42;" probably conveys that meaning, and it
> would be natural to conclude it does, but there's no way to be 100%
> sure. It could be something like RET 42 in x86 assembly, which returns
> and pops 42 bytes off the stack in the process (though I suppose one
> could argue that return(42); could do the same thing).

Sorry, but that's a nonsense justification. Someone might see the
return(42); form as pushing an argument ans executing a call
instruction. As you suggest, I can make up as many just-so stories as
you can.

>> I get
>> that you might simply have misspoken and meant to say "I like them" or
>> something like that, but you spoke of and ambiguity being removed, and I
>> can't see one, even if it is "below" some threshold -- I can't see it at
>> all -- nada.
>
> That's okay. Chocolate. Vanilla. They both exist for a reason.

As I said, if you meant it's just a personal preference I'm OK with
that, but instead I wasted time trying to find out what ambiguity the
()s remove (despite the clue that you said there was none on one
occasion). This last remark suggest is is simply a personal choice, but
above you try to offer a justification for it.

<snip>
> On the whole, I use parentheses far more places than they're needed
> by syntax,

Fine, but you might want to reconsider this remark:

"I use return(x); everywhere in source code."

<snip>
--
Ben.

David Kleinecke

unread,
Jun 17, 2015, 1:07:43 PM6/17/15
to
On Tuesday, June 16, 2015 at 11:05:49 AM UTC-7, Keith Thompson wrote:
> David Kleinecke <dklei...@gmail.com> writes:
> [...]
> > One way to think of it is that "sizeof (int)" is the sizeof operator
> > acting on a type cast and "sizeof x" is the operator acting on a
> > variable (like "& x") - and to forget that "sizeof (x)" is possible.
>
> That is, in my humble opinion, a misleading way to think about it.
>
> A cast operator and the sizeof operator applied to a type name
> both happen to use a similar syntax, a type name in parentheses,
> but in very different contexts. (Compound literals also use a
> type name in parentheses, but it's neither preceded by a `sizeof`
> operator nor followed by an expression.)
>
> In `sizeof (int)`, the `(int)` is not a cast operator, any more than
> the comma in `func(x, y)` is a comma operator or the `*` in `*ptr`
> is a multiplication operator. C re-uses punctuation characters in
> diferent contexts, and their meaning is highly context-specific.
>
> As for `sizeof x`, that's a `sizeof` operator applied to an
> *expression* (specifically, the grammar requires a *unary-expression*
> in that context). In this case, the expression happens to be the
> name of an object, but for example `sizeof 42` is equally valid.
> A parenthesized expression is a unary-expression, so `sizeof (x)`
> is also valid, but personally I prefer to add parentheses only
> when they're necessary for grouping or when they improve clarity.
> I probably wouldn't write `sizeof x ++`, but if I felt the need to
> do so I might write it as `sizeof (x++)` just to make it obvious
> what the `sizeof` applies to.

Come on - I didn't say sizeof(int) involved a cast. I said think of
it as a cast - a gimmick to help one remember the syntax.

And it is useful, if I am writing a compliler, to think of the comma
in f(a,b) as the comma operator and give the comma operator different
semantics in free-standing expressions versus function arguments. That
the standard chose not to do that is irrelevant.

There are numerous places in C where details can be handled in the
syntax or the semantics and which way one goes is more a matter of
taste than anything else.

Rick C. Hodgin

unread,
Jun 17, 2015, 1:07:59 PM6/17/15
to
Check.

> then it was not
> needed. I get the difference -- I just don't know what the threshold
> is (but I also don't care so there's no need to explain it).

Check.

> >> What is the
> >> ambiguity you spoke of that is removed by adding the parentheses?
> >
> > It just conveys completely that the value 42 is being input into the
> > return, whereas "return 42;" probably conveys that meaning, and it
> > would be natural to conclude it does, but there's no way to be 100%
> > sure. It could be something like RET 42 in x86 assembly, which returns
> > and pops 42 bytes off the stack in the process (though I suppose one
> > could argue that return(42); could do the same thing).
>
> Sorry, but that's a nonsense justification. Someone might see the
> return(42); form as pushing an argument ans executing a call
> instruction. As you suggest, I can make up as many just-so stories
> as you can.

Check.

> >> I get
> >> that you might simply have misspoken and meant to say "I like them" or
> >> something like that, but you spoke of and ambiguity being removed, and I
> >> can't see one, even if it is "below" some threshold -- I can't see it at
> >> all -- nada.
> >
> > That's okay. Chocolate. Vanilla. They both exist for a reason.
>
> As I said, if you meant it's just a personal preference I'm OK with
> that, but instead I wasted time trying to find out what ambiguity the
> ()s remove (despite the clue that you said there was none on one
> occasion). This last remark suggest is is simply a personal choice, but
> above you try to offer a justification for it.

It doesn't make "return(42);" less ambiguous, but it does make something
like "return(lnBase + lnAdds - lnSubtracts);" less ambiguous than the
equivalent "return lnBase + lnAdds - lnSubtracts;"

I use that type of code in places where I return some calculation rather
than assigning it first to a variable. Not always, but if it's an obvious
thing I do.

> <snip>
> > On the whole, I use parentheses far more places than they're needed
> > by syntax,
>
> Fine, but you might want to reconsider this remark:
>
> "I use return(x); everywhere in source code."

If there is some place I haven't or don't, then it's an oversight on
my behalf, or it's code I've missed from a contributor, or brought
in either "as is" or "relatively as is" from another project.

Rick C. Hodgin

unread,
Jun 17, 2015, 1:10:07 PM6/17/15
to
It could also be old code before I settled on this standard. :-)

David Kleinecke

unread,
Jun 17, 2015, 1:35:18 PM6/17/15
to
Part of the appeal of the BBC TV series is how amateurish (by
Hollywood standards) it is.

David Kleinecke

unread,
Jun 17, 2015, 1:46:20 PM6/17/15
to
I have tried but I can't agree even agree that
return(x)
is a "function". To me that means "return" the expression "(x)".

But then I remember how Pascal did "returns". At the end of function
"foo" it returned value "x" by
foo = x
C could have done this but chose not to.


Keith Thompson

unread,
Jun 17, 2015, 1:53:15 PM6/17/15
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:
> On Wednesday, June 17, 2015 at 10:46:44 AM UTC-4, Ben Bacarisse wrote:
[...]
>> What is the
>> ambiguity you spoke of that is removed by adding the parentheses?
>
> It just conveys completely that the value 42 is being input into the
> return, whereas "return 42;" probably conveys that meaning, and it
> would be natural to conclude it does, but there's no way to be 100%
> sure. It could be something like RET 42 in x86 assembly, which returns
> and pops 42 bytes off the stack in the process (though I suppose one
> could argue that return(42); could do the same thing).

There is no ambiguity. None. Zero. `return 42;` and `return(42);`
mean exactly the same thing in C.

If I see a return statement with parentheses in C code written in the
last 30 years, my first assumption will be that the author doesn't know
the language very well. That can be useful if it's true; it means I'll
be on the lookout for other problems. If the author has communicated
that he or she *does* know the language and simply prefers the
parentheses, that's a different matter.

I don't object to your using unnecessary parentheses in your code. I'm
responding only because your claimed reasons for doing so are not valid.
You don't *need* to have a reason, or to tell us what it is. My only
concern here is with accuracy. (I personally find code that doesn't use
parentheses on return statements cleaner and easier to read, and as
you've seen I'm glad to expound on that point, but that imposes no
obligation on anyone else.)

[...]

> I did not know that. Interesting. I know that many C compilers today
> allow for the trailing , in a list because it's easier for generated
> code to not remove that trailing comma and just leave it there.

That's not just a matter of "many C compilers". It's specified by the
language grammar. Trailing commas are permitted in some contexts
(particularly enumeration lists and initializers), but not in others
(argument lists, for example). This was a grammar change in C99, so
pre-C99 compilers might not permit trailing commas even in those
contexts.

> I
> disagree with that as well because someone following along after in
> that code for maintenance would wonder "Did the original developer
> leave off some more data?"

Any such doubt is easily cured by understanding that it's a language
feature.

> The same with not using the keyword "void"
> in something like "int f()" instead of "int f(void)" because it's
> much more difficult to accidentally type void than it is to
> accidentally leave it blank. And seeing it blank also begs the
> question, "Was the developer finished here? Did they mean to leave
> it blank, or is this placeholder code not yet developed?"

`int f()` and `int f(void)` have different meanings. You can often get
away with using `int f()`, but it's poor style and can lead to
undiagnosed errors.

[...]

Keith Thompson

unread,
Jun 17, 2015, 2:13:10 PM6/17/15
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:
[...]
> > It doesn't make "return(42);" less ambiguous, but it does make something
> like "return(lnBase + lnAdds - lnSubtracts);" less ambiguous than the
> equivalent "return lnBase + lnAdds - lnSubtracts;"

No, it doesn't.

The syntax of a return statement is

return expression[opt] ;

There is no operator precedence outside the (optional) expression.
There is no way that

return x + y - z;

could be treated as

(return x) + y - z;

or could be interpreted that way by anyone who knows the C language.
Someone ignorant of C *might* make that mistake, but there's no way you
can make your C code explicit enough to avoid any such
misunderstandings.

If you want to use extra parentheses, go ahead. If you continue to post
invalid justifications for doing so, we will continue to refute them.

Keith Thompson

unread,
Jun 17, 2015, 2:16:51 PM6/17/15
to
I didn't say you said it was a cast. I said that thinking of it as a
cast is misleading.

> And it is useful, if I am writing a compliler, to think of the comma
> in f(a,b) as the comma operator and give the comma operator different
> semantics in free-standing expressions versus function arguments. That
> the standard chose not to do that is irrelevant.

Really? I don't see how that would be useful. Most compilers use some
explicit representation of the C grammar. The use of the comma as an
operator and as a separator between function arguments are in different
clauses of that grammar. Or they use recursive descent, in which case
the handling of the different uses of the comma will be handled in
different parts of the parser. How could it be useful to conflate them?

> There are numerous places in C where details can be handled in the
> syntax or the semantics and which way one goes is more a matter of
> taste than anything else.

Rick C. Hodgin

unread,
Jun 17, 2015, 2:17:47 PM6/17/15
to
On Wednesday, June 17, 2015 at 1:53:15 PM UTC-4, Keith Thompson wrote:
> There is no ambiguity. None. Zero. `return 42;` and `return(42);`
> mean exactly the same thing in C.

Okay. Sorry.

Rick C. Hodgin

unread,
Jun 17, 2015, 4:59:28 PM6/17/15
to
On Wednesday, June 17, 2015 at 1:53:15 PM UTC-4, Keith Thompson wrote:
> There is no ambiguity. None. Zero. `return 42;` and `return(42);`
> mean exactly the same thing in C.

Something occurred to me here in re-reading your reply. I wasn't
speaking specifically about C, or C's syntax, but rather about general
code readability.

Using the parentheses makes it less ambiguous for the human mind and
eye in my opinion. A person without special training would recognize
the abc(xyz) format sooner than they would recognize abc xyz format
in my opinion. At the very least they might think (42) was a footnote
number, but they would definitely know it was something associated
with the "return".

This is just my opinion, and it is a general observation, not one
specific to C, but one that I do see in several places in C. It would
be interested to conduct a poll of 50 random people at a university.

Ian Collins

unread,
Jun 17, 2015, 9:41:55 PM6/17/15
to
Rick C. Hodgin wrote:
> On Wednesday, June 17, 2015 at 1:53:15 PM UTC-4, Keith Thompson wrote:
>> There is no ambiguity. None. Zero. `return 42;` and `return(42);`
>> mean exactly the same thing in C.
>
> Something occurred to me here in re-reading your reply. I wasn't
> speaking specifically about C, or C's syntax, but rather about general
> code readability.
>
> Using the parentheses makes it less ambiguous for the human mind and
> eye in my opinion. A person without special training would recognize
> the abc(xyz) format sooner than they would recognize abc xyz format
> in my opinion. At the very least they might think (42) was a footnote
> number, but they would definitely know it was something associated
> with the "return".

I'm sure I'm not alone in thinking the parentheses makes it more
ambiguous - it makes a return look like another function call...

--
Ian Collins

Nathan Wagner

unread,
Jun 18, 2015, 3:15:24 AM6/18/15
to
On 2015-06-17, Keith Thompson <ks...@mib.org> wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> [...]
>> > It doesn't make "return(42);" less ambiguous, but it does make something
>> like "return(lnBase + lnAdds - lnSubtracts);" less ambiguous than the
>> equivalent "return lnBase + lnAdds - lnSubtracts;"
>
> No, it doesn't.

One wonders if Mr Hodgin thinks that "(a * b) + c" is less ambiguous
than "a * b + c".

AFAIK the C specification is not ambiguous in itself, so the only thing
left is how easy it is for a human to understand by looking at it.
Parentheses on a return statement always make me do a double take and
instead of just noting that a value is being returned and moving on, I
now have to look at the code to make sure nothing else goofy is
happening. Furthermore, if the ( is right next to the return, I can't
use my whitespace pattern recognition apparatus to quickly find the
return statement(s) in a function.

--
nw

David Brown

unread,
Jun 18, 2015, 3:54:08 AM6/18/15
to
On 18/06/15 09:14, Nathan Wagner wrote:
> On 2015-06-17, Keith Thompson <ks...@mib.org> wrote:
>> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
>> [...]
>>>> It doesn't make "return(42);" less ambiguous, but it does make something
>>> like "return(lnBase + lnAdds - lnSubtracts);" less ambiguous than the
>>> equivalent "return lnBase + lnAdds - lnSubtracts;"
>>
>> No, it doesn't.
>
> One wonders if Mr Hodgin thinks that "(a * b) + c" is less ambiguous
> than "a * b + c".
>
> AFAIK the C specification is not ambiguous in itself, so the only thing
> left is how easy it is for a human to understand by looking at it.

To me, it sounds like Rick is using a poor choice of words with
"ambiguous" - his posts would make more sense if it were replaced with
"clearer".

"return lnBase + lnAdds - lnSubtracts;" is not in any way ambiguous -
there is only one possible interpretation of it in C.

However, it is fair to argue that "return (lnBase + lnAdds -
lnSubtracts);" is /clearer/ to a human reader, or faster for a human to
parse - it is immediately obvious that the expression in brackets should
be calculated, and the result returned.

Obviously it is a matter of personal opinion whether the brackets
improve readability here, but it would not be an unreasonable opinion.


David Brown

unread,
Jun 18, 2015, 4:04:52 AM6/18/15
to
On 17/06/15 19:53, Keith Thompson wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
<snip>
>
>> I did not know that. Interesting. I know that many C compilers today
>> allow for the trailing , in a list because it's easier for generated
>> code to not remove that trailing comma and just leave it there.
>
> That's not just a matter of "many C compilers". It's specified by the
> language grammar. Trailing commas are permitted in some contexts
> (particularly enumeration lists and initializers), but not in others
> (argument lists, for example). This was a grammar change in C99, so
> pre-C99 compilers might not permit trailing commas even in those
> contexts.

I find the trailing comma useful in some types of code:

typedef void (*FVoid)(void);

static const FVoid thingsToDo[] = {
doThis, // An important task
doThat, // Another task
doSomething, // Less important
doAnotherThing, // Critical task
};

The trailing comma makes the entries more consistent, easier to
re-arrange, and easier to extend. It's a small thing, but nice -
especially when you want to compare two versions of the code and see
what has /really/ changed.

(It is a nice enough feature that C++11 adopted it too.)


>
>> I
>> disagree with that as well because someone following along after in
>> that code for maintenance would wonder "Did the original developer
>> leave off some more data?"
>
> Any such doubt is easily cured by understanding that it's a language
> feature.
>
>> The same with not using the keyword "void"
>> in something like "int f()" instead of "int f(void)" because it's
>> much more difficult to accidentally type void than it is to
>> accidentally leave it blank. And seeing it blank also begs the
>> question, "Was the developer finished here? Did they mean to leave
>> it blank, or is this placeholder code not yet developed?"
>
> `int f()` and `int f(void)` have different meanings. You can often get
> away with using `int f()`, but it's poor style and can lead to
> undiagnosed errors.
>

The confusion here is sometimes caused by f() and f(void) being the same
thing in C++, unlike in C.


David Brown

unread,
Jun 18, 2015, 4:18:12 AM6/18/15
to
It is much more akin to a theatre play. It was low budget, and made
long before computer graphics and modern special effects were available.
But it was /intentionally/ made with "amateur" effects - the point was
to emphasis the humour and the characters, not to try and make a flashy
science fiction series. (For comparison, see something like Blake's 7
which was a contemporary science fiction series from the BBC, with much
more emphasis on the effects.)

The BBC at that time excelled at making programs where viewers'
imaginations filled out the scene, rather than spoon-feeding Hollywood
graphics.

David Brown

unread,
Jun 18, 2015, 4:21:46 AM6/18/15
to
On 17/06/15 17:23, Rick C. Hodgin wrote:

>> If these discussions have woken an interest in Douglas Adams, then I
>> strongly recommend you read his books.
>
> I have read them years ago. Brilliant humor. "The ships hung in the
> sky in much the same way bricks don't."
>
> I've never seen any of the TV shows, and likely won't. In my mind are
> how the characters look. And that's good enough for me. :-)
>

DNA was behind the TV series too - he always felt that the story could
and should be viewed in different media, because they allowed him to say
different things in different ways. The radio series was different from
the books, and the TV series was different again. (He wanted to make a
film version too, which would be different too - but not like the one
that was eventually produced.)


Richard Heathfield

unread,
Jun 18, 2015, 5:09:05 AM6/18/15
to
On 18/06/15 09:18, David Brown wrote:

> [The TV adaptation of Hitchhiker] is much more akin to a theatre
> play. It was low budget, and made long before computer graphics
> and modern special effects were available.

The radio series had much better pictures, with one curious exception -
the very computer graphics that you said weren't available, which were,
quite frankly, the stars of the TV show. Nevertheless, as you rightly
say, they weren't available - not as computer graphics, anyway, or at
least not within budget. And so, instead, *every frame was hand-drawn* -
you know, acetates, crayons, stuff like that (says Joe Artist). One
reporter from a computer magazine was so impressed by the graphics that
he phoned up the company that had drawn the cartoons and asked them
which computer they'd used. The answer was, apparently, unprintable.

Rick C. Hodgin

unread,
Jun 18, 2015, 8:19:44 AM6/18/15
to
On Thursday, June 18, 2015 at 3:15:24 AM UTC-4, Nathan Wagner wrote:
> On 2015-06-17, Keith Thompson <ks...@mib.org> wrote:
> > "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> > [...]
> >> > It doesn't make "return(42);" less ambiguous, but it does make something
> >> like "return(lnBase + lnAdds - lnSubtracts);" less ambiguous than the
> >> equivalent "return lnBase + lnAdds - lnSubtracts;"
> >
> > No, it doesn't.
>
> One wonders if Mr Hodgin thinks that "(a * b) + c" is less ambiguous
> than "a * b + c".

Yes I do. :-)

But, perhaps the word I should've been using, as David Brown points
out, is "clearer" rather than "less ambiguous."

Ambiguous, adj

1. open to or having several possible meanings or interpretations;
equivocal: an ambiguous answer.

2. Linguistics. (of an expression) exhibiting constructional
homonymity; having two or more structural descriptions, as
the sequence Flying planes can be dangerous.

3. of doubtful or uncertain nature; difficult to comprehend,
distinguish, or classify:
a rock of ambiguous character.

4. lacking clearness or definiteness; obscure; indistinct:
an ambiguous shape; an ambiguous future.

I would have been using the #3 definition there, specifically the
"difficult to comprehend, DISTINGUISH, or classify," reference.

Use of "clearer" probably does make my meaning clearer, and therefore
also less ambiguous in certain circles. :-)

[Thank you, David.]

David Kleinecke

unread,
Jun 18, 2015, 1:22:18 PM6/18/15
to
In the C compilers I have written expressions are handled in a separate
block (think sub-routine - but not really a subroutine) and a function
call is essentially
function-name OPEN (expression) CLOSE
The semantics of COMMA change during this instance of expression from
the default semantics in
variable EQUAL expression
and all the other places exprssions are used.

To not flip the semantics would be silly. Any other approach is
perverse.

Keith Thompson

unread,
Jun 18, 2015, 1:42:42 PM6/18/15
to
David Kleinecke <dklei...@gmail.com> writes:
> On Wednesday, June 17, 2015 at 11:16:51 AM UTC-7, Keith Thompson wrote:
>> David Kleinecke <dklei...@gmail.com> writes:
[...]
>> > And it is useful, if I am writing a compliler, to think of the comma
>> > in f(a,b) as the comma operator and give the comma operator different
>> > semantics in free-standing expressions versus function arguments. That
>> > the standard chose not to do that is irrelevant.
>>
>> Really? I don't see how that would be useful. Most compilers use some
>> explicit representation of the C grammar. The use of the comma as an
>> operator and as a separator between function arguments are in different
>> clauses of that grammar. Or they use recursive descent, in which case
>> the handling of the different uses of the comma will be handled in
>> different parts of the parser. How could it be useful to conflate them?
>>
>> > There are numerous places in C where details can be handled in the
>> > syntax or the semantics and which way one goes is more a matter of
>> > taste than anything else.
>
> In the C compilers I have written expressions are handled in a separate
> block (think sub-routine - but not really a subroutine) and a function
> call is essentially
> function-name OPEN (expression) CLOSE
> The semantics of COMMA change during this instance of expression from
> the default semantics in
> variable EQUAL expression
> and all the other places exprssions are used.
>
> To not flip the semantics would be silly. Any other approach is
> perverse.

That seems like an odd way to go about it. Does it handle comma
operators within arguments correctly, like func((x, y))?

Normally the parser analyzes the program structure, driven by the
language grammar. The portion of the compiler that generates code
for a function call would see a sequence of argument expressions;
it wouldn't even be aware that they were separated in the source
code by a token that happens to look exactly like a comma operator.

If, hypothetically, you wanted to compile a language that's just like
C except that function arguments are separated by semicolons rather
than commas, you'd just have to change the grammar specification,
and everything else would just work. It would probably be a one-line
change. I don't suggest that that particular flexibility is a real
advantage; it's merely a consequence of the way most parsers happen
to work.

David Kleinecke

unread,
Jun 18, 2015, 2:41:15 PM6/18/15
to
Sure. The second ( flips the semantics back again to normal. The
( stack (in my recent stuff - recursion actually handles the flip
automatically) remembers which semantics.

> Normally the parser analyzes the program structure, driven by the
> language grammar. The portion of the compiler that generates code
> for a function call would see a sequence of argument expressions;
> it wouldn't even be aware that they were separated in the source
> code by a token that happens to look exactly like a comma operator.

> If, hypothetically, you wanted to compile a language that's just like
> C except that function arguments are separated by semicolons rather
> than commas, you'd just have to change the grammar specification,
> and everything else would just work. It would probably be a one-line
> change. I don't suggest that that particular flexibility is a real
> advantage; it's merely a consequence of the way most parsers happen
> to work.

But not my parsers. I'll explain how I parse if you want to know.

Richard Bos

unread,
Jun 18, 2015, 4:38:51 PM6/18/15
to
Richard Heathfield <r...@cpax.org.uk> wrote:

> Is this tongue-in-cheek? (Apologies if it isn't.) You make too much of a
> trifle.

Oh no, sir, you can _never_ make too much of a trifle. Even the
acknowledged masters of cookery in Europe, the Italians, recognised the
value of a trifle, that one, lone worthwhile contribution of the
English, when they adopted it as the Zuppa Inglese.

Richard
0 new messages