By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,852 Members | 2,240 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,852 IT Pros & Developers. It's quick & easy.

Is it ANSI or is it compiler dependent?

P: n/a
#include<iostream>
int main() {
char buff[3];
std::cin.getline(buff,3);
std::cin.getline(buff,3);
std::cout << buff << endl;
}
Run at command prompt and input
1234567
what do you get as output?
Please include your compiler make/version in replies.

The question is: Does ANSI require that ios::failbit to be set after
the first getline() or is it compiler dependent? I expect the output
to be an empty line. I'm particularly interested in complilers that
output '34'.

Thanks in advance
Jul 22 '05 #1
Share this Question
Share on Google+
22 Replies


P: n/a
On 8 May 2004 16:29:08 -0700, ja******@hotmail.com (Canonical Latin) wrote:
#include<iostream>
int main() {
char buff[3];
std::cin.getline(buff,3);
std::cin.getline(buff,3);
std::cout << buff << endl;
std::cout << buff << std::endl;
}
Run at command prompt and input
1234567
what do you get as output?
Please include your compiler make/version in replies.

The question is: Does ANSI require that ios::failbit to be set after
the first getline() or is it compiler dependent? I expect the output
to be an empty line. I'm particularly interested in complilers that
output '34'.

Thanks in advance


Some data points for you:

Comeau/libcomo: 12
Comeau/Dinkumware: (empty line)
MSVC7.1: (empty line)
MSVC6: (empty line)
MSVC6/Dinkumware: (empty line)
CodeWarrior 8: (empty line)
Borland 5.5.1: (empty line)
Borland C++BuilderX: 12
gcc 3.3: (empty line)
Digital Mars: 12
Intel 7/8: (empty line)

I expected "12". Section 27.6.1.3/17 does say that failbit will be set if
the buffer fills up before the trailing delimiter is detected. The output
is consistently 12 if you take away the second getline call, so perhaps
this really boils down to how the different versions of getline behave if
they're called with failbit already set. I suspect they're not obliged to
do any particular thing then, but I haven't located evidence of that in the
Standard yet.
-leor


--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Jul 22 '05 #2

P: n/a

"Leor Zolman" <le**@bdsoft.com> wrote in message
news:ha********************************@4ax.com...
Some data points for you:

Comeau/libcomo: 12
Comeau/Dinkumware: (empty line)
MSVC7.1: (empty line)
MSVC6: (empty line)
MSVC6/Dinkumware: (empty line)
CodeWarrior 8: (empty line)
Borland 5.5.1: (empty line)
Borland C++BuilderX: 12
gcc 3.3: (empty line)
Digital Mars: 12
Intel 7/8: (empty line)

I expected "12". Section 27.6.1.3/17 does say that failbit will be set if
the buffer fills up before the trailing delimiter is detected. The output
is consistently 12 if you take away the second getline call, so perhaps
this really boils down to how the different versions of getline behave if
they're called with failbit already set. I suspect they're not obliged to
do any particular thing then, but I haven't located evidence of that in the Standard yet.
-leor


Thank you. I know this must've come up before, but if you may solve another
mystery for me

#include<iostream>

void fun(int v[2]) {

std::cout << sizeof(v) << endl; // sizeof(int*) = But this v is not a
type!

}

int main() {

int v[3]={};

std::cout << sizeof(v) << '-'; // 3 * sizeof(int) = OK v is a type.

fun(v);

}

under gcc 3.2 on a 32 bit data/memory machine I get: 12-4

Why does this even compile? Does ANSI say that typed array arg's are to be
ignored?
Jul 22 '05 #3

P: n/a

"Canonical Latin" <ja******@hotmail.com> wrote in message
news:7d**************************@posting.google.c om...
#include<iostream>
int main() {
char buff[3];
std::cin.getline(buff,3);
std::cin.getline(buff,3);
std::cout << buff << endl;
}
Run at command prompt and input
1234567
what do you get as output?
Please include your compiler make/version in replies.

I expect the output to be an empty line.


The reason I think it is reasonable for buff[0]='\0' after the second
getline() is that then the character count is zero indicating that nothing
was read. This behavior is backward compatible with C getlen().
Jul 22 '05 #4

P: n/a
On Sun, 09 May 2004 15:04:59 GMT, "Canonical Latin" <ja******@hotmail.com>
wrote:

"Leor Zolman" <le**@bdsoft.com> wrote in message
news:ha********************************@4ax.com.. .
Some data points for you:

