tryick use of sizeof again[Explaination Wanted]

G

goacross

If you're going to post code here, please make sure it's C, not C++.
It's also helpful to post a (small) complete program rather than an
isolated snippet.

'cout', '<<', and 'endl' are specific to C++.

Your underlying question happens, in this particular case, to be
equally valid in both languages, but there are subtle differences
between C and C++ that even the C experts here may not be aware of.

Just this once, I'll show you a C version of your program.

#include <stdio.h>
int main(void)
{
char ch = 'a';
int v = sizeof ++ch;
printf("%c\n", ch);
return 0;

}

Next time, please either post C in the first place, or post to
comp.lang.c++. If you're having trouble knowing the difference, you
need to learn one language or the other (perhaps eventually both).
A newsgroup is not a good place to do that, but
alt.comp.lang.learn.c-c++ might be more appropriate for your purposes
than comp.lang.c.

Several people have already given you the answer to your question --
which is unfortunate, since the question looks very much like
homework. An expression like 'sizeof ++ch' isn't something that you'd
write if your goal is to accomplish something. It was almost
certainly written by someone trying to make a specific point.

If you want us to do your homework for you, please post your
instructor's e-mail address so we can submit our solutions directly.
We're willing to provide hints if you've done some of the work
yourself and you're stuck on something, but we won't (usually) do it
for you.

--
Keith Thompson (The_Other_Keith) (e-mail address removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Thanks for your detailed illustration.

However, unfortunately , this is NOT any homework.
Just some personal interest.

Suggest you be more tolerant to freshmen, even if you're expert. I'm
sorry to say you seemed to like a bear with a sore head from the above
words.

Of course, I'm sorry about the cout issue.
 
M

Martin Wells

Ian:
int main(void) {
const int N = 42;

int data[N];

printf( "%d\n", sizeof data );

}

Gives the same result in C and C++, bit in the former the operand is
evaluated, in the latter it is not.

That's wrong -- the operand is evaluated in *neither* language.

In C++, this will print something like 168 (i.e. sizeof(int) * 42)
because N is a compile-time constant. In C89, the code won't compile.
In C99... well... I can't really say I care.

Martin
 
I

Ian Collins

Martin said:
Ian:
int main(void) {
const int N = 42;

int data[N];

printf( "%d\n", sizeof data );

}

Gives the same result in C and C++, bit in the former the operand is
evaluated, in the latter it is not.

That's wrong -- the operand is evaluated in *neither* language.

In C++, this will print something like 168 (i.e. sizeof(int) * 42)
because N is a compile-time constant. In C89, the code won't compile.
In C99... well... I can't really say I care.
Like it or not, C99 is C.
 
C

Charlie Gordon

Jack Klein said:
Yes it is. Nowhere in the C standard does it define what "sizeof" is,
means, or does in C++. Now it may just happen that C++ defines sizeof
this way, but whether it does or not is 100% completely off-topic
here.


Kindly quote chapter and verse from _any_ version of the C standard
that defines this, or any other behavior, for sizeof in C++.

Well we can't say what it does for C++ from the C standard, big deal!

At least we can explain what it does in C for the two lines

char ch = 'a';
int v = sizeof ++ch;

The expression ++ch is _not_ evaluated, only its type is determined by the
compiler to be char, which by definition has a size of 1. ch is unchanged.

Here are the appropriate quotations for the C language.

6.5.3.4 The sizeof operator

p2 semantics

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

Annex J (informative)

J.1 Unspecified behavior

The following are unspecified:

Whether or not a size expression is evaluated when it is part of the operand
of a
sizeof operator and changing the value of the size expression would not
affect the
result of the operator (6.7.5.2).

For C++, ask the appropriate group, I suspect the interpretation will be the
same, but I am not an expert at C++.
 
C

CBFalconer

Martin said:
Ian:
int main(void) {
const int N = 42;

int data[N];

printf( "%d\n", sizeof data );

}

Gives the same result in C and C++, bit in the former the operand is
evaluated, in the latter it is not.

That's wrong -- the operand is evaluated in *neither* language.

In C++, this will print something like 168 (i.e. sizeof(int) * 42)
because N is a compile-time constant. In C89, the code won't compile.
In C99... well... I can't really say I care.

However the following minor correction functions under C90:

#include <stdio.h>

int main(void) {
# define N 42
int data[N];

printf("%lu\n", (unsigned long)sizeof data);
return 0;
}
 
C

CBFalconer

Charlie said:
.... snip ...

How can you demonstrate the true nature of 'h' without resorting
to the sizeof operator ? The very reason it is an int is quite
obscure, multibyte character constants are not defined in any
standard way, it would be foolish to use them.

What's obscure? chars are represented by an integer value. The
obvious place to hold an integer value is an int, provided it has
the capacity. Any other choice would cause program slowdowns in
one way or another. I never heard of any computer that held things
other than integers, although those integers (or collections of
integers) can be interpreted in various esoteric ways.
 
C

CBFalconer

Chris said:
.... snip ...

Even if the sizeof operator is considered "the same" (e.g., if one
is using C89 or C95), there are still subtle traps:

#include <stdio.h>

struct A { char block[8]; };

int main(void) {
struct B {
struct A {
char block[512];
} a;
};

printf("sizeof(struct A) = %lu\n",
(unsigned long) sizeof(struct A));
return 0;
}

Compile this program with a C compiler and with a C++ compiler,
and run the two executables:

% ln prog.c prog.c++
% cc -o cprog prog.c -O4 -W -Wall -ansi -pedantic
% g++ -o c++prog -O4 prog.c++ -W -Wall
% ./cprog
sizeof(struct A) = 512
% ./c++prog
sizeof(struct A) = 8
%

Exercise: explain the results. :)

