A couple of things from H&S

F

Frank

This reading is starting to get really interesting. I'm so glad I
bought a currently-valid reference.

A lot of little things pop up. On p. 222 is the following snippet:
size_t z = sizeof(j++);
size_t x = sizeof(int [n++]);

The authors claim that the former statement does not increment j,
while the latter does increment n. Why?

The other one I can't find, so I'll try to produce it faithfully.
They claim that

char c;
while ((c = getchar()) != EOF)
....

is not the right way to do it. Instead they say to use
int c;
....

Supposedly, on most machines, the test condition would become 255 ==
-1. I've written a boatload of programs that would never have exited
the while loop. The rationale for this had to do with the signed-ness
of char.

Can someone say a few words about this?
 
P

Peter Nilsson

...
size_t z = sizeof(j++);
size_t x = sizeof(int [n++]);

The authors claim that the former statement does not
increment j, while the latter does increment n.  Why?

Because the latter operand to sizeof is a variable length
array and the expression needs to be evaluated in order to
determine the size of that array, whether it exists or not.
...
char c;
while ((c = getchar()) != EOF)
Can someone say a few words about this?

<http://c-faq.com/stdio/getcharc.html>
 
B

Ben Bacarisse

Frank said:
This reading is starting to get really interesting. I'm so glad I
bought a currently-valid reference.

A lot of little things pop up. On p. 222 is the following snippet:
size_t z = sizeof(j++);
size_t x = sizeof(int [n++]);

The authors claim that the former statement does not increment j,
while the latter does increment n. Why?

Do they really not say? The sizeof operator does not evaluate its
argument unless the argument is a VLA type. This is not the wording
from the standard but it is the gist of the matter. The size of a
variable length array type can't be found without evaluating the
expression that gives the length.
The other one I can't find, so I'll try to produce it faithfully.
They claim that

char c;
while ((c = getchar()) != EOF)
...

is not the right way to do it. Instead they say to use
int c;
...

Supposedly, on most machines, the test condition would become 255 ==
-1. I've written a boatload of programs that would never have exited
the while loop. The rationale for this had to do with the signed-ness
of char.

Can someone say a few words about this?

This is a FAQ: http://c-faq.com/stdio/getcharc.html
 
B

Ben Bacarisse

Peter Nilsson said:
...
size_t z = sizeof(j++);
size_t x = sizeof(int [n++]);

The authors claim that the former statement does not
increment j, while the latter does increment n.  Why?

Because the latter operand to sizeof is a variable length
array and the expression needs to be evaluated in order to
determine the size of that array, whether it exists or not.

Nit: the operand is a type not an array.

<snip>
 
K

Keith Thompson

Frank said:
This reading is starting to get really interesting. I'm so glad I
bought a currently-valid reference.

A lot of little things pop up. On p. 222 is the following snippet:
size_t z = sizeof(j++);
size_t x = sizeof(int [n++]);

The authors claim that the former statement does not increment j,
while the latter does increment n. Why?

The authors explain this quite clearly at the bottom of 221.

[snip]
 
A

arnuld

This reading is starting to get really interesting. I'm so glad I
bought a currently-valid reference.

A lot of little things pop up. On p. 222 is the following snippet:
size_t z = sizeof(j++);
size_t x = sizeof(int [n++]);

The authors claim that the former statement does not increment j, while
the latter does increment n. Why?

The authors explain this quite clearly at the bottom of 221.

Well they do:

"If VLA type name appears in a sizeof expression and the value of the
array size affects the value of sizeof expression, then the array size
expression is always fully evaluated, including side-effects. If the
value of array size does not affect the result of sizeof, then it is
undefined whether the size expression is evaluated or not."

Now how come array size is going to affect the result of sizeof ? Will
not this expression /int [N]/ be considered the pointer to an int no
matter whether the N = N, N++ or ++N or N+1 and sizeof will always get a
pointer.