Comeau/libcomo: 12
Comeau/Dinkumware: (empty line)
MSVC7.1: (empty line)
MSVC6: (empty line)
MSVC6/Dinkumware: (empty line)
CodeWarrior 8: (empty line)
Borland 5.5.1: (empty line)
Borland C++BuilderX: 12
gcc 3.3: (empty line)
Digital Mars: 12
Intel 7/8: (empty line)

I expected "12". Section 27.6.1.3/17 does say that failbit will be set if
the buffer fills up before the trailing delimiter is detected. The output
is consistently 12 if you take away the second getline call, so perhaps
this really boils down to how the different versions of getline behave if
they're called with failbit already set. I suspect they're not obliged to
do any particular thing then, but I haven't located evidence of that inthe
Standard yet.
-leor


Thank you. I know this must've come up before, but if you may solve another
mystery for me

#include<iostream>

void fun(int v[2]) {

std::cout << sizeof(v) << endl; // sizeof(int*) = But this v is not a
type!


First of all, it didn't compile, because again you neglected to put std::
in front of endl.

Once that's fixed...what do you mean when you say "v is not a type"? Of
course it isn't, it is the name of some data. Just as it is below in
main(). In both cases you're asking what the storage is of the object
referred to by the name "v". Above it is a pointer to int, as you've
indicated, and below it is an array of 3 ints. Recall there are two forms
of sizeof:
sizeof expression
sizeof (type)
(And it is OK to put the expression in parens, if you prefer, but it is not
OK to leave out the parens in the 2nd case). You've used the first form in
both cases.

If you still have a question, let us know...
-leor

}

int main() {

int v[3]={};

std::cout << sizeof(v) << '-'; // 3 * sizeof(int) = OK v is a type.

fun(v);

}

under gcc 3.2 on a 32 bit data/memory machine I get: 12-4

Why does this even compile? Does ANSI say that typed array arg's are to be
ignored?


--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Jul 22 '05 #5

P: n/a
On Sun, 09 May 2004 16:22:00 GMT, "Canonical Latin" <ja******@hotmail.com>
wrote:

"Canonical Latin" <ja******@hotmail.com> wrote in message
news:7d**************************@posting.google. com...
#include<iostream>
int main() {
char buff[3];
std::cin.getline(buff,3);
std::cin.getline(buff,3);
std::cout << buff << endl;
}
Run at command prompt and input
1234567
what do you get as output?
Please include your compiler make/version in replies.

I expect the output to be an empty line.
The reason I think it is reasonable for buff[0]='\0' after the second
getline() is that then the character count is zero indicating that nothing
was read. This behavior is backward compatible with C getlen().


Unfortunately (or fortunately, depending upon your point of view),
reasonability doesn't necessarily count for much. It seems just as
"reasonable" to me for getline to do absolutely nothing if failbit is
already set as it is for it to put a NUL into the first position of the
buffer. Well, in fact it actually seems a bit /more/ reasonable for it to
do nothing, for consistency with the way extractors don't alter their
operand if the stream is broken;
cin >> i; // doesn't alter i if it can't extract

BTW, what the heck is "C getlen()" ?
-leor


--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Jul 22 '05 #6

P: n/a

"Leor Zolman" <le**@bdsoft.com> wrote in message
news:94********************************@4ax.com...
If you still have a question, let us know...
-leor


LOL. A simple "I don't know" would have been shorter
Jul 22 '05 #7

P: n/a
Canonical Latin wrote:> ...
#include<iostream>