Obviously the local scope struct A is in effect for the printf
call, but as far as I am concerned this is wrong. That scope
should only appear when a struct B is open. I.e. the 512 result
should only appear for "sizeof struct B.a". In fact, since there
is no way to create an object of that type, it should not be
'sizable' at all.
 
C

Charlie Gordon

CBFalconer said:
What's obscure? chars are represented by an integer value. The
obvious place to hold an integer value is an int, provided it has
the capacity. Any other choice would cause program slowdowns in
one way or another. I never heard of any computer that held things
other than integers, although those integers (or collections of
integers) can be interpreted in various esoteric ways.

I'm sorry but the very fact 'a' be an int constant literal as opposed to a
char constant literal is counter intuitive to most C programmers and the
reasons for that are indeed obscure. After all, the grammar in C99 6.4.4.4
calls it a character-constant.

C++ chose to change that in order for overloaded functions to be called in a
more understandable way.

Since you are so adamant about everything being held as an integer (which is
only vaguely related to the issue), why is L'a' not an int as well ?

On my system:

sizeof("a"[0]) = 1
sizeof('a') = 4
sizeof(L'a') = 2
sizeof(L"a"[0]) = 2
 
C

Charlie Gordon

CBFalconer said:
What's obscure? chars are represented by an integer value. The
obvious place to hold an integer value is an int, provided it has
the capacity. Any other choice would cause program slowdowns in
one way or another. I never heard of any computer that held things
other than integers, although those integers (or collections of
integers) can be interpreted in various esoteric ways.

I'm sorry but the very fact 'a' be an int constant literal as opposed to a
char constant literal is counter intuitive to most C programmers and the
reasons for that are indeed obscure. After all, the grammar in C99 6.4.4.4
calls it a character-constant.

C++ chose to change that in order for overloaded functions to be called in a
more understandable way.

Since you are so adamant about everything being held as an integer (which is
only vaguely related to the issue), why is L'a' not an int as well ?

On my system:

sizeof("a"[0]) = 1
sizeof('a') = 4
sizeof(L'a') = 2
sizeof(L"a"[0]) = 2
 
K

Keith Thompson

Martin Wells said:
int main(void) {
const int N = 42;

int data[N];

printf( "%d\n", sizeof data );

}

Gives the same result in C and C++, bit in the former the operand is
evaluated, in the latter it is not.

That's wrong -- the operand is evaluated in *neither* language.

In C++, this will print something like 168 (i.e. sizeof(int) * 42)
because N is a compile-time constant. In C89, the code won't compile.
In C99... well... I can't really say I care.

Since I do care ...

In C99, N is not a constant expression (though it's very likely to be
evaluted at compile time anyway), and 'data' is a VLA, therefore the
argument to sizeof *is* evaluated.

