指向“基础”的指针类型 - 标准对此有何评价? [英] Pointer to "base" type - what does the Standard say about this?

查看:41
本文介绍了指向“基础”的指针类型 - 标准对此有何评价?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好!


在我提出问题之前,我想澄清我的问题不是关于我将要展示的代码的b $ b,但是关于C标准应该说什么应该发生的事情。


大概一周前我发现一个人可以实现一个非常基本的

的子类化形式(大师们当然已经知道了这一点,但

这对我来说是新闻)。我所做的(如下所示)似乎可以很好地完成所有的工作,并且完全按照我的预期进行,但我要问的是

因为当我在gcc上切换到更高的优化级别时我开始收到关于违反严格

模式的类型惩罚指针的警告。这让我感到疑惑,它是否意味着严格的C模式。或严格

GCC模式?我不太关心后者,只要我与前者遵守
。为了清楚(再次),我的问题不是GCC特定的。

我的问题是我在这里采取的方法是否合法

根据The标准。我只是问,因为GCC建议(在一些

优化级别,无论如何)我可能违反某些C规则

而不知道我这样做。


代码(遗憾的是长度 - 它与我可以做的一样短......

这个例子在C中仍保持可读性):


// -------------------开始代码

#include< stdio.h>

#include< stdlib.h>


struct base_type; // unfortunate fwd decl

// base_type对象的公共API:

struct base_public_api

{

void( * func1)(struct base_type const * self);

long(* func2)(struct base_type const * self,int);

};

typedef struct base_public_api base_public_api;


//基本类型的抽象接口

struct base_type

{

base_public_api api;

};

typedef struct base_type base_type;


// base_type abstract的实现界面

struct sub_type

{

base_public_api api;

int member1;

};

typedef struct sub_type sub_type;


#define MARKER if(1)printf(" MARKER:%s:%d:%s() :

\ n",__ FILE __,__ LINE __,__ func__);如果(1)printf


#define SUBP((sub_type const *)self)

void impl_f1(base_type const * self)

{

MARKER(" SUBP-> member1 =%d \ n",SUBP-> member1);

}

long impl_f2(base_type const * self,int x)

{

返回SUBP-> member1 * x;

}


//现在这里是可疑的部分:请注意这里的具体类型:

static const sub_type sub_type_inst = {{impl_f1,impl_f2},42 };

static base_type const * sub_inst =(base_type const *)& sub_type_inst;

// ^^^^"警告:解除引用类型惩罚指针将中断严格 -

别名规则"


int main(int argc,char const ** argv)

{


sub_inst-> api.func1(sub_inst);

MARKER(" func2()==%ld \ n",sub_inst-> api.func2 (sub_inst,2));

返回0;

}

// ------------- ------结束代码


在我的盒子上看起来像:

stephan @jareth:〜/ tmp $ ls -la inher.c

-rw-r - r-- 1 stephan stephan 1184 2008-11-05 14:43 inherc

stephan @jareth:〜/ tmp $ make inher

cc inher.c -o inher

stephan @jareth:〜/ tmp $ ./inher

MARKER:inher.c:34:impl_f1():

SUBP-> member1 = 42

MARKER:inher.c:48:main():

func2()== 84

我用这种方法走向黑暗之路吗?或者是否有更好的/

更可接受的方法来模拟C中的单继承? (我是

不是很想改变模型,但我确实需要某种形式的

单独的接口/实现我正在做的事情。)


非常感谢您的见解。


PS(与问题无关,真的):有什么意义

那个?我正在一个库里工作,我真的需要抽象基础

接口(只需要一个级别的继承),这个

的方法似乎相当清楚(虽然有时候有点冗长。)

我用它来实现抽象流接口的子类,例如
,所以我的库可以处理FILE句柄和内存

缓冲区(或客户端提供的流类型,带有适当的包装)

使用相同的读/写API。


PS2:我在comp.lang.c.moderated上的dupe帖子的应用 - 我无意中将
发布到该组。

Hi, all!

Before i ask my question, i want to clarify that my question is not
about the code i will show, but about what the C Standard says should
happen.

A week or so ago it occurred to me that one can implement a very basic
form of subclassing in C (the gurus certainly already know this, but
it was news to me). What i''ve done (shown below) seems to work all
fine and well, and does exactly what i''d expect, but i''m asking about
it because when i switched to a higher optimization level on gcc i
started getting warnings about type-punned pointers violating "strict
mode." That got me wondering, does it mean "strict C mode" or "strict
GCC mode"? i don''t care much about the latter, as long as i comply
with the former. To be clear (again), my question is not GCC-specific.
My question is whether or not the approach i''ve taken here is legal
according to The Standard. i only ask because GCC suggests (at some
optimization levels, anyway) that i might be violating some C rule
without knowing i''m doing so.

The code (sorry for the length - it''s about as short as i can make
this example in C while still keeping it readable):

// ------------------- begin code
#include <stdio.h>
#include <stdlib.h>