Also, authors say: "When sizeof is applied to an expression, the
expression is analyzed at compile time to determine ts type, but the
expression is not evaluated"

Whats analyze ? I know what is compilation, what is run-time but what
exactly is the meaning of "analyze" here. Perhaps "the expression id
read" is a better term ?
 
F

Frank

This reading is starting to get really interesting.  I'm so glad I
bought a currently-valid reference.
A lot of little things pop up.  On p. 222 is the following snippet:
size_t z = sizeof(j++);
size_t x = sizeof(int [n++]);
The authors claim that the former statement does not increment j, while
the latter does increment n.  Why?
The authors explain this quite clearly at the bottom of 221.

Well they do:

"If VLA type name appears in a sizeof expression and the value of the
array size affects the value of sizeof expression, then the array size
expression is always fully evaluated, including side-effects. If the
value of array size does not affect the result of sizeof, then it is
undefined whether the size expression is evaluated or not."

Now how come array size is going to affect the result of sizeof ? Will
not this expression /int [N]/ be considered the pointer to an int no
matter whether the N = N, N++ or ++N or N+1  and sizeof will always get a
pointer.

Also, authors say: "When sizeof is applied to an expression, the
expression is analyzed at compile time to determine ts type, but the
expression is not evaluated"

Whats analyze ?  I know what is compilation, what is run-time but what
exactly is the meaning of  "analyze" here. Perhaps "the expression id
read" is a better term ?

Thanks for helping me dig that out, arnuld.

I don't know what a VLA is.
 
W

Willem

Frank wrote:
) They claim that
)
) char c;
) while ((c = getchar()) != EOF)
) ...
)
) is not the right way to do it. Instead they say to use
) int c;
) ...
)
) Supposedly, on most machines, the test condition would become 255 ==
) -1. I've written a boatload of programs that would never have exited
) the while loop. The rationale for this had to do with the signed-ness
) of char.

The test condition will only become 255 == -1 if char is unsigned.
On most machines, it's signed, so it would work. Most of the time.
Try reading a file that has a character in it halfway with the value of 255.
Then you'll see why the above loop with char is wrong.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
K

Keith Thompson

arnuld said:
This reading is starting to get really interesting. I'm so glad I
bought a currently-valid reference.

A lot of little things pop up. On p. 222 is the following snippet:
size_t z = sizeof(j++);
size_t x = sizeof(int [n++]);

The authors claim that the former statement does not increment j, while
the latter does increment n. Why?

The authors explain this quite clearly at the bottom of 221.

Well they do:

"If VLA type name appears in a sizeof expression and the value of the
array size affects the value of sizeof expression, then the array size
expression is always fully evaluated, including side-effects. If the
value of array size does not affect the result of sizeof, then it is
undefined whether the size expression is evaluated or not."

Now how come array size is going to affect the result of sizeof ? Will
not this expression /int [N]/ be considered the pointer to an int no
matter whether the N = N, N++ or ++N or N+1 and sizeof will always get a
pointer.

No.

``int [n++]'' is not an expression, it's a type name, specifically an
array type name, more specifically a VLA (variable-length array) type
name. Array type names don't decay the way array expressions do.

And even if you have an expression as the operand of sizeof, an
expression of array type decays to a pointer to the array's first
element *unless* it's in one of three contexts: the operand of sizeof,
the operand of unary "&", or it's a string literal used to initialize
an array.
Also, authors say: "When sizeof is applied to an expression, the
expression is analyzed at compile time to determine ts type, but the
expression is not evaluated"

Whats analyze ? I know what is compilation, what is run-time but what
exactly is the meaning of "analyze" here. Perhaps "the expression id
read" is a better term ?