void fun(int v[2]) {

std::cout << sizeof(v) << endl; // sizeof(int*)
Yes, it shall output size of 'int*', since declaration 'int v[2]' is
equivalent to 'int* v' in this context. But this v is not a type!
Huh? So what? 'sizeof' works with expressions just like it works with types. int main() {

int v[3]={};

std::cout << sizeof(v) << '-'; // 3 * sizeof(int)
As expected. OK v is a type.
No, 'v' is a name of an object of array type. fun(v);

}

under gcc 3.2 on a 32 bit data/memory machine I get: 12-4

Why does this even compile?
Why shouldn't it compile? Does ANSI say that typed array arg's are to be
ignored?


ANSI says that function parameters of array type are automatically
replaced with parameters of pointer type.
--
Best regards,
Andrey Tarasevich
Jul 22 '05 #8

P: n/a
On Sun, 09 May 2004 21:21:58 GMT, "Canonical Latin" <ja******@hotmail.com>
wrote:

"Leor Zolman" <le**@bdsoft.com> wrote in message
news:94********************************@4ax.com.. .
If you still have a question, let us know...
-leor


LOL. A simple "I don't know" would have been shorter


I was in fact trying to answer the question. The way you used the word
"type", however, led me to believe I needed to clarify the distinction
between type and object in the context of using the sizeof operator. If
that in itself didn't answer your question, I was inviting you to rephrase
it so I could understand what you meant. In what way would "I don't know"
have been a better answer?
-leor
--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Jul 22 '05 #9

P: n/a

"Leor Zolman" <le**@bdsoft.com> wrote in message
news:6d********************************@4ax.com...

I was in fact trying to answer the question. The way you used the word
"type", however, led me to believe I needed to clarify the distinction
between type and object in the context of using the sizeof operator. If
that in itself didn't answer your question, I was inviting you to rephrase
it so I could understand what you meant.


Sorry. I had assumed the use of word 'type' was clear in the context of my
question. But here is a more carefully 'worded' version.

int v[3];
int w[3][3];

Granted that v is a variable with certain storage type. But v is also a
variable of type int[3] and w is a of type int[3][3].

void fun1(int v[2]) {}
void fun2(int v[2][3]) {}
void fun3(int v[2][2]) {}
int main() {
int v[3]={};
int w[3][3]={};
fun1(v);
fun2(w);
fun3(w);
}

It is a mystery to me why fun3(w) produces a compile error while the others
don't. For some reason the first dimension of an array is ignored when doing
type checking--as if v had the type int[] and w the type int[][3]. I used
sizeof operator to note that indeed v has the same storage requirement as
type int[2] in the main() which implies that at least here the compiler
acknowledges that v is indeed of type int[2] and not of type int[]. But then
later it treats it as int[] despite the specified type.

You can also check this by noting that fun(int v[3]) and fun(int v[4])
cannot be overloaded (since the compiler sees them as type int[]) but the
fun(int v[3][3]) and fun(int v[4][4]) can be overloaded.

I realize that you don't need the size of the first dimension of an array
for index computation while you need the rest. But surely this is a
different issue than type checking.

Jul 22 '05 #10

P: n/a
On Mon, 10 May 2004 01:45:53 GMT, "Canonical Latin" <ja******@hotmail.com>
wrote:

"Leor Zolman" <le**@bdsoft.com> wrote in message
news:6d********************************@4ax.com.. .

I was in fact trying to answer the question. The way you used the word
"type", however, led me to believe I needed to clarify the distinction
between type and object in the context of using the sizeof operator. If
that in itself didn't answer your question, I was inviting you to rephrase
it so I could understand what you meant.
Sorry. I had assumed the use of word 'type' was clear in the context of my
question. But here is a more carefully 'worded' version.


I tend to take wording pretty literally, because often ambiguous wording
reflects a poster's unfamiliarity with the basic concepts--so I can't be
quite sure if the question I think I'm answering is the one really being
asked. I, in fact, often answer the wrong question even when the wording is
/clear/, so I tend to ask for clarification a lot ;-)

int v[3];
int w[3][3];

Granted that v is a variable with certain storage type. But v is also a
variable of type int[3] and w is a of type int[3][3].
OK, I'm already hung up on your wording above. In this case it isn't going
to keep me from answering you subsequent questions, but... what do you mean
by v being "a variable with certain storage type", and "also a variable of
type int[3]" ? Isn't int[3] in fact "a certain storage type"? I'm sorry,
this is a really strange way to phrase whatever it is you're thinking, and
I must admit I haven't a clue as to what you are trying to say. But
hopefully it won't matter, if you understand what's going on below.

void fun1(int v[2]) {}
void fun2(int v[2][3]) {}
void fun3(int v[2][2]) {}
int main() {
int v[3]={};
int w[3][3]={};
Are the empty braces just to force zero-initialization? I didn't even
realize that was legal, until just trying it. Usually I see at least a 0
in there, e.g:
int v[] = {0};
But I guess that's just a matter of style.
fun1(v);
fun2(w);
fun3(w);
}

It is a mystery to me why fun3(w) produces a compile error while the others
don't. For some reason the first dimension of an array is ignored when doing
type checking--as if v had the type int[] and w the type int[][3].
Formal parameters to a function written in the form of 1- or 2-dimensional
arrays actually do behave as you've just described, but they're actually
just pointers. Another way of looking at it: the first dimension of an
array parameter is "syntactic sugar", and is not actually part of the type.
The other dimensions are. In your definition of fun1 above, v has type
"pointer to int". In fun2, v has type "pointer to array of 3 ints". In
fun3, "pointer to array of 2 ints".

So let's look at your calls. In the call to fun1, you pass an array of int;
Arrays of T "decay" to type "pointer to T" when used in most contexts. So
you're actually passing a pointer to int, matching the parameter to fun1
fine.