struct base_type; // unfortunate fwd decl
// Public API for base_type objects:
struct base_public_api
{
void (*func1)( struct base_type const * self );
long (*func2)( struct base_type const * self, int );
};
typedef struct base_public_api base_public_api;

// Base-most type of the abstract interface
struct base_type
{
base_public_api api;
};
typedef struct base_type base_type;

// Implementation of base_type abstract interface
struct sub_type
{
base_public_api api;
int member1;
};
typedef struct sub_type sub_type;

#define MARKER if(1) printf("MARKER: %s:%d:%s():
\n",__FILE__,__LINE__,__func__); if(1) printf

#define SUBP ((sub_type const *)self)
void impl_f1( base_type const * self )
{
MARKER("SUBP->member1=%d\n",SUBP->member1);
}
long impl_f2( base_type const * self, int x )
{
return SUBP->member1 * x;
}

// Now here''s the part which is dubious: note the concrete types here:
static const sub_type sub_type_inst = { {impl_f1,impl_f2}, 42 };
static base_type const * sub_inst = (base_type const*) &sub_type_inst;
// ^^^^ "warning: dereferencing type-punned pointer will break strict-
aliasing rules"

int main( int argc, char const ** argv )
{

sub_inst->api.func1(sub_inst);
MARKER("func2()==%ld\n", sub_inst->api.func2(sub_inst, 2) );
return 0;
}
// ------------------- end code

On my box that looks like:
stephan@jareth:~/tmp$ ls -la inher.c
-rw-r--r-- 1 stephan stephan 1184 2008-11-05 14:43 inher.c
stephan@jareth:~/tmp$ make inher
cc inher.c -o inher
stephan@jareth:~/tmp$ ./inher
MARKER: inher.c:34:impl_f1():
SUBP->member1=42
MARKER: inher.c:48:main():
func2()==84
Am i headed down a Dark Path with this approach? Or is there a better/
more acceptable approach to simulating single inheritance in C? (i''m
not abject to changing the model, but i really do need some form of
separate interface/implementation for what i''m doing.)

Many thanks in advance for your insights.

PS (not relevant to the question, really): what''s the point of all
that? i''m working on a library where i really need abstract base
interfaces (with only one level of inheritance necessary), and this
approach seems to be fairly clear (though a tad bit verbose at times).
i''ve used it to implement subclasses of an abstract stream interface,
for example, so my library can treat FILE handles and in-memory
buffers (or client-supplied stream types, with an appropriate wrapper)
with the same read/write API.

PS2: my appologies for the dupe post on comp.lang.c.moderated - i
inadvertently posted to that group.

推荐答案

ls -la inher.c

-rw-r - r-- 1 stephan stephan 1184 2008-11-05 14:43 inher.c

stephan @jareth:〜/ tmp
ls -la inher.c
-rw-r--r-- 1 stephan stephan 1184 2008-11-05 14:43 inher.c
stephan@jareth:~/tmp


make inher

cc inher.c -o inher

stephan @jareth: 〜/ tmp
make inher
cc inher.c -o inher
stephan@jareth:~/tmp


./ inher

MARKER:inher.c:34:impl_f1():

SUBP-> member1 = 42

MARKER:inher.c:48:main():

func2()== 84

我用这种方法走向黑暗之路吗?或者是否有更好的/

更可接受的方法来模拟C中的单继承? (我是

不是很想改变模型,但我确实需要某种形式的

单独的接口/实现我正在做的事情。)


非常感谢您的见解。


PS(与问题无关,真的):有什么意义

那个?我正在一个库里工作,我真的需要抽象基础

接口(只需要一个级别的继承),这个

的方法似乎相当清楚(虽然有时候有点冗长。)

我用它来实现抽象流接口的子类,例如
,所以我的库可以处理FILE句柄和内存

缓冲区(或客户端提供的流类型,带有适当的包装)

使用相同的读/写API。


PS2:我在comp.lang.c.moderated上的dupe帖子的应用 - 我无意中将
发布到该组。
./inher
MARKER: inher.c:34:impl_f1():
SUBP->member1=42
MARKER: inher.c:48:main():
func2()==84
Am i headed down a Dark Path with this approach? Or is there a better/
more acceptable approach to simulating single inheritance in C? (i''m
not abject to changing the model, but i really do need some form of
separate interface/implementation for what i''m doing.)

Many thanks in advance for your insights.

PS (not relevant to the question, really): what''s the point of all
that? i''m working on a library where i really need abstract base
interfaces (with only one level of inheritance necessary), and this
approach seems to be fairly clear (though a tad bit verbose at times).
i''ve used it to implement subclasses of an abstract stream interface,
for example, so my library can treat FILE handles and in-memory
buffers (or client-supplied stream types, with an appropriate wrapper)
with the same read/write API.

PS2: my appologies for the dupe post on comp.lang.c.moderated - i
inadvertently posted to that group.


这篇关于指向“基础”的指针类型 - 标准对此有何评价?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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