类型化数组(是:它是ANSI还是依赖于编译器?) [英] Typed arrays (was: Is it ANSI or is it compiler dependent?)

查看:66
本文介绍了类型化数组(是:它是ANSI还是依赖于编译器?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Leor Zolman <乐** @ bdsoft.com>写了

" Canonical Latin" < JA ****** @ hotmail.com>写道:

...
但我仍然很好奇有类型的指向
指针到数组的大小N -of-type-T(很好)并且没有类型大小的N-of-type-T型(有一些例外,这很奇怪)。
到目前为止似乎共识似乎是每个人都知道这一点,没有人知道它背后的理性。我肯定必须有一个令人信服的理由
这个曾经解释过很明显:)

我知道你让我不再回答你的问题了,但是我'
顽固;-)

函数参数的特殊情况是你不能有大小数组N的地方。否则他们就没事了。

在函数参数的情况下,如果一个数组按值传递,那将是一个非常昂贵的操作。大多数时候,人们不得不围绕它编程,通过编写一个表达式来评估某种指针和传递/那个/。不管你信不信,如果数组通过价值传递,那实际上就是特例......因为
以下内容:

因为我很喜欢当然,阵列只是烟雾和镜子。无论如何;它们主要是语法糖,编译器将数组名称转换为指向第一个元素的指针(有一些例外,例如应用
sizeof时)。即使你没有把它们传递给一个函数也是如此。

所以,给定:
int a [10];
a [3] = 5 ;

最后一行实际编译成如下:
*(& a [0] + 3)= 5;

因此,在函数调用中例如:
func(a);

完全可以理解传递的是指向阵列第一个元素的指针:

func(& a [0]);

因此该函数没有关于该数组的大小



的信息。< -leor

- Leor Zolman --- BD软件--- www.bdsoft.com
C / C ++,Java,Perl和Unix的现场培训
C ++用户:下载BD Software的免费STL错误消息解密器at:
www.bdsoft.com/tools/stlfilt.html




键入检查d通过值传递是两个不同的问题。考虑:


fun1(T []); //指向类型的指针-

fun2(T [2]); //数组大小为2-type-T

fun3(T [3]); //数组大小-T-type-T

fun4(T **); //指针指向类型-T

fun5(T * [2]); //指向数组大小的数组-T-

fun6(T * [3]); //指向数组大小的数组-T-

在任何情况下,整个数组都是按值传递的,这不是

问题。假设c ++实际上确实有一个合法的类型

array-of-size-N-of-type-T。然后


fun(T x []); // fun1


fun(T x [2]); // fun2


fun(T x [3]); // fun3


main(){


T a [2];


T b [3];


T c [4];


T * d;


fun(a); //给fun2打电话


fun(b); // call fun3


fun(c); // call fun1(见末尾的评论)


fun(d); //调用fun1


}


显然这在c ++中不起作用,因为编译器看到了

数组在大多数情况下,-of-size-N-of-type-T指向类型-T。执行类型

检查数组与按值传递整个数组无关。

如果你认为我对所谓行为的描述太过分了,或者那个

数组只是冒烟和镜像然后考虑