Analyzing is (part of) what compilers do. It simply means that the
compiler determines the type of the expression. For example, given:
sizeof (2 + 2)
the compiler analyzes the expression (2 + 2) to determine that its
type is int (it doesn't need to know that its value is 4), and causes
the expression to evaluate to the size in bytes of type int (probably
by replacing the whole thing with the equivalent of an integer
constant).
 
M

Morris Keesan

Now how come array size is going to affect the result of sizeof ? Will
not this expression /int [N]/ be considered the pointer to an int no
matter whether the N = N, N++ or ++N or N+1 and sizeof will always get a
pointer.

int [N] is not an expression, it's a type, specifically the type "array of
N ints",
not the type "pointer to int".
 
F

Flash Gordon

Frank said:
Oh, now that I think about it, you didn't.

No. My problem is imagining a syntax where an array is *not* of
variable length.

int arr[5];

More specifically, before C99 the size was required to be an integer
constant expression. It makes it far easier to implement the compiler,
especially where there could be multiple arrays, since the compiler
knows exactly what offsets to use for each array at compile time on a
typical implementation.
 
F

Frank

Oh, now that I think about it, you didn't.
No. My problem is imagining a syntax where an array is *not* of
variable length.

int arr[5];

More specifically, before C99 the size was required to be an integer
constant expression. It makes it far easier to implement the compiler,
especially where there could be multiple arrays, since the compiler
knows exactly what offsets to use for each array at compile time on a
typical implementation.

Yeah. I did more thinking about it and realized that a non-vla array
is precisely what you wrote. I'v simply goten used to getting
whatever length array I need at runtime.
 
A

arnuld

...SNIP....
And even if you have an expression as the operand of sizeof, an
expression of array type decays to a pointer to the array's first
element *unless* it's in one of three contexts: the operand of sizeof,
the operand of unary "&", or it's a string literal used to initialize an
array.

Three contexts, I understand better with examples:

1) sizeof(int arr[N++]);
2) & (int arr[N++]);
3) const char* p = "This is CLC";


(3) is quite obvious, p is the pointer. A string literal is not an array,
so there is no confusion regarding thaat there will be no conversion to
pointer from string literal.

What happens in case (1) and (2) ?


This is from page 222 of H&S 5:

size_t y = sizeof(int (*)[f(n)]);

The function call may or may not be performed. Its seems just like a VLA
where it is undefined if its evaluated or not. If size of VLA affects the
result of sizeof then it will definitely be evaluated.

I never understood how can size of array affect the result of sizeof when
sizeof is only interested in knowing the type, not the number of
elements. How can you explain that ? I think these all will return the
same value:

sizeof( int arr[N++]);
sizeof( int arr[M]);
sizeof( int arr[++Z]);
 
M

Morris Keesan

Three contexts, I understand better with examples:

1) sizeof(int arr[N++]);
2) & (int arr[N++]);
3) const char* p = "This is CLC";


(3) is quite obvious, p is the pointer. A string literal is not an array,
so there is no confusion regarding thaat there will be no conversion to
pointer from string literal.

What happens in case (1) and (2) ?

You get compiler diagnostics, because they're syntax errors. You can't
declare variables in those contexts, and with the symbol "arr" there
they're
not types. Did you mean
1) sizeof(int [N++])
and 2) & (int [N++])
?
Case (1) should evaluate to N * sizeof(int), and increment N.
Case (2) is still an error, because you can't take the address of a type.
This is from page 222 of H&S 5:

size_t y = sizeof(int (*)[f(n)]);

The function call may or may not be performed. Its seems just like a VLA
where it is undefined if its evaluated or not. If size of VLA affects the
result of sizeof then it will definitely be evaluated.

I never understood how can size of array affect the result of sizeof when
sizeof is only interested in knowing the type, not the number of
elements.

The number of elements of an array affects its size, and is part of its
type.
How can you explain that ? I think these all will return the
same value:

sizeof( int arr[N++]);
sizeof( int arr[M]);
sizeof( int arr[++Z]);
As above, these are syntax errors. Without the "arr" in each one,
they have the same values only if N == M and M == Z-1 .

Do you expect that sizeof(int [3]) == sizeof(int [10])?
 
K

