在C中进行类型转换 [英] Typecasting portability in C

查看:57
本文介绍了在C中进行类型转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要做的是在C中实现多态性。为什么?这是为了
构建一个库,它将是一个C库,可以从C调用。

但是,我想要具有可从
$调用的多态函数b $ b在图书馆外面。具体来说,我希望有像Show()

这样的函数,它将获取一个指向对象的指针,并根据传递给它的类型对象执行不同的
。当然这在C ++中会很简单,但是我只能使用C.


好​​吧所以我现在的想法就像多面性Show( )

例程:由于所有对象都是在库内创建的,我可以将每个对象附加一个签名。
Show()例程将接受一个

void *,然后对其进行类型转换并从对象中获取签名。

因为每个对象都是一个结构(并且已创建和定义)在

库中)我会将此签名附加到每个

结构的前面。签名可能类似于整数。所以

每个对象看起来都像:

struct SomeObjectType {

int signature;

..... //捆绑其他其他东西

};


Show()例程将void *转换为以下

结构:


struct {

int签名;

}


所以我的Show()和类似的多态例程将得到该对象,并且最终打开它并查看第一个字段,该字段始终是签名对象的
。根据它在那里找到的(

签名的价值),它会做一些不同的事情。说得通?我希望如此。


所以我已经实现了一些原型代码并且它确实有效但是我想知道这是多么便携?结构'的第一个

项目(签名)将始终保持相同,我可以保证,但

再次如何可移植性。我真的是从指针转换为

一种类型,转换为void *,然后指向另一种类型的指针(用于签名

提取)。当然,最终结构中的第一个对象将与原始结构中的第一个对象相同,并且相同的

大小也是如此。但这是否可以携带?


这个合法的C是否由标准定义?这是否可以跨平台运行

?我希望你看到我的困境,代码似乎在我的系统上运行

。下面的代码愉快地打印出预期的输出

112.但是我不知道它是否能保证在任何地方工作以及

便携式库函数将如何是因为它?


这是在任何C标准中定义的将会发生什么以及

关于一般可移植性的问题?

在下面的示例中,我定义了一个结构CanBeAnything并填充了

它带有long和char但实际上不仅仅是那个结构而是

之后的任何东西签名整数将不同于

对象到对象。我唯一能保证的是第一个

项目将是每个对象上的签名整数。这个

转换会有效吗?它是便携式的吗?它可以在我的机器上运行但是这样做

意味着它一般会起作用吗?谢谢。 :)


---

//在我的机器上运行时,下面的代码很高兴打印出112

/ /没有带警告标志的gcc编译器发出警告-Wall


#include< stdio.h>


//这个结构可以包含任何东西

struct CouldBeAnything

{

long ThisTimeItsALong;

char AndAChar;

};


struct MinimalStructure

{

int签名;

};

struct LargerStructure

{

int签名;

struct CouldBeAnything SomeStructure;

};


int main()

{

struct LargerStructure SomeLargeStructure;


SomeLargeStructure .Signature = 112;

SomeLargeStructure.SomeStructure.ThisTimeItsALong = 1;

SomeLargeStructure.SomeStructure.AndAChar =''a'';


struct MinimalStructure * Minimal =(struct MinimalStructu重新*)

& SomeLargeStructure;


printf(签名=%d \ n,最小 - >签名);

返回0;

}

What I am trying to do is implement polymorphism in C. Why? This is to
build a library which will be a C library and callable from C.
However, I want to have polymorphic functions which are callable from
outside the library. Specifically I want to have functions like Show()
which will take a pointer to an object and do something different
based on the type object passed to it. Of course this would be trival
in C++ but I''m restricted to use C.

OK so my current idea for something like the polymophic Show()
routine: Since all the objects are created inside the library I can
attach to each object a signature. The Show() routine would accept a
void* but then typecast it and get the signature out of the object.
Since each object is a structure (and created and defined inside the
library) I would append this signature to the front of each and every
struct. The signature would likely be something like an integer. So
each and every object would look like:

struct SomeObjectType {
int signature;
.....//bunch other other stuff
};

The Show() routine would typecast the void* to the following
structure:

struct {
int signature;
}

So my Show() and similar polymorphic routines would get the object and
ultimatly open it and look at the first field which would always be
the signature object. Based on what it found there (the value of
signature) it would do something different. Makes sense? I hope so.

So I have implemented some prototype code on this and it does work but
what I was wondering is how portable is this? The structure''s first
item (the signature) will always be the same this I can guarantee but
again what about portability. Really I''m converting from a pointer to
one type, to a void*, then to a pointer to another type (for signature
extraction). Certainly the first object in the final structure will be
the same as the first object in the original structure and the same
size as well. But does that make it portable?