In the call to fun2, you're passing w, a 2D array of ints with dims 3,3, or
alternatively, an array of 3 arrays of 3 ints. When you pass that to a
function, then, you're actually passing a pointer to an array of 3 ints.
Again a perfect match.

In the call to fun3, you're passing the same array, but this time to a
function expecting a different kind of pointer. Hence the error.
I used
sizeof operator to note that indeed v has the same storage requirement as
type int[2] in the main() which implies that at least here the compiler
acknowledges that v is indeed of type int[2] and not of type int[]. But then
later it treats it as int[] despite the specified type.
Okay, I've lost you again. You've defined v in main() as follows:
int v[3]={};
That's type int[3]; not type int[2], and certainly not int[] -- which isn't
even really a type, and you can test that by trying to compile a line like
this:
cout << "size: " << sizeof(int[]) << endl;
and noting it does not compile. Remember, when used in a formal parameter
declaration, it is really treated as "int *".
You can also check this by noting that fun(int v[3]) and fun(int v[4])
cannot be overloaded (since the compiler sees them as type int[])
which is the same as "int *"...
but the
fun(int v[3][3]) and fun(int v[4][4]) can be overloaded.
Right. Different types.

I realize that you don't need the size of the first dimension of an array
for index computation while you need the rest. But surely this is a
different issue than type checking.
Bzzzt. All but the first dimension of an array parameter are crucial to the
type; hence, crucial to type-/checking/.
-leor


--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Jul 22 '05 #11

P: n/a

"Leor Zolman" <le**@bdsoft.com> wrote in message
news:kt********************************@4ax.com...

I tend to take wording pretty literally, because often ambiguous wording
....
Bzzzt. All but the first dimension of an array parameter are crucial to the type; hence, crucial to type-/checking/.


I'm sorry that you can't understand me. I still thank you for your reply to
my original question but ask for no further assistance as I can't understand
your subsequent replies either. I still consider the second question
unanswered if someone else may have an idea.

The question is:

Why in ANSI c++ the first dimension of an array is ignored in its type name
in the examples that I gave (e.g overloading a function).


Jul 22 '05 #12

P: n/a
Canonical Latin wrote in
news:ZY******************@newssvr29.news.prodigy.c om in comp.lang.c++:
Why in ANSI c++ the first dimension of an array is ignored in its type
name in the examples that I gave (e.g overloading a function).


Because in C++ (and also C) you can't pass around array's.
The language handles arrays by /decaying/ them to pointers.
So a function such as:

int f( int a[3] );

is really:

int f( int *a );

Again:

int g( int b[3][2] );

is really:

int g( int (*b)[2] );

or (for typedef fans):

typedef two_ints[2];

int g( two_ints *b );
As to "Why ?", well that was how C was designed to work and C++
"inherited" the behaviour. "Why ?" doesn't actually matter, its
the way it is and we have to live with it.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #13

P: n/a
"Canonical Latin" <ja******@hotmail.com> wrote in message news:<k9******************@newssvr29.news.prodigy. com>...
"Leor Zolman" <le**@bdsoft.com> wrote in message
news:6d********************************@4ax.com...

I was in fact trying to answer the question. The way you used the word
"type", however, led me to believe I needed to clarify the distinction
between type and object in the context of using the sizeof operator. If
that in itself didn't answer your question, I was inviting you to rephrase
it so I could understand what you meant.
Sorry. I had assumed the use of word 'type' was clear in the context of my
question. But here is a more carefully 'worded' version.


When passed to functions, 1-D arrays are converted to pointers, and
n-dimension arrays are converted to pointers to n-1 dimension arrays.
Thus, for determining the type of the argument, it is the converted
value that is used.

Using your examples (with my comments)
void fun1(int v[2]) {} // equivalent to void fun1(int *v) {}
So it will work with any 1-D array or int pointer.
void fun2(int v[2][3]) {} // equivalent to void fun2(int *v[3]) {}
void fun3(int v[2][2]) {} // equivalent to void fun3(int *v[2]) {}
int main() {
int v[3]={};
int w[3][3]={};
fun1(v); // ok, converted type of argument is int *
fun2(w); // ok, converted type of argument is int *[3]
fun3(w); // error, conv.type of arg. is int *[3], expcecting int *[2]
}


See Stroustrup TC++PL section C.7 for more info, and also sections
4.2, 8.3.4 and 13.1 of the Standard.

HTH, Dave Moore
Jul 22 '05 #14

P: n/a
On Mon, 10 May 2004 04:57:29 GMT, "Canonical Latin" <ja******@hotmail.com>
wrote:

"Leor Zolman" <le**@bdsoft.com> wrote in message
news:kt********************************@4ax.com.. .

I tend to take wording pretty literally, because often ambiguous wording
....
Bzzzt. All but the first dimension of an array parameter are crucial to

the
type; hence, crucial to type-/checking/.


I'm sorry that you can't understand me. I still thank you for your reply to
my original question but ask for no further assistance as I can't understand
your subsequent replies either. I still consider the second question
unanswered if someone else may have an idea.


Darn, and I thought I did such a good job on that last one! Perhaps when
you put Rob's code and words alongside my longer-winded analysis, the
combination will make some sense ;-)
Good luck,
-leor

--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Jul 22 '05 #15

P: n/a
"Canonical Latin" <ja******@hotmail.com>:

It is a mystery to me why fun3(w) produces a compile error while the others
don't. For some reason the first dimension of an array is ignored when doing
type checking--as if v had the type int[] and w the type int[][3].
You cannot pass arrays to functions. You cannot declare a function that
takes an array as parameter (if you try, then what you are actually
declaring a function that takes a pointer to the first parameter of
that array). Finally, if you use an array name in a value context
(eg. as an argument in a function call), it gets converted to a pointer
to that array's first member.

You have observed that this conversion loses information: namely, the
number of elements in the array.
void fun1(int v[2]) {}
v[0] has type "int", so this is identical to:
void fun1(int *v) {}
void fun2(int v[2][3]) {}
v[0] has type "int [3]", so :
void fun2(int (*v)[3]) {}
void fun3(int v[2][2]) {}
void fun3(int (*v)[2]);

Some people prefer to always write the versions with "*",
to avoid confusion.
int main() {
int v[3]={};
v has type "int [3]"
int w[3][3]={};
w has type "int [3][3]"
fun1(v);
When using an array when a value is expected, the array is converted to
a pointer to its first element. v[0] has type "int", so &v[0] has
type "int *". Since fun1 is "void fun1(int *)", this is OK.
fun2(w);
w[0] has type "int [3]" . &w[0] has type "int (*)[3]".
fun2 is "void fun2(int (*)[3])". So this is OK too.
fun3(w);
&w[0] has type "int (*)[3]". But fun3 has type "void fun3(int (*)[2])".
So this is not OK. A set of rows (each containing 3 ints) cannot be
substituted for a set of rows (each containing 2 ints).
}


In case you were unaware, you could pass a pointer to the entire array
to a function:

void fun4(int (*v)[3][3]); // or: void fun4(int v[1][3][3])

int x[3][3];
fun4(&x);
Jul 22 '05 #16

P: n/a
On Sun, 09 May 2004 16:22:00 GMT, "Canonical Latin"
<ja******@hotmail.com> wrote:

"Canonical Latin" <ja******@hotmail.com> wrote in message
news:7d**************************@posting.google. com...
#include<iostream>
int main() {
char buff[3];
std::cin.getline(buff,3);
std::cin.getline(buff,3);
std::cout << buff << endl;
}
Run at command prompt and input
1234567
what do you get as output?
Please include your compiler make/version in replies.

I expect the output to be an empty line.


The reason I think it is reasonable for buff[0]='\0' after the second
getline() is that then the character count is zero indicating that nothing
was read. This behavior is backward compatible with C getlen().