void fun(T ** x){cout<< " FUN1英寸; }


void fun(T(* x)[2]){cout<< " FUN2英寸; }


void fun(T(* x)[3]){cout<< " FUN3英寸; }


int main(int argc,char * argv []){


T(* a)[2];


T(* b)[3];


T(* c)[4];


T ** d;


fun(a); //给fun2打电话


fun(b); // call fun3


fun((T **)(c)); //调用fun1(在c ++中不安全)


fun(d); //调用fun1


}


编译并按预期运行。请注意,

值没有传递任何内容。这就是说,对于N的每个值,指针到数组大小的N-type-T是一个不同的类型。我所说的是到目前为止我有没有听到一个令人信服的理由为什么大小为N-of-type-T也不应该为每个N值提供一个不同的类型。 b br />

另一个与此密切相关的问题:

c ++中存在一个问题,类型指针指向数组大小为N-of -type-T我标记为

" unsafe"在我的例子中。基本上你不能转换

指针到数组大小的N-of-type-T到指针指向类型-T而没有

使用重新解释演员。这可能是

重新解释大小为N-of-type-T作为指向类型-T的奇怪行为的来源。当然,

这整个业务都会消失(我们会在讨价还价中得到真正的类型数组)

如果是数组大小的N-of-type-T是只有当N的特定值没有匹配类型时,才会自动转换为指向类型的指针-B
.

解决方案




" Andrey Tarasevich" <一个************** @ hotmail.com>在消息中写道

news:10 ************* @ news.supernews.com ...

Leor Zolman写道:

在函数参数的情况下,如果数组通过值传递,
将是一个非常昂贵的操作。大多数时候人们会有
来编程它,通过编写一个表达式来计算某种指针
并传递/ that /。不管你信不信,如果数组得到的价值是
,那实际上就是特例......



这不是真的。从概念上讲,数组是聚合的,在这方面,它们与结构没有区别。使数组可通过通过
值不会让事情更复杂或不方便他们已经结构了。人们必须做同样的事情 - 如果你想要传递大的东西而不需要副本 -
通过指针传递它。
跟随函数将以非常不同的方式接受其参数,
取决于typedef-name''T''是否指定数组类型或结构类型

void foo(T agg)<这个并不是件好事。

因为以下原因:

因为我喜欢说,阵列只是烟雾和镜子。无论如何;
他们主要是语法糖,并且编译器将数组名称转换为
指向其第一个元素的指针(有一些例外,例如当
应用sizeof时)。



你可以调用这些上下文的唯一原因(数组不会衰减到指针中)异常这是因为与数组衰减到指针的情况相比,这些上下文显然相对较少(特别是对于C来说是真的)。但这是一个错误的理由。没有什么比幻觉更多了。

从形式上看,数组保持其数组性。是数组的
_normal_行为,而衰减为指针的数组是异常(异常)行为。说数组只是烟雾和镜子是绝对不正确的。

即使你没有将它们传递给一个也是如此函数。

所以,给定:
int a [10];
a [3] = 5;

最后一行实际编译成某事喜欢:
*(& a [0] + 3)= 5;

因此,在函数调用中如:
func(a);

完全可以理解传递的是指向数组的第一个
元素的指针:

func(& a [0]);

因此该函数没有关于该数组大小
的信息。



嗯,理解允许数组到传递给函数时衰减指针是一个有用的技巧,它有其特定的目的。它的目的是帮助创建可以使用不同大小的数组的函数。

在不需要使用不同大小的数组的能力的情况下,它会产生更多通过数组类型的指针/引用传递数组的意义(即通过指针/引用/指向数组类型的指针/引用)。例如,一个与3d几何体一起工作的应用程序,并使用以下类型来表示3D空间中的点

typedef int point_t [3];

应该将这些要点传递给以下函数

void foo(const point_t& point)



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

不如

void foo(const point_t point)
void bar(const int point [3])<注意,这样的函数声明对于''point_t''定义可能的未来变化是不变的

typedef struct point_t {int x,y,z ;最好的问候,
Andrey Tarasevich




我喜欢你的回复Andery。但是你的想法比我的b
更具革命性。只有在新线程中没有N的匹配类型时,才能读取我的替代解决方案,即将数组大小为N-of-type-T衰减到
指针到类型-T />
Typed Arrays。我不会回避一些建设性的批评:)


Canonical Latin写道:

...
类型检查和按值传递是两个不同的问题。考虑一下:

fun1(T []); //指向类型-T

fun2(T [2]); // array-of-size-2-of-type-T

fun3(T [3]); // array-of-size-3-of-type-T

fun4(T **); //指针指向类型-T

fun5(T * [2]); //指向数组的大小为2-of-type-T


不,它是一个2''T *'的数组。

fun6(T * [3]); //指向数组的大小为3的类型-T


不,它是一个3''T *'的数组。


你可能意味着


fun5(T(*)[2])

fun5(T(*)[3 ])

在任何情况下,整个数组都按值传递,这不是问题。假设c ++实际上确实有一个合法类型的数组大小为N-of-type-T。那么


但是,C ++确实有一个合法类型的数组大小为N-of-type-T。不过

虽然功能齐全。

fun(T x []); // fun1

有趣(T x [2]); // fun2

有趣(T x [3]); // fun3

main(){

T a [2];

T b [3];
T c [4];

T * d;

有趣(a); //呼叫fun2

有趣(b); //打电话给fun3

有趣(c); //调用fun1(见末尾的评论)

有趣(d); //调用fun1



显然这在c ++中不起作用,因为编译器会看到
数组大小为N-of-type-T在大多数情况下,作为指向类型的指针。


这不完全正确。在函数参数声明的情况下,编译器将size-of-size-N-of-type-T视为指向类型-T的指针。其余的

如下。这是特定于当一个人使用语法时的情况

尝试按值按传递数组。


注意,如果你将你的函数声明为


fun(T(& x)[2]); // fun2

fun(T(& x)[3]); // fun3


重载将按照你的描述开始工作。

强制类型
检查数组与传递整个数组无关按价值。
如果你认为我对所谓行为的描述太过分了,或者说数组只是冒烟和镜像。然后考虑

void fun(T ** x){cout<< " FUN1英寸;无趣(T(* x)[2]){cout<< " FUN2英寸;无趣(T(* x)[3]){cout<< " FUN3英寸; }


T(* a)[2];

T(* b)[3];

T(* c)[4];

T ** d;

有趣(a); //呼叫fun2

有趣(b); // call fun3

有趣((T **)(c)); //调用fun1(在c ++中不安全)

有趣(d); //调用fun1



编译和行为符合预期。请注意,
值没有传递任何内容。这就是说,对于N的每个值,指针到数组大小的N-type-T是一个不同的类型。我所说的是到目前为止我已经没有听到令人信服的理由为什么阵列大小的N-of-type-T也不应该是每个N值的不同类型。


它_is_每个on值的不同类型。在某些情况下,由于数组到指针的转换,这个

差异会丢失。

另一个与此密切相关的问题:
c ++类型指针到数组大小的N-of-type-T我标记为
unsafe"在我的例子中。基本上你不能使用重新解释转换将指针指向大小为N-of-type-T的指针转换为指针指向类型-T。这可能是将数组大小为N-of-type-T重新解释为指向类型-T的指针的奇怪行为的来源。当然,这整个业务都会消失(我们会在讨价还价中得到真正的类型数组)
如果size-of-size-N-of-type-T自动转换为指向类型的指针-T
只有当N的特定值没有匹配类型时才会显示。




嗯..我不完全明白你在尝试什么在这里说。


-

祝你好运,

Andrey Tarasevich




" Andrey Tarasevich" <一个************** @ hotmail.com>在消息中写道

news:10 ************* @ news.supernews.com ...

Canonical Latin写道:

...
类型检查和按值传递是两个不同的问题。考虑一下:

fun1(T []); //指向类型-T
fun2(T [2]); // array-of-size-2-of-type-T
fun3(T [3]); // array-of-size-3-of-type-T
fun4(T **); //指针指向类型-T
fun5(T * [2]); //指向数组大小的指针-T ->
不,它是一个2''T *'的数组。

fun6(T * [3]); //指向数组的大小为3的数组-T


不,它是一个3''T *'的数组。

你可能意味着

fun5(T(*)[2])
fun5(T(*)[3])




哎呀!是的我的意思是


在任何情况下,整个数组都是按值传递的,这不是
问题。假设c ++实际上确实有一个合法类型的数组大小为N-of-type-T。那么



但是,C ++确实有一个合法类型的数组大小为N-of-type-T。虽然不是完全正常的。

fun(T x []); // fun1
有趣(T x [2]); // fun2
有趣(T x [3]); // fun3
main(){
T a [2];
T b [3];
T c [4];

T * d;
有趣(a); // call fun2
有趣(b); // call fun3
有趣(c); //调用fun1(见末尾的评论)
有趣(d); //调用fun1
}

显然这在c ++中不起作用,因为编译器认为
size-of-size-N-of-type-T指针指向-type-T在大多数情况下。



这不完全正确。在函数参数声明的情况下,编译器将size-of-size-N-of-type-T视为指向类型-T的指针。其余的
如下。这特定于当一个人使语法尝试按值传递数组时的情况。

注意,如果你声明你的函数是有趣的(/ T(& x)[2]); // fun2
有趣(T(& x)[3]); // fun3



这很棒。它几乎就在那里。唯一的问题是,现在你不能



fun(T x []); // fun1

并用它来调用

T xx [4];

fun(xx);

重载将按照您的描述开始工作。

执行类型检查数组与将整个数组传递
值无关。如果你认为我对假设行为的描述太过分了,或者b $ b,那么数组只是冒烟和镜像。然后考虑

void fun(T ** x){cout<< " FUN1英寸; }
void fun(T(* x)[2]){cout<< " FUN2英寸; } fun /> void fun(T(* x)[3]){cout<< " FUN3英寸; }
int main(int argc,char * argv []){
T(* a)[2];
T(* b)[3];
T( * c)[4];
T ** d;
有趣(a); // call fun2
有趣(b); // call fun3
fun((T **)(c)); //调用fun1(在c ++中不安全)
有趣(d); //调用fun1
}

编译和行为符合预期。请注意,
值没有传递任何内容。这就是说,对于N的每个值,指针到数组大小的N-of-type-T
是不同的类型。我所说的是到目前为止我
没有听到一个令人信服的理由为什么大小为N的类型-T不应该是
对于N的每个值也是一个不同的类型。
它_is_是每个值的不同类型上。在某些情况下,由于数组到指针的转换,这种差异会丢失。

与此密切相关的另一个问题是:已经存在
问题在c ++中使用类型指针到数组大小的N-of-type-T,我将其标记为
unsafe在我的例子中。基本上你不能在不使用重新解释转换的情况下将指针指向大小的N-of-type-T转换为指向类型-T
的指针。这可能是奇怪行为
重新解释大小为N-of-type-T作为指针到类型-T的来源。
当然,如果size-of-size-N-of-type-T自动转换为
指针,整个业务将消失(我们在
讨价还价中获得真正的类型数组) -to-type-T只有当N的特定值没有匹配类型时才会显示。



嗯......我不完全理解你在这里想说的话。



我不确定是否也这样做,但我尝试了!这是另一种尝试:因为它是,

数组大小的N-of-type-T衰减到指针类型-T而不是参数

sizeof并且正如您所指出的那样不符合&。让我说我想要数组类型

检查并且仍然希望能够将T [N]传递给不具有的功能

指定N值例如

fun(T * x); // funA

fun(T(& x)[2]); // funB

main(){

T x [3];

fun(x); // funA

}

所以编译器试图找到乐趣(T(& x)[3]),因为它不能那么

自动寻找乐趣(T * x); // funA

-
致以最诚挚的问候,
Andrey Tarasevich




"Leor Zolman" <le**@bdsoft.com> wrote

"Canonical Latin" <ja******@hotmail.com> wrote:

...
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 knowsthe rational behind it. I''m sure there must be a compelling reason for thisand once explained it would be obvious :)

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

--
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



Type checking and passing by value are two different issues. Consider:

fun1 (T[]); // pointer-to-type-T

fun2 (T[2]); // array-of-size-2-of-type-T

fun3 (T[3]); // array-of-size-3-of-type-T

fun4 (T**); // pointer-to-pointer-to-type-T

fun5 (T*[2]); // pointer-to-array-of-size-2-of-type-T

fun6 (T*[3]); // pointer-to-array-of-size-3-of-type-T

In none of the cases the whole array is passed by value and this is not the
issue. Suppose that c++ actually did have a legitimate type
array-of-size-N-of-type-T. Then

fun (T x[]); // fun1

fun (T x[2]); // fun2

fun (T x[3]); // fun3

main() {

T a[2];

T b[3];

T c[4];

T *d;

fun(a); // call fun2

fun(b) ; // call fun3

fun(c) ; // call fun1 (see comment at end)

fun(d) ; // call fun1

}

Obviously this doesn''t work in c++ because compiler sees
array-of-size-N-of-type-T as pointer-to-type-T in most cases. Enforcing type
checking for arrays has nothing to do with passing the whole array by value.
If you think my description of supposed behavior is too far fetched, or that
arrays are just "smoke and mirror" then consider

void fun (T **x) { cout << "fun1"; }

void fun (T (*x)[2]) { cout << "fun2"; }

void fun (T (*x)[3]) { cout << "fun3"; }

int main(int argc, char *argv[]) {

T (*a)[2];

T (*b)[3];

T (*c)[4];

T **d;

fun(a); // call fun2

fun(b) ; // call fun3

fun((T**)(c)) ; // call fun1 (unsafe in c++)

fun(d) ; // call fun1

}

which compiles and behaves as expected. Note that nothing is passed by
value. What this is saying is that pointer-to-array-of-size-N-of-type-T is a
different type for each value of N. What I am saying is that so far I have
not heard a compelling reason why array-of-size-N-of-type-T should not also
be a different type for each value of N.

Another issue that is closely related to this: There is already a problem in
c++ with type pointer-to-array-of-size-N-of-type-T which I marked as
"unsafe" in my example. Essentially you cannot convert
pointer-to-array-of-size-N-of-type-T to pointer-to-pointer-of-type-T without
using a reinterpret cast. This perhaps is the source of the odd behavior of
reinterpreting array-of-size-N-of-type-T as pointer-to-type-T. Of course,
this whole business would go away (and we get true typed arrays in bargain)
if array-of-size-N-of-type-T is automatically converted to pointer-to-type-T
only if there is no matching type for the specific value of N.

解决方案



"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 :)


Canonical Latin wrote:

...
Type checking and passing by value are two different issues. Consider:

fun1 (T[]); // pointer-to-type-T

fun2 (T[2]); // array-of-size-2-of-type-T

fun3 (T[3]); // array-of-size-3-of-type-T

fun4 (T**); // pointer-to-pointer-to-type-T

fun5 (T*[2]); // pointer-to-array-of-size-2-of-type-T
No, it is an array of 2 ''T*''s.
fun6 (T*[3]); // pointer-to-array-of-size-3-of-type-T
No, it is an array of 3 ''T*''s.

You probably meant

fun5(T(*)[2])
fun5(T(*)[3])

In none of the cases the whole array is passed by value and this is not the
issue. Suppose that c++ actually did have a legitimate type
array-of-size-N-of-type-T. Then
But, C++ does have a legitimate type array-of-size-N-of-type-T. Not
fully functional though.
fun (T x[]); // fun1

fun (T x[2]); // fun2

fun (T x[3]); // fun3

main() {

T a[2];

T b[3];

T c[4];

T *d;

fun(a); // call fun2

fun(b) ; // call fun3

fun(c) ; // call fun1 (see comment at end)

fun(d) ; // call fun1

}

Obviously this doesn''t work in c++ because compiler sees
array-of-size-N-of-type-T as pointer-to-type-T in most cases.
It is not exactly correct. Compiler sees array-of-size-N-of-type-T as
pointer-to-type-T in case of function parameter declaration. The rest
follows. This is specific to situations when one makes syntactical
attempt to pass arrays "by value".

Note, that if you declare your functions as

fun (T (&x)[2]); // fun2
fun (T (&x)[3]); // fun3

the overloading will start working as you describe.
Enforcing type
checking for arrays has nothing to do with passing the whole array by value.
If you think my description of supposed behavior is too far fetched, or that
arrays are just "smoke and mirror" then consider

void fun (T **x) { cout << "fun1"; }

void fun (T (*x)[2]) { cout << "fun2"; }

void fun (T (*x)[3]) { cout << "fun3"; }

int main(int argc, char *argv[]) {

T (*a)[2];

T (*b)[3];

T (*c)[4];

T **d;

fun(a); // call fun2

fun(b) ; // call fun3

fun((T**)(c)) ; // call fun1 (unsafe in c++)

fun(d) ; // call fun1

}

which compiles and behaves as expected. Note that nothing is passed by
value. What this is saying is that pointer-to-array-of-size-N-of-type-T is a
different type for each value of N. What I am saying is that so far I have
not heard a compelling reason why array-of-size-N-of-type-T should not also
be a different type for each value of N.
It _is_ a different type for each value of on. In certain contexts this
difference is lost because of array-to-pointer conversion.
Another issue that is closely related to this: There is already a problem in
c++ with type pointer-to-array-of-size-N-of-type-T which I marked as
"unsafe" in my example. Essentially you cannot convert
pointer-to-array-of-size-N-of-type-T to pointer-to-pointer-of-type-T without
using a reinterpret cast. This perhaps is the source of the odd behavior of
reinterpreting array-of-size-N-of-type-T as pointer-to-type-T. Of course,
this whole business would go away (and we get true typed arrays in bargain)
if array-of-size-N-of-type-T is automatically converted to pointer-to-type-T
only if there is no matching type for the specific value of N.



Hmm.. I don''t exactly understand what you are trying to say here.

--
Best regards,
Andrey Tarasevich



"Andrey Tarasevich" <an**************@hotmail.com> wrote in message
news:10*************@news.supernews.com...

Canonical Latin wrote:

...
Type checking and passing by value are two different issues. Consider:

fun1 (T[]); // pointer-to-type-T
fun2 (T[2]); // array-of-size-2-of-type-T
fun3 (T[3]); // array-of-size-3-of-type-T
fun4 (T**); // pointer-to-pointer-to-type-T
fun5 (T*[2]); // pointer-to-array-of-size-2-of-type-T
No, it is an array of 2 ''T*''s.

fun6 (T*[3]); // pointer-to-array-of-size-3-of-type-T



No, it is an array of 3 ''T*''s.

You probably meant

fun5(T(*)[2])
fun5(T(*)[3])



Oops! Yes I did mean that


In none of the cases the whole array is passed by value and this is not the issue. Suppose that c++ actually did have a legitimate type
array-of-size-N-of-type-T. Then



But, C++ does have a legitimate type array-of-size-N-of-type-T. Not
fully functional though.

fun (T x[]); // fun1
fun (T x[2]); // fun2
fun (T x[3]); // fun3
main() {
T a[2];
T b[3];
T c[4];

T *d;
fun(a); // call fun2
fun(b) ; // call fun3
fun(c) ; // call fun1 (see comment at end)
fun(d) ; // call fun1
}

Obviously this doesn''t work in c++ because compiler sees
array-of-size-N-of-type-T as pointer-to-type-T in most cases.



It is not exactly correct. Compiler sees array-of-size-N-of-type-T as
pointer-to-type-T in case of function parameter declaration. The rest
follows. This is specific to situations when one makes syntactical
attempt to pass arrays "by value".

Note, that if you declare your functions as

fun (T (&x)[2]); // fun2
fun (T (&x)[3]); // fun3


That is great. It is almost there. The only problem is that now you cannot
have
fun (T x[]); // fun1
and call it with
T xx[4];
fun(xx);
the overloading will start working as you describe.

Enforcing type
checking for arrays has nothing to do with passing the whole array by value. If you think my description of supposed behavior is too far fetched, or that arrays are just "smoke and mirror" then consider

void fun (T **x) { cout << "fun1"; }
void fun (T (*x)[2]) { cout << "fun2"; }
void fun (T (*x)[3]) { cout << "fun3"; }
int main(int argc, char *argv[]) {
T (*a)[2];
T (*b)[3];
T (*c)[4];
T **d;
fun(a); // call fun2
fun(b) ; // call fun3
fun((T**)(c)) ; // call fun1 (unsafe in c++)
fun(d) ; // call fun1
}

which compiles and behaves as expected. Note that nothing is passed by
value. What this is saying is that pointer-to-array-of-size-N-of-type-T is a different type for each value of N. What I am saying is that so far I have not heard a compelling reason why array-of-size-N-of-type-T should not also be a different type for each value of N.
It _is_ a different type for each value of on. In certain contexts this
difference is lost because of array-to-pointer conversion.

Another issue that is closely related to this: There is already a problem in c++ with type pointer-to-array-of-size-N-of-type-T which I marked as
"unsafe" in my example. Essentially you cannot convert
pointer-to-array-of-size-N-of-type-T to pointer-to-pointer-of-type-T without using a reinterpret cast. This perhaps is the source of the odd behavior of reinterpreting array-of-size-N-of-type-T as pointer-to-type-T. Of course, this whole business would go away (and we get true typed arrays in bargain) if array-of-size-N-of-type-T is automatically converted to pointer-to-type-T only if there is no matching type for the specific value of N.



Hmm.. I don''t exactly understand what you are trying to say here.


I''m not sure I do either, but I try! Here is another attempt: as it is,
array-of-size-N-of-type-T decays to pointer-of-type-T when not argument to
sizeof and as you noted not qualified by &. Lets say I want array type
checking and still want to be able to pass T[N] to a function that does not
specify the N value e.g.
fun(T *x); // funA
fun(T (&x)[2]); // funB
main() {
T x[3] ;
fun(x) ; // funA
}
So the compiler tries to find fun(T (&x)[3]) and since it can''t then it
automatically looks for fun(T *x); // funA

--
Best regards,
Andrey Tarasevich




这篇关于类型化数组(是:它是ANSI还是依赖于编译器?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