Is this legal C as defined by the standard? Is this going to work
across platforms? I hope you see my dilemma the code appears to work
on my system. The code below happily prints the expected output of
112. but I don''t know if it''s guaranteed to work everywhere and how
portable the library functions will be because of it?

Is this defined in any C standard anywhere what will happen and what
about general portability concerns?

In the example below I defined a structure CouldBeAnything and filled
it with a long and a char but really not only that structure but
anything after that initial signature integer will be different from
object to object. The only thing I can guarantee is that the first
item will be that signature integer on each object. Will this
conversion work? Is it portable? It works on my machine but does that
mean it will work in general? Thank you. :)

---
//On the code below when run on my machine it happily prints out 112
//No warnings are given by the gcc complier with warning flag -Wall

#include <stdio.h>

//This structure could contain anything
struct CouldBeAnything
{
long ThisTimeItsALong;
char AndAChar;
};

struct MinimalStructure
{
int Signature;
};
struct LargerStructure
{
int Signature;
struct CouldBeAnything SomeStructure;
};

int main ()
{
struct LargerStructure SomeLargeStructure;

SomeLargeStructure.Signature = 112;
SomeLargeStructure.SomeStructure.ThisTimeItsALong = 1;
SomeLargeStructure.SomeStructure.AndAChar = ''a'';

struct MinimalStructure* Minimal = ( struct MinimalStructure* )
&SomeLargeStructure;

printf( "Signature = %d\n", Minimal->Signature );
return 0;
}

推荐答案

ch ***************** @ yahoo.com 写道:

我要做的是在C中实现多态。
What I am trying to do is implement polymorphism in C.



....

....


我会将此签名附加到每个

结构的前面。签名可能类似于整数。所以

每个对象看起来都像:

struct SomeObjectType {

int signature;

.... //捆绑其他其他东西

};


Show()例程会将void *强制转换为以下内容

结构:


struct {

int签名;

}
I would append this signature to the front of each and every
struct. The signature would likely be something like an integer. So
each and every object would look like:

struct SomeObjectType {
int signature;
....//bunch other other stuff
};

The Show() routine would typecast the void* to the following
structure:

struct {
int signature;
}



....

....


这个合法的C是否由标准定义?
Is this legal C as defined by the standard?



是的。如果两个结构的初始序列匹配,则可以通过任一结构类型访问初始序列中的成员。


您可能会考虑定义结构更准确地匹配

你的实际用法:


struct OverloadedType {

enum {ST1,ST2} subtype; / *以下数据的子类型* /

union {

struct ST1 {

/ * T1子类型成员* /

} st1;

struct ST2 {

/ * T2子类型成员* /

} st2;

} u;

} * ot;

....

开关(ot-subtype){

案例ST1:

do_something_to_ST1(& ot-> u.st1);

休息;

案例ST2:

do_something_to_ST2(& ot-> u.st2);

休息;

}


-

Thad

Yes. If the initial sequence of two structures match, the members in
the initial sequence can be accessed through either structure type.

You might consider, though, defining the struct to more accurately match
you actual usage:

struct OverloadedType {
enum {ST1, ST2} subtype; /* subtype of following data */
union {
struct ST1 {
/* T1 subtype members */
} st1;
struct ST2 {
/* T2 subtype members */
} st2;
} u;
} *ot;
....
switch (ot-subtype) {
case ST1:
do_something_to_ST1 (&ot->u.st1);
break;
case ST2:
do_something_to_ST2 (&ot->u.st2);
break;
}

--
Thad


Thad Smith写道:
Thad Smith wrote:
ch ***************** @ yahoo.com 写道:

>我要做的是在C中实现多态。
>What I am trying to do is implement polymorphism in C.



...

...


>我会将此签名附加到每个结构的前面。
签名可能是类似整数的东西。所以每个对象看起来都像:

struct SomeObjectType {
int signature;
.... //其他其他东西
} ;

Show()例程会将void *类型化为以下结构:

struct {
int signature;
}
>I would append this signature to the front of each and every struct.
The signature would likely be something like an integer. So each and
every object would look like:

struct SomeObjectType {
int signature;
....//bunch other other stuff
};

The Show() routine would typecast the void* to the following structure:

struct {
int signature;
}



...

...


>这个合法C是否由标准定义?
>Is this legal C as defined by the standard?



是的。如果两个结构的初始序列匹配,则可以通过任一结构类型访问初始序列中的成员。


Yes. If the initial sequence of two structures match, the members in
the initial sequence can be accessed through either structure type.



...如果两个结构是同一个联盟的成员。

编译器需要非常聪明且非常反常

安排事情让工会的存在有所不同,