The standard is currently ambiguous on this point (what getline should
do for a non-good stream), but there is a defect about it
(http://anubis.dkuug.dk/jtc1/sc22/wg2...fects.html#243)
which resolves it to behave as you want. Dinkumware's library already
does it that way apparently.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #17

P: n/a

"tom_usenet" <to********@hotmail.com> wrote in message
news:s2********************************@4ax.com...

The standard is currently ambiguous on this point (what getline should
do for a non-good stream), but there is a defect about it
(http://anubis.dkuug.dk/jtc1/sc22/wg2...fects.html#243)
which resolves it to behave as you want. Dinkumware's library already
does it that way apparently.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html


Thank you that is a great reference. That link answers a lot of the
questions that I've had and a great many that I've not even asked yet. But
I'm still curious as to the rational of having type
pointer-to-array-of-size-N-of-type-T (which is fine) and not having type
array-of-size-N-of-type-T (with some exceptions, which is curious). So far
the consensus seems to be that while everyone is aware of this no one knows
the rational behind it. I'm sure there must be a compelling reason for this
and once explained it would be obvious :)


Jul 22 '05 #18

P: n/a
On Tue, 11 May 2004 16:53:52 GMT, "Canonical Latin" <ja******@hotmail.com>
wrote:

"tom_usenet" <to********@hotmail.com> wrote in message
news:s2********************************@4ax.com.. .

The standard is currently ambiguous on this point (what getline should
do for a non-good stream), but there is a defect about it
(http://anubis.dkuug.dk/jtc1/sc22/wg2...fects.html#243)
which resolves it to behave as you want. Dinkumware's library already
does it that way apparently.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Thank you that is a great reference. That link answers a lot of the
questions that I've had and a great many that I've not even asked yet. But
I'm still curious as to the rational of having type
pointer-to-array-of-size-N-of-type-T (which is fine) and not having type
array-of-size-N-of-type-T (with some exceptions, which is curious).


I know you asked me not to answer any more of your questions, but I'm
stubborn ;-)

The place where you can't have array-of-size-N is in the special case of a
function parameter. Otherwise they're fine.

In the case of function parameters, if an array got passed by value, that
would be a very expensive operation. Most of the time folks would have to
program around it, by writing an expression that evaluates to a pointer of
some kind and passing /that/. But believe it or not, if arrays got passed
by value, that would actually be the special case...because of the
following:

As I'm fond of saying, arrays are just "smoke and mirrors" anyway; they're
mostly syntactic sugar, and compilers translate array names into pointers
to their first elements (there are a few exceptions, such as when applying
sizeof). That's true even if you don't pass them to a function.

So, given:
int a[10];
a[3] = 5;

that last line actually compiles into something like:
*(&a[0] + 3) = 5;

Therefore, in a function call such as:
func(a);

it makes perfect sense what gets passed is a pointer to the first element
of the array:

func(&a[0]);

and thus there's no information available to the function about the size of
that array.
-leor


So far
the consensus seems to be that while everyone is aware of this no one knows
the rational behind it. I'm sure there must be a compelling reason for this
and once explained it would be obvious :)


--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Jul 22 '05 #19

P: n/a

"Leor Zolman" <le**@bdsoft.com> wrote in message
news:p8********************************@4ax.com...
On Tue, 11 May 2004 16:53:52 GMT, "Canonical Latin" <ja******@hotmail.com>
wrote:

"tom_usenet" <to********@hotmail.com> wrote in message
news:s2********************************@4ax.com.. .

The standard is currently ambiguous on this point (what getline should
do for a non-good stream), but there is a defect about it
(http://anubis.dkuug.dk/jtc1/sc22/wg2...fects.html#243)
which resolves it to behave as you want. Dinkumware's library already
does it that way apparently.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Thank you that is a great reference. That link answers a lot of the
questions that I've had and a great many that I've not even asked yet. ButI'm still curious as to the rational of having type
pointer-to-array-of-size-N-of-type-T (which is fine) and not having type
array-of-size-N-of-type-T (with some exceptions, which is curious).


I know you asked me not to answer any more of your questions, but I'm
stubborn ;-)

The place where you can't have array-of-size-N is in the special case of a
function parameter. Otherwise they're fine.

In the case of function parameters, if an array got passed by value, that
would be a very expensive operation. Most of the time folks would have to
program around it, by writing an expression that evaluates to a pointer of
some kind and passing /that/. But believe it or not, if arrays got passed
by value, that would actually be the special case...because of the
following:

As I'm fond of saying, arrays are just "smoke and mirrors" anyway; they're
mostly syntactic sugar, and compilers translate array names into pointers
to their first elements (there are a few exceptions, such as when applying
sizeof). That's true even if you don't pass them to a function.

So, given:
int a[10];
a[3] = 5;

that last line actually compiles into something like:
*(&a[0] + 3) = 5;

Therefore, in a function call such as:
func(a);

it makes perfect sense what gets passed is a pointer to the first element
of the array:

func(&a[0]);

and thus there's no information available to the function about the size

of that array.
-leor


So far
the consensus seems to be that while everyone is aware of this no one knowsthe rational behind it. I'm sure there must be a compelling reason for thisand once explained it would be obvious :)


--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html


As this thread seems to be about an entirely different issue than the
original question, I have started a new thread
"Typed arrays (was: Is it ANSI or is it compiler dependent?)"
Jul 22 '05 #20

P: n/a
Leor Zolman wrote:
In the case of function parameters, if an array got passed by value, that
would be a very expensive operation. Most of the time folks would have to
program around it, by writing an expression that evaluates to a pointer of
some kind and passing /that/. But believe it or not, if arrays got passed
by value, that would actually be the special case...
That's not really true. Conceptually, arrays are aggregates and in this
respect they are not different from structs. Making arrays passable "by
value" wouldn't make things more complicated or inconvenient they
already are with structs. Folks would have to do the same thing they
always did - if you want to pass something large and don't need a copy -
pass it "by pointer".