Keith Thompson

arnuld said:
SNIP....
And even if you have an expression as the operand of sizeof, an
expression of array type decays to a pointer to the array's first
element *unless* it's in one of three contexts: the operand of sizeof,
the operand of unary "&", or it's a string literal used to initialize an
array.

Three contexts, I understand better with examples:

1) sizeof(int arr[N++]);

``int arr[N++]'' is a declaration of an object named "arr", or it
would be if it had a semicolon and appeared by itself.

I think you mean:

sizeof (arr[N++])

where arr[N++] is an array type (specifically a VLA type). Here N++
is evaluated, with the side effect of modifying N.

Note that the operand of sizeof is a parenthesized type name, not an
expression. The operand of sizeof can be an expression of VLA type:

int n = 42;
int vla[n];
sizeof vla;

but I'm not sure it's possible for such an expression to have side
effects -- meaning it doesn't matter whether it's evaluated or not.
2) & (int arr[N++]);

Unary "&" can apply only to an expression, which must be an lvalue.
Here you're trying to apply it to a declaration. Even if you drop the
"arr", you're still applying it to a type, which is illegal.

Try this:

int arr[N++];
&arr;

N++ is evaluated just once, when the type is created. &arr just gives
you the address of arr, which is of a pointer-to-array type.
3) const char* p = "This is CLC";


(3) is quite obvious, p is the pointer. A string literal is not an array,
so there is no confusion regarding thaat there will be no conversion to
pointer from string literal.

No, a string literal *is* an expression of array type. In the above
declaration, this expression is implicitly converted to char*,
yielding a pointer to the first character of the array object.

Try this:

const char arr[] = "This is CLC";

This is the third case where an array expression isn't converted to a
pointer: when it's used to initialize an array.
What happens in case (1) and (2) ?

Your compiler complains.
This is from page 222 of H&S 5:

size_t y = sizeof(int (*)[f(n)]);

The function call may or may not be performed. Its seems just like a VLA
where it is undefined if its evaluated or not. If size of VLA affects the
result of sizeof then it will definitely be evaluated.

I never understood how can size of array affect the result of sizeof when
sizeof is only interested in knowing the type, not the number of
elements. How can you explain that ?

Because the numer of elements is part of the type.

int[10], int[20], and int[N] are three distinct types.
think these all will return the
same value:

sizeof( int arr[N++]);
sizeof( int arr[M]);
sizeof( int arr[++Z]);

These are all syntax errors, but if you drop the "arr" from each of
them, their values will depend on the values of N, M, and Z.
 
B

Ben Bacarisse

Keith Thompson said:
arnuld said:
SNIP....
And even if you have an expression as the operand of sizeof, an
expression of array type decays to a pointer to the array's first
element *unless* it's in one of three contexts: the operand of sizeof,
the operand of unary "&", or it's a string literal used to initialize an
array.

Three contexts, I understand better with examples:

1) sizeof(int arr[N++]);

``int arr[N++]'' is a declaration of an object named "arr", or it
would be if it had a semicolon and appeared by itself.

I think you mean:

sizeof (arr[N++])

Did you mean sizeof (int [N++])?
where arr[N++] is an array type (specifically a VLA type). Here N++
is evaluated, with the side effect of modifying N.

(The type of the operand you wrote is int so the expression is not
evaluated.)
Note that the operand of sizeof is a parenthesized type name, not an
expression.

This makes it even more obviously a typo despite it appearing twice.

<snip>
 
K

Keith Thompson

Ben Bacarisse said:
Keith Thompson said:
Three contexts, I understand better with examples:

1) sizeof(int arr[N++]);

``int arr[N++]'' is a declaration of an object named "arr", or it
would be if it had a semicolon and appeared by itself.

I think you mean:

sizeof (arr[N++])

Did you mean sizeof (int [N++])?

Whoops, yes, I did.

[...]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,192
Latest member
KalaReid2

Latest Threads

Top