但正式保证有工会会员资格(寻找...

union label")作为前提条件。


然而,OP并不需要这个保证,因为有另外一个填充了b / b
不需要工会化的账单:指向结构的
指针可以转换为指向其第一个

元素(并且返回)的指针而不会丢失或损坏。因此,如果他开始使用

a`struct SomeObjectType *''并将其转换为'void *'来进行

函数调用,他可以再次转换为`int *''在开头访问

'signature''元素。

... provided the two structs are members of the same union.
A compiler would need to be awfully smart and awfully perverse
to arrange things so the presence of the union made any difference,
but the formal guarantee has union membership ("Look for ... the
union label") as a precondition.

However, the O.P. doesn''t need this guarantee because there''s
another that fills the bill without requiring unionization: A
pointer to a struct can be converted to a pointer to its first
element (and back) without loss or damage. So if he begins with
a `struct SomeObjectType*'' and converts it to a `void*'' for the
function call, he can in turn convert again to an `int*'' to access
the `signature'' element at the beginning.


你可能会考虑定义结构更准确地匹配

您的实际使用情况:


struct OverloadedType {

enum {ST1,ST2} subtype; / *以下数据的子类型* /

union {

struct ST1 {

/ * T1子类型成员* /

} st1;

struct ST2 {

/ * T2子类型成员* /

} st2;

} u;

} * ot;

...

开关(ot-subtype){

case ST1:

do_something_to_ST1(& ot-> u.st1);

休息;

案例ST2:

do_something_to_ST2(& ot-> u.st2);

休息;

}
You might consider, though, defining the struct to more accurately match
you actual usage:

struct OverloadedType {
enum {ST1, ST2} subtype; /* subtype of following data */
union {
struct ST1 {
/* T1 subtype members */
} st1;
struct ST2 {
/* T2 subtype members */
} st2;
} u;
} *ot;
...
switch (ot-subtype) {
case ST1:
do_something_to_ST1 (&ot->u.st1);
break;
case ST2:
do_something_to_ST2 (&ot->u.st2);
break;
}



这是更干净,但它要求所有重载

类型在声明`struct OverloadedType''

时已知。另外,如果`struct ST1''和

`struct ST2''的大小差异很大,可能会浪费。使用签名 - int,enum,甚至是一个小结构 - 启动每种类型

可能更方便,更具可扩展性。


一种重要的签名是指向结构的指针

或包含函数指针的其他数据结构。取而代之的是上面显示的选择和实现逻辑的
,然后可以执行


obj-> methods-> someMethod(obj,42) ;

或者

obj-> typeData.methods [SOME_METHOD](obj,42);


一个警告:虽然这种模式可以提升可扩展性,但它使得代码的静态分析变得更加困难和/或更加有效。$ / b

-

Eric Sosman
es ***** @ acm-dot -org.inva


" Eric Sosman" < es ***** @ acm-dot-org.invalidwrote in message

新闻:GY ********************* *********@comcast.com。 ..
"Eric Sosman" <es*****@acm-dot-org.invalidwrote in message
news:GY******************************@comcast.com. ..

一种重要的签名是指向结构的指针

或包含函数指针的其他数据结构。取而代之的是上面显示的选择和实现逻辑的
,然后可以执行


obj-> methods-> someMethod(obj,42) ;

或者

obj-> typeData.methods [SOME_METHOD](obj,42);
An important kind of "signature" is a pointer to a struct
or other data structure containing function pointers. Instead
of the select-and-implement logic shown above, one can then do

obj->methods->someMethod(obj, 42);
or maybe
obj->typeData.methods[SOME_METHOD](obj, 42);



如果所有

多态类型的方法相同(并且顺序相同),那么为什么不这样做:


obj-> someMethod(obj,42);


这与C中的虚拟函数差不多。

这种策略当然不可能实现多重继承,但

这可能是一件好事。


虽然我会承认自己曾经使用过这样的hackery,如果我在几个地方有这种东西需要真正的b
我会使用C ++

而不是。只是因为有可能并不意味着它是一个很好的想法。


S


-

Stephen Sprunk上帝不玩骰子。 --Albert Einstein

CCIE#3723上帝是一个顽固的赌徒,他会在每一个可能的机会投掷
K5SSS骰子。 --Stephen Hawking

-

通过 http://www.teranews.com

If the methods are the same (and in the same order) for all of the
polymorphic types, then why not do:

obj->someMethod(obj, 42);

This is about as close as one can get to virtual functions in C.
Multiple inheritance is, of course, impossible with this strategy, but
that''s probably a good thing.

Though I''ll admit to having used such hackery myself, if I had a real
need for this sort of thing in more than a couple places I''d use C++
instead. Just because something is possible doesn''t mean it''s a good
idea.

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking
--
Posted via a free Usenet account from http://www.teranews.com


这篇关于在C中进行类型转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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