Actually, impossibility to pass arrays by value made things _more_
cumbersome and error prone, because it breaks the invariance of the code
with respect to aggregate types hidden behind typedef-names. The
following function will accepts its parameters very differently,
depending on whether typedef-name 'T' designates array type or struct type

void foo(T agg)

and that's not a good thing.
because of the following:

As I'm fond of saying, arrays are just "smoke and mirrors" anyway; they're
mostly syntactic sugar, and compilers translate array names into pointers
to their first elements (there are a few exceptions, such as when applying
sizeof).
The only reason you can call these contexts (where arrays don't decay
into pointers) "exceptions" is that these contexts are apparently
relatively rare compared to the contexts where arrays do decay to
pointers (especially true for C). But that's a fake reason. Nothing more
than an illusion.

From the formal point of view, arrays keeping their "arrayness" is the
_normal_ behavior of arrays, while arrays decaying into pointers is the
abnormal (exceptional) behavior. It is definitely not correct to say
that arrays are just "smoke and mirrors".
That's true even if you don't pass them to a function.

So, given:
int a[10];
a[3] = 5;

that last line actually compiles into something like:
*(&a[0] + 3) = 5;

Therefore, in a function call such as:
func(a);

it makes perfect sense what gets passed is a pointer to the first element
of the array:

func(&a[0]);

and thus there's no information available to the function about the size of
that array.


Well, it is also important to understand that allowing an array to decay
to a pointer when passed to a function is a useful trick, which has its
own specific purpose. It purpose is to help create functions that can
work with arrays of different sizes.

In contexts where the ability to work with differently sized arrays is
not needed, it makes more sense to pass arrays by array-typed
pointer/reference (i.e. by a pointer/reference of
pointer/reference-to-array type). For example, an application that works
with, say, 3d geometry and used the following type to represent points
in 3D space

typedef int point_t[3];

should pass these points to functions as follows

void foo(const point_t& point)

or

void bar(const int (&point)[3])

not as

void foo(const point_t point)
void bar(const int point[3])

Note, that such function declaration are invariant to the possible
future change of 'point_t' definition to

typedef struct point_t { int x, y, z; };

--
Best regards,
Andrey Tarasevich

Jul 22 '05 #21

P: n/a

"Andrey Tarasevich" <an**************@hotmail.com> wrote in message
news:10*************@news.supernews.com...
Leor Zolman wrote:
In the case of function parameters, if an array got passed by value, that would be a very expensive operation. Most of the time folks would have to program around it, by writing an expression that evaluates to a pointer of some kind and passing /that/. But believe it or not, if arrays got passed by value, that would actually be the special case...


That's not really true. Conceptually, arrays are aggregates and in this
respect they are not different from structs. Making arrays passable "by
value" wouldn't make things more complicated or inconvenient they
already are with structs. Folks would have to do the same thing they
always did - if you want to pass something large and don't need a copy -
pass it "by pointer".

Actually, impossibility to pass arrays by value made things _more_
cumbersome and error prone, because it breaks the invariance of the code
with respect to aggregate types hidden behind typedef-names. The
following function will accepts its parameters very differently,
depending on whether typedef-name 'T' designates array type or struct type

void foo(T agg)

and that's not a good thing.
because of the following:

As I'm fond of saying, arrays are just "smoke and mirrors" anyway; they're mostly syntactic sugar, and compilers translate array names into pointers to their first elements (there are a few exceptions, such as when applying sizeof).


The only reason you can call these contexts (where arrays don't decay
into pointers) "exceptions" is that these contexts are apparently
relatively rare compared to the contexts where arrays do decay to
pointers (especially true for C). But that's a fake reason. Nothing more
than an illusion.

From the formal point of view, arrays keeping their "arrayness" is the
_normal_ behavior of arrays, while arrays decaying into pointers is the
abnormal (exceptional) behavior. It is definitely not correct to say
that arrays are just "smoke and mirrors".
That's true even if you don't pass them to a function.

So, given:
int a[10];
a[3] = 5;

that last line actually compiles into something like:
*(&a[0] + 3) = 5;

Therefore, in a function call such as:
func(a);

it makes perfect sense what gets passed is a pointer to the first element of the array:

func(&a[0]);

and thus there's no information available to the function about the size of that array.


Well, it is also important to understand that allowing an array to decay
to a pointer when passed to a function is a useful trick, which has its
own specific purpose. It purpose is to help create functions that can
work with arrays of different sizes.