But 'data' is just an object, and the result of evaluating it is
discarded, since sizeof still depends only on the type of its
argument. So what difference does it make whether the argument is
evaluated or not?

The only case I can think of is where the VLA is volatile.

Can anyone think of a case where the evaluation of the argument of
sizeof (when it's a VLA) has a visible effect on the behavior of the
program?
 
K

Keith Thompson

Thanks for your detailed illustration.

However, unfortunately , this is NOT any homework.
Just some personal interest.

Ok. But we do get a lot of people posting obvious homework questions
here, showing no sign of any effort to try to do the work themselves.
People even copy-and-paste their actual homework questions, without
indicating that they're homework.

And, as I said, your question *looks like* homework. I'm glad to
learn that it isn't.

Incidentally, when you post a followup, please delete any quoted
material that isn't relevant to your followup, particularly thee
signature (the stuff at the end following the "-- " delimiter).
Thanks.
 
F

Flash Gordon

Keith Thompson wrote, On 15/09/07 20:52:

Can anyone think of a case where the evaluation of the argument of
sizeof (when it's a VLA) has a visible effect on the behavior of the
program?

size_t size=5
int array[++size];
 
I

Ian Collins

CBFalconer said:
Martin said:
Ian:
int main(void) {
const int N = 42;

int data[N];

printf( "%d\n", sizeof data );

}

Gives the same result in C and C++, bit in the former the operand is
evaluated, in the latter it is not.
That's wrong -- the operand is evaluated in *neither* language.

In C++, this will print something like 168 (i.e. sizeof(int) * 42)
because N is a compile-time constant. In C89, the code won't compile.
In C99... well... I can't really say I care.

However the following minor correction functions under C90:
It also defeats the purpose of the example.
#include <stdio.h>

int main(void) {
# define N 42
int data[N];

printf("%lu\n", (unsigned long)sizeof data);
return 0;
}
 
I

Ian Collins

CBFalconer said:
Chris Torek wrote:
.... snip ...
Even if the sizeof operator is considered "the same" (e.g., if one
is using C89 or C95), there are still subtle traps:

#include <stdio.h>

struct A { char block[8]; };

int main(void) {
struct B {
struct A {
char block[512];
} a;
};

printf("sizeof(struct A) = %lu\n",
(unsigned long) sizeof(struct A));
return 0;
}


Exercise: explain the results. :)

Obviously the local scope struct A is in effect for the printf
call, but as far as I am concerned this is wrong. That scope
should only appear when a struct B is open. I.e. the 512 result
should only appear for "sizeof struct B.a". In fact, since there
is no way to create an object of that type, it should not be
'sizable' at all.
I guess the lack of syntax to express the scope is a hole in C. In C++
one would write sizeof(struct B::A), or simply sizeof(B::A).
 
R

rafaelc

sizeof is a handy way of ensuring that an expression is legal without
actually evaluating the expression. For instance, you could have code
something like the following:

typedef ... SomeType;

void Func(SomeType const *p)
{
sizeof (p->val); /* Ensure that SomeType has a member called
val */
}

When would someone want to do something like that? I mean, why wouldn't you know
if SomeType has a val member or not? You can determine it before compilation.
 
?

=?iso-2022-kr?q?Harald_van_D=0E=29=26=0Fk?=

Martin Wells said:
int main(void) {
const int N = 42;

int data[N];

printf( "%d\n", sizeof data );

}

Gives the same result in C and C++, bit in the former the operand is
evaluated, in the latter it is not.

That's wrong -- the operand is evaluated in *neither* language.

In C++, this will print something like 168 (i.e. sizeof(int) * 42)
because N is a compile-time constant. In C89, the code won't compile.
In C99... well... I can't really say I care.

Since I do care ...

In C99, N is not a constant expression (though it's very likely to be
evaluted at compile time anyway), and 'data' is a VLA, therefore the
argument to sizeof *is* evaluated.

But 'data' is just an object, and the result of evaluating it is
discarded, since sizeof still depends only on the type of its argument.
So what difference does it make whether the argument is evaluated or
not?

The only case I can think of is where the VLA is volatile.

Can anyone think of a case where the evaluation of the argument of
sizeof (when it's a VLA) has a visible effect on the behavior of the
program?

#include <stdio.h>
int f(void) {
puts("f is called!");
return 0;
}
int main(void) {
enum { constant_size = 1 };
const int nonconstant_size = 1;

char nonvla[constant_size];
char vla[nonconstant_size];

printf("sizeof (&nonvla)[f()] = %zu\n", sizeof (&nonvla)[f()]);
printf("sizeof (&vla)[f()] = %zu\n", sizeof (&vla)[f()]);

return 0;
}

This should print:

sizeof (&nonvla)[f()] = 1
f is called!
sizeof (&vla)[f()] = 1
 
I

Ian Collins

Harald said:
Can anyone think of a case where the evaluation of the argument of
sizeof (when it's a VLA) has a visible effect on the behavior of the
program?

#include <stdio.h>
int f(void) {
puts("f is called!");
return 0;
}
int main(void) {
enum { constant_size = 1 };
const int nonconstant_size = 1;

char nonvla[constant_size];
char vla[nonconstant_size];

printf("sizeof (&nonvla)[f()] = %zu\n", sizeof (&nonvla)[f()]);
printf("sizeof (&vla)[f()] = %zu\n", sizeof (&vla)[f()]);

return 0;
}

This should print:

sizeof (&nonvla)[f()] = 1
f is called!
sizeof (&vla)[f()] = 1

Should it?
 
?

=?iso-2022-kr?q?Harald_van_D=0E=29=26=0Fk?=

Harald said:
Can anyone think of a case where the evaluation of the argument of
sizeof (when it's a VLA) has a visible effect on the behavior of the
program?

#include <stdio.h>
int f(void) {
puts("f is called!");
return 0;
}
int main(void) {
enum { constant_size = 1 };
const int nonconstant_size = 1;

char nonvla[constant_size];
char vla[nonconstant_size];

printf("sizeof (&nonvla)[f()] = %zu\n", sizeof (&nonvla)[f()]);
printf("sizeof (&vla)[f()] = %zu\n", sizeof (&vla)[f()]);

return 0;
}

This should print:

sizeof (&nonvla)[f()] = 1
f is called!
sizeof (&vla)[f()] = 1

Should it?

This is the behaviour mandated by the standard and implemented by the
compiler I'm using. If you believe the standard would have been better if
sizeof on VLAs were specified differently, then I don't necessarily
disagree, but if you believe the standard requires (or allows) any
different output, then could you please explain why?
 
?

=?iso-2022-kr?q?Harald_van_D=0E=29=26=0Fk?=

Keith Thompson wrote, On 15/09/07 20:52:

Can anyone think of a case where the evaluation of the argument of
sizeof (when it's a VLA) has a visible effect on the behavior of the
program?

size_t size=5
int array[++size];

No, sizeof(array) will always return 6 in this case. The array size is
evaluated when the declaration is reached, but not re-evaluated
afterwards.
 
K

Keith Thompson

Harald van D)&k said:
In C99, N is not a constant expression (though it's very likely to be
evaluted at compile time anyway), and 'data' is a VLA, therefore the
argument to sizeof *is* evaluated.

But 'data' is just an object, and the result of evaluating it is
discarded, since sizeof still depends only on the type of its argument.
So what difference does it make whether the argument is evaluated or
not?

The only case I can think of is where the VLA is volatile.

Can anyone think of a case where the evaluation of the argument of
sizeof (when it's a VLA) has a visible effect on the behavior of the
program?

#include <stdio.h>
int f(void) {
puts("f is called!");
return 0;
}
int main(void) {
enum { constant_size = 1 };
const int nonconstant_size = 1;

char nonvla[constant_size];
char vla[nonconstant_size];

printf("sizeof (&nonvla)[f()] = %zu\n", sizeof (&nonvla)[f()]);
printf("sizeof (&vla)[f()] = %zu\n", sizeof (&vla)[f()]);

return 0;
}

This should print:

sizeof (&nonvla)[f()] = 1
f is called!
sizeof (&vla)[f()] = 1

Nope.

Here's what the standard says (C99 6.5.3.4p2):

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.

The type of the operand in both of your sizeof expressions is char,
not a VLA type. f() is never called. (I tried it, and the behavior
under the implementation I used is consistent with this.)
 

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,774
Messages
2,569,596
Members
45,142
Latest member
arinsharma
Top