In contexts where the ability to work with differently sized arrays is
not needed, it makes more sense to pass arrays by array-typed
pointer/reference (i.e. by a pointer/reference of
pointer/reference-to-array type). For example, an application that works
with, say, 3d geometry and used the following type to represent points
in 3D space

typedef int point_t[3];

should pass these points to functions as follows

void foo(const point_t& point)

or

void bar(const int (&point)[3])

not as

void foo(const point_t point)
void bar(const int point[3])

Note, that such function declaration are invariant to the possible
future change of 'point_t' definition to

typedef struct point_t { int x, y, z; };

--
Best regards,
Andrey Tarasevich


I like your reply Andery. But your idea is a bit more revolutionary than
mine. Read my alternative solution of decaying array-to-size-N-of-type-T to
pointer-to-type-T only if there is no matching type for N in the new thread
"Typed Arrays". I won't shy away from some constructive criticism :)
Jul 22 '05 #22

P: n/a
On Tue, 11 May 2004 16:35:15 -0700, Andrey Tarasevich
<an**************@hotmail.com> wrote:
Leor Zolman wrote:
In the case of function parameters, if an array got passed by value, that
would be a very expensive operation. Most of the time folks would have to
program around it, by writing an expression that evaluates to a pointer of
some kind and passing /that/. But believe it or not, if arrays got passed
by value, that would actually be the special case...
That's not really true. Conceptually, arrays are aggregates and in this
respect they are not different from structs. Making arrays passable "by
value" wouldn't make things more complicated or inconvenient they
already are with structs. Folks would have to do the same thing they
always did - if you want to pass something large and don't need a copy -
pass it "by pointer".


I could have been clearer about what I meant there, but I see your point.
What I meant by it being a special case for arrays to be passed by value,
is that it would be an exception to the rule that an array name 'a' may
have '&a[0]' substituted for it (the current exceptions I know of being
sizeof, & and declarators). So the behavior of arrays as function
parameters is consistent with /that/, not with the behavior of structs.

BTW, I agree in principle that if arrays had always been first-class
citizens, then that would probably have been a Good Thing.

Actually, impossibility to pass arrays by value made things _more_
cumbersome and error prone, because it breaks the invariance of the code
with respect to aggregate types hidden behind typedef-names. The
following function will accepts its parameters very differently,
depending on whether typedef-name 'T' designates array type or struct type

void foo(T agg)

and that's not a good thing.
because of the following:

As I'm fond of saying, arrays are just "smoke and mirrors" anyway; they're
mostly syntactic sugar, and compilers translate array names into pointers
to their first elements (there are a few exceptions, such as when applying
sizeof).
The only reason you can call these contexts (where arrays don't decay
into pointers) "exceptions" is that these contexts are apparently
relatively rare compared to the contexts where arrays do decay to
pointers (especially true for C). But that's a fake reason. Nothing more
than an illusion.

From the formal point of view, arrays keeping their "arrayness" is the
_normal_ behavior of arrays, while arrays decaying into pointers is the
abnormal (exceptional) behavior. It is definitely not correct to say
that arrays are just "smoke and mirrors".


"Not correct"? Okay, so perhaps my view of reality is, in fact, incorrect.
This wouldn't be the first time I've had to come to grips with /that/.
That's true even if you don't pass them to a function.

So, given:
int a[10];
a[3] = 5;

that last line actually compiles into something like:
*(&a[0] + 3) = 5;

Therefore, in a function call such as:
func(a);

it makes perfect sense what gets passed is a pointer to the first element
of the array:

func(&a[0]);

and thus there's no information available to the function about the size of
that array.


Well, it is also important to understand that allowing an array to decay
to a pointer when passed to a function is a useful trick, which has its
own specific purpose. It purpose is to help create functions that can
work with arrays of different sizes.

In contexts where the ability to work with differently sized arrays is
not needed, it makes more sense to pass arrays by array-typed
pointer/reference (i.e. by a pointer/reference of
pointer/reference-to-array type). For example, an application that works
with, say, 3d geometry and used the following type to represent points
in 3D space

typedef int point_t[3];

should pass these points to functions as follows

void foo(const point_t& point)

or

void bar(const int (&point)[3])

not as

void foo(const point_t point)
void bar(const int point[3])

Note, that such function declaration are invariant to the possible
future change of 'point_t' definition to

typedef struct point_t { int x, y, z; };


So that would make boost:;array, or some similar class template, a better
tool for the job in those cases, sure.
-leor
--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Jul 22 '05 #23

This discussion thread is closed

Replies have been disabled for this discussion.