搜索
bottom↓
楼主: Gorgon_Meducer

[2017-5-20 更新][交流][微知识]模块的封装(一):C语言类.....

  [复制链接]

出0入296汤圆

 楼主| 发表于 2013-3-20 18:15:30 | 显示全部楼层
charlieholy 发表于 2013-3-20 16:51
怎么就能起到保护作用呢  举个试图改写里面内容的例子呗

不是read only这种物理保护,而是逻辑上的一种警告性质的约束。防君子不防小人。

出0入0汤圆

发表于 2013-3-22 17:14:06 | 显示全部楼层
顶一个~~

出0入0汤圆

发表于 2013-3-22 21:08:22 | 显示全部楼层
学习了······

出0入0汤圆

发表于 2013-3-23 01:15:28 来自手机 | 显示全部楼层
好强啊!谢谢了!!!!!

出0入0汤圆

发表于 2013-4-7 20:22:57 | 显示全部楼层
多谢楼主分享

出0入0汤圆

发表于 2013-4-9 09:45:52 | 显示全部楼层

出0入296汤圆

 楼主| 发表于 2013-5-10 20:16:34 | 显示全部楼层

2013-5-10 Update

    更新宏定义,解决了不同平台下CPU访问掩码结构体时可能存在的数组未对其到内核宽度的问题。
所谓对齐到内核宽度是指,当用掩码结构体的类型声明静态变量时,8位机要对齐到Byte,16位机要
对齐到Half-Word,32位机要对齐到Word。
   该更新可以直接解决MSP430在IAR环境下无法正常使用掩码结构体的问题。关于essf_atom_t的
说明,请参照另外一个帖子

出0入0汤圆

发表于 2013-5-10 20:43:09 | 显示全部楼层
好深的坑~
不过我猜LZ和我一样不喜欢每个C文件下面都挂一大串H文件~
最近把手头的工程完整重构成了垂直模块的结构,不相干的模块就千万不要有关系~
(也写的很苦逼啊,为了做封装写了N多接口函数,为了减少接口数量就想办法提高一组操作的耦合度,耦合度高了,又把系统写的太死了,配置起来不方便,又增加接口~~~

出0入0汤圆

发表于 2013-5-16 22:06:55 | 显示全部楼层
mark  不错。

出0入0汤圆

发表于 2013-5-16 22:42:08 | 显示全部楼层
受教了!

出0入0汤圆

发表于 2013-5-17 11:22:46 | 显示全部楼层
C语言封装成类,通常还和COM编程模型紧密联系在一起。我曾用过并已经成为编码习惯的就是高通的brew接口模型。网上可以下载到brew SDK。Brew PK不开放,网上似乎只能下到2.1的PK,不知是从哪流出来的。PK比SDK包含的源代码更细一些。里边可以看到部分COM接口模型的宏定义。写的非常漂亮,封装、继承都设计的的非常好。另外一个用过的C封装成类的应用实例就是strongswan,也就是目前仅有的支持IKE V2的ipsec解决方案,里边的各种模块都是用C封装成类的形式提供接口,供外面调用,也很漂亮。顺便说一下strongswan的线程调度器,思路非常N B,是真正的把线程当成处理分片任务的东西来做的,而不是通常情况下,人们习惯的一个线程做一件事那种思路来做的。

出0入0汤圆

发表于 2013-5-18 00:05:28 | 显示全部楼层
厉害!      

出0入0汤圆

发表于 2013-5-20 10:28:26 | 显示全部楼层
受教了!

出0入0汤圆

发表于 2013-5-20 16:34:02 | 显示全部楼层

出0入0汤圆

发表于 2013-5-29 22:45:19 | 显示全部楼层
谢谢,学习了

出0入0汤圆

发表于 2013-6-17 13:45:49 | 显示全部楼层
学习 ~~~~~~~~~

出0入296汤圆

 楼主| 发表于 2013-6-25 19:02:32 | 显示全部楼层
2013-6-25 更新
    更新了掩码结构体的宏,使其能够支持在类中使用指向自己的指针,同时也能插入 delegate 类型
(事件处理函数原型)的声明。统一了格式。

出0入0汤圆

发表于 2013-6-25 20:58:05 | 显示全部楼层
Mark!! OOC

出0入0汤圆

发表于 2013-6-25 21:54:06 来自手机 | 显示全部楼层
记号,回家学习

出0入0汤圆

发表于 2013-6-25 23:14:34 | 显示全部楼层



         

出0入0汤圆

发表于 2013-6-25 23:48:30 | 显示全部楼层
不是太懂,但是我很欣赏你的代码风格。呵呵

出0入0汤圆

发表于 2013-6-26 16:37:07 | 显示全部楼层
  学习了

出0入0汤圆

发表于 2013-7-19 13:26:42 | 显示全部楼层
谢谢楼主分享您的知识和经验,
楼主还有更新吗,这个系列就写了两篇,还是说楼主写到你的书里的?

出0入296汤圆

 楼主| 发表于 2013-7-20 10:58:41 | 显示全部楼层
leoyang 发表于 2013-7-19 13:26
谢谢楼主分享您的知识和经验,
楼主还有更新吗,这个系列就写了两篇,还是说楼主写到你的书里的? ...

大部分内容在书里面。但是我会根据情况,提取一些内容继续更新这个系列。

出0入0汤圆

发表于 2013-7-27 17:42:23 | 显示全部楼层
Gorgon_Meducer 发表于 2013-7-20 10:58
大部分内容在书里面。但是我会根据情况,提取一些内容继续更新这个系列。 ...

谢谢,出书了吼一声,买几本来自己学习,送同事很好。

出0入14汤圆

发表于 2013-7-29 09:15:41 | 显示全部楼层
Etual 发表于 2012-11-15 09:32
代码顶楼傻孩子已有,我这里只是为了帮助理解做了必要的解释

(一)首先基础知识

#define EXTERN_CLASS(__NAME,...) \

    typedef union __NAME __NAME;\

    __VA_ARGS__\

    union __NAME {\

        uint_fast8_t chMask[(sizeof(struct {



#define END_EXTERN_CLASS(__NAME) \

        }) + sizeof(uint_fast8_t) - 1) / sizeof(uint_fast8_t)];\

    };

这个宏,不是很明白怎么变换成
typedef struct {                                    //这个struct在宏中也没有表现出来
    uint8_t chMask[sizeof(struct {
    uint8_t *pchBuffer;    //!< queue buffer   
    uint16_t hwBufferSize; //!< buffer size
    uint16_t hwHead;       //!< head pointer
    uint16_t hwTail;       //!< tail pointer
    uint16_t hwCounter;    //!< byte counter
    })];
}queue_t;

出0入0汤圆

发表于 2013-8-6 19:05:58 | 显示全部楼层
顶完在看!

出0入296汤圆

 楼主| 发表于 2013-8-6 23:59:03 | 显示全部楼层
Pjm2008 发表于 2013-7-29 09:15
#define EXTERN_CLASS(__NAME,...) \

    typedef union __NAME __NAME;\

已经用union了

出0入0汤圆

发表于 2013-8-13 23:00:45 来自手机 | 显示全部楼层
mark……
顶一个…

出0入0汤圆

发表于 2013-8-15 21:43:11 | 显示全部楼层
和高焕堂大师的OOPC类似啊,呵呵。经典。

出0入0汤圆

发表于 2013-11-14 09:47:36 | 显示全部楼层
学习啦  

出0入0汤圆

发表于 2013-11-16 20:57:19 | 显示全部楼层
受教,mark

出0入0汤圆

发表于 2013-12-17 11:50:33 | 显示全部楼层
mark                          

出0入0汤圆

发表于 2013-12-17 12:05:34 | 显示全部楼层

受教了!   

出0入0汤圆

发表于 2013-12-17 13:02:22 | 显示全部楼层
好贴,学习了

出0入0汤圆

发表于 2013-12-17 13:37:03 | 显示全部楼层
不明觉厉

出0入0汤圆

发表于 2014-2-22 10:38:14 | 显示全部楼层
mark!!!

出0入0汤圆

发表于 2014-2-22 16:34:05 | 显示全部楼层
我土得掉渣了

出0入0汤圆

发表于 2014-2-24 20:28:39 | 显示全部楼层
楼主好帖,受教了

出870入263汤圆

发表于 2014-2-24 22:16:50 | 显示全部楼层
takashiki 发表于 2012-12-5 10:58
如果需要使用对应类型的大小信息,那就域中弄上一大堆的Reserved。
比如Windows API中,关于串行通信的部 ...

按照你说的,通过一个函数获得对象的大小字节数,是不能将对象定义堆栈内存和全局内存的,而只能通过malloc来分配了。

出870入263汤圆

发表于 2014-2-24 22:27:11 | 显示全部楼层
ifree64 发表于 2012-12-9 17:14
这种所谓封装严格来说和直接定义差不多。

头文件中定义

首先,你说的没错!然后是:楼主的方法在于很明显的告诉使用者,不要尝试直接改变结构体成员,而是应该通过公开的API;事实上,楼主的方法已经成功避免了误用的隐患,这就够了;至于“故意”要去设法访问,是没有任何编程语言能在编译时阻止这类行为的,你想破坏数据还不容易吗?

出0入93汤圆

发表于 2014-2-25 07:25:36 | 显示全部楼层
armstrong 发表于 2014-2-24 22:16
按照你说的,通过一个函数获得对象的大小字节数,是不能将对象定义堆栈内存和全局内存的,而只能通过mall ...

你认为不可以的,实际上是可以的,只是因为你从没有这样用过。
Google一下placement new,你就知道,C++的new出来的对象可以在堆上,也可以在栈上!只是这个方法我们基本不用。
同样,按照我说的,通过一个函数获得对象的大小字节数,是完全将对象定义堆栈内存和全局内存的。

事实上,我个人喜欢原生的东西,反感各种模拟的东西,四不像。要玩封装,直接用C++就好了,比C强多了,也不需要每个函数都弄成虚函数来折腾。

出0入0汤圆

发表于 2014-3-26 17:14:18 | 显示全部楼层
马克            

出0入296汤圆

 楼主| 发表于 2014-3-27 00:34:58 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2014-3-27 00:41 编辑
takashiki 发表于 2014-2-25 07:25
你认为不可以的,实际上是可以的,只是因为你从没有这样用过。
Google一下placement new,你就知道,C++ ...


OOPC不象任何人,因为它就是自己。你只是不承认他而已。这是每个人的
认知不同而已。其实不必每个函数都做成虚函数,可以这么做,但不是必须
这么做。OOPC是实用主义,需要的时候才会引入必要的特性,而不会为了
形式而形式。我和你一样反感形式上的模仿。我是实用主义。我们一直在说
C,讨论也是基于ANSIC99,拿C++的特性来解释问题有点欺负人的感觉。
C++本来就比C功能强大。

只要有大小信息,的确可以在栈上先用数组申请到所需的大小,然后用指针
实现强制类型转换,从而实现了对象的栈分配,但就像你说的,不自然,不
是原生态的。如果类型本身就包含了正确的大小信息,则直接用该类型申请
局部变量就可以了。至于堆,没什么好说的。c的堆就是人造的,分配也是
手工的。

出0入0汤圆

发表于 2014-5-27 17:07:01 | 显示全部楼层
学习,学习

出0入0汤圆

发表于 2014-5-27 17:26:36 | 显示全部楼层
厉害  厉害~~ 学些学些

出0入0汤圆

发表于 2014-7-22 17:47:16 | 显示全部楼层
takashiki 发表于 2012-12-4 13:42
不对,隐藏完全是可能的,声明和定义不一致就可以了。面向对象是思想,实现的方式可以多种多样,继承、派生 ...

看的有的疑问,查了下 结构的定义,附在这里: C 和 C++ 里面是不同的。
1. C
定义结构变量的一般格式为:
struct 结构名
{
类型 变量名;
类型 变量名;
...
} 结构变量;
结构名是结构的标识符不是变量名。

另一种常用格式为:
typedef struct 结构名
{
类型 变量名;
类型 变量名;
...
} 结构别名;
这里queue_t  是结构别名。
queue_t *create_queue();
void destroty_queue(queue_t *q);

2.C++
在c++中如果用typedef的话,又会造成区别:
struct Student
{
int a;
}stu1;//stu1是一个变量
typedef struct Student2
{
int a;
}stu2;//stu2是一个结构体类型
使用时可以直接访问stu1.a
但是stu2则必须先 stu2 s2;
然后 s2.a=10;

出0入93汤圆

发表于 2014-7-22 18:15:06 | 显示全部楼层
ppdd 发表于 2014-7-22 17:47
看的有的疑问,查了下 结构的定义,附在这里: C 和 C++ 里面是不同的。
1. C
定义结构变量的一般格式为: ...

C和C++的struct是有区别,但不是你说的什么区别。

在C中,struct只是数据的封装,并且所有数据都是可访问的(public)。
在C++中,struct是数据和方法的封装,并且数据可以隐藏。事实上,struct就是class,只是class默认访问级别为private,struct为public。

在C中,我为什么喜欢写typedef呢,是因为结构体/联合体/枚举定义变量时,前面的struct/union/enum关键字不能省略。像我这么懒的人,多打这么多字会伤多少细胞啊,所以用typedef。但是C++就不同了,C++的struct/union/enum关键字是可以省略的,而且是建议省略,不省略都觉得不好意思跟别人打招呼。

出0入0汤圆

发表于 2014-7-22 18:18:52 | 显示全部楼层
Mark+++++++

出0入0汤圆

发表于 2014-7-22 22:44:05 | 显示全部楼层
takashiki 发表于 2014-7-22 18:15
C和C++的struct是有区别,但不是你说的什么区别。

在C中,struct只是数据的封装,并且所有数据都是可访 ...

谢谢! 还没有理解到这么深入!

出0入0汤圆

发表于 2014-8-14 19:58:12 | 显示全部楼层
顶顶!!!!!!!!!!!!!!!

出0入0汤圆

发表于 2014-8-14 19:58:27 | 显示全部楼层
顶顶!!!!!!!!!!!!!!!

出0入0汤圆

发表于 2014-8-18 16:37:41 | 显示全部楼层
mark一下,C语言类封装

出0入0汤圆

发表于 2014-9-10 12:24:28 | 显示全部楼层
Mark,学习了

出0入0汤圆

发表于 2014-10-30 16:47:09 | 显示全部楼层
感谢分享,mark记录一下

出0入0汤圆

发表于 2014-10-30 17:04:04 | 显示全部楼层
学习了!

出0入0汤圆

发表于 2014-10-31 08:29:05 | 显示全部楼层
takashiki 发表于 2014-7-22 18:15
C和C++的struct是有区别,但不是你说的什么区别。

在C中,struct只是数据的封装,并且所有数据都是可访 ...

在C中使用typedef,可能是个不好的实践,Linus大神就反对这种写法,他认为如果没有一个真的原因就搞类型抽象是不必要的,少打字更不是个好的理由,当你编程时你的打字速度主要问题时,你绝对做错了什么。(I dislike type abstraction if it has no real reason. And saving on typing is not a good reason - if your typing speed is the main issue when you're coding, you're doing something seriously wrong.)

并且,绝对不要搞指针类型的typedef, 写出 typedef struct urb_struct * urbp_t: (或其他别的名字)的人都该被枪毙 ( ,他很高兴在内核USB驱动里看到这些垃圾被切除。( And never _ever_ make the "pointerness" part of the type. People who write

        typedef struct urb_struct * urbp_t;

(or whatever the name was) should just be shot. I was _soo_ happy to see that crap get excised from the kernel USB drivers.

Linus大神还是蛮酷的啊。

http://yarchive.net/comp/linux/typedefs.html

Linus的全文:

Index Home About Blog
Newsgroups: fa.linux.kernel
From: Linus Torvalds <torvalds@transmeta.com>
Subject: Re: [PATCH] 2.5.21 - list.h cleanup
Original-Message-ID: <Pine.LNX.4.44.0206100954250.30535-100000@home.transmeta.com>
Date: Mon, 10 Jun 2002 17:03:50 GMT
Message-ID: <fa.l4d7opv.1mhk21p@ifi.uio.no>

On Mon, 10 Jun 2002, Thomas 'Dent' Mirlacher wrote:
>
> ok, the point that *_t is hiding implementation details (when used for
> structs is valid). but is there a general consens on not using typedefs
> for structs?

The linux coding style _tends_ to avoid using typedefs. It's not a hard
rule (and I did in fact apply this patch, since it otherwise looked fine),
but it's fairly common to use an explicit "struct xxxx" instead of
"xxxx_t".

I dislike type abstraction if it has no real reason. And saving on typing
is not a good reason - if your typing speed is the main issue when you're
coding, you're doing something seriously wrong.

(Similarly, if you are trying to compress lines to be shorter, you have
other problems, nothing to do with type names).

Does code look "prettier" with a "_t" rather than a "struct "? I don't
know. I personally don't think so, and I also hate the "_p" (or even more
the just plain "p") convention for "pointer".

Hiding the fact that it's a struct causes bad things if people don't
realize it: allocating structs on the stack is something you should be
aware of (and careful with), and passing them as parameters is is much
better done explicitly as a "pointer to struct".

There are _some_ exceptions. For example, "pte_t" etc might well be a
struct on most architectures, and that's ok: it's expressly designed to be
an opaque (and still fairly small) thing. This is an example of where
there are clear _reasons_ for the abstraction, not just abstraction for
its own sake.

But in the end, maintainership matters. I personally don't want the
typedef culture to get the upper hand, but I don't mind a few of them, and
people who maintain their own code usually get the last word.

                Linus


Newsgroups: fa.linux.kernel
From: Linus Torvalds <torvalds@transmeta.com>
Subject: Re: [PATCH] 2.5.21 - list.h cleanup
Original-Message-ID: <Pine.LNX.4.44.0206101011440.30535-100000@home.transmeta.com>
Date: Mon, 10 Jun 2002 17:22:34 GMT
Message-ID: <fa.l5sjnpv.1l1431s@ifi.uio.no>

On Mon, 10 Jun 2002, Thomas 'Dent' Mirlacher wrote:
>
> On Mon, 10 Jun 2002, Linus Torvalds wrote:
>
> --snip/snip
> > But in the end, maintainership matters. I personally don't want the
> > typedef culture to get the upper hand, but I don't mind a few of them, and
> > people who maintain their own code usually get the last word.
>
> to sum it up:
>
> using the "struct mystruct" is _recommended_, but not a must.

Well, it's more than just "struct xx". It's really typedefs in general.

For example, some people like to do things like

        typedef unsigned int counter_t;

and then use "counter_t" all over the place. I think that's not just ugly,
but stupid and counter-productive. It makes it much harder to do things
like "printk()" portably, for example ("should I use %u, %l or just %d?"),
and generally adds no value. It only _hides_ information, like whether the
type is signed or not.

There is nothing wrong with just using something like "unsigned long"
directly, even if it is a few characters longer than you might like. And
if you care about the number of bits, use "u32" or something. Don't make
up useless types that have no added advantage.

We actually have real _problems_ due to this in the kernel, where people
use "off_t", and it's not easily printk'able across different
architectures (we used to have this same problem with size_t). We should
have just used "unsigned long" inside the kernel, and be done with it (and
"unsigned long long" for loff_t).

We should also have some format for printing out "u32/u64" etc, but that's
another issue and has the problem that gcc won't understand them, so
adding new formats is _hard_ from a maintenance standpoint.

                        Linus

PS. And never _ever_ make the "pointerness" part of the type. People who
write

        typedef struct urb_struct * urbp_t;

(or whatever the name was) should just be shot. I was _soo_ happy to see
that crap get excised from the kernel USB drivers.


Newsgroups: fa.linux.kernel
From: Linus Torvalds <torvalds@transmeta.com>
Subject: Re: [patch] Workqueue Abstraction, 2.5.40-H7
Original-Message-ID: <Pine.LNX.4.33.0210011210030.1878-100000@penguin.transmeta.com>
Date: Tue, 1 Oct 2002 19:15:17 GMT
Message-ID: <fa.o99pduv.hkq436@ifi.uio.no>

On Tue, 1 Oct 2002, Ingo Molnar wrote:
>
> the attached (compressed) patch is the next iteration of the workqueue
> abstraction. There are two major categories of changes:

Please don't introduce more typedefs. They only hide what the hell the
thing is, which is actively _bad_ for structures, since passing a
structure by value etc is something that should never be done, for
example.

The few saved characters of typing do not actually _buy_ you anything
else, and only obscures what the thing is.

Also, it's against the Linux coding standard, which does not like adding
magic single-letter suffixes to things - that also is the case for your
strange "_s" suffix for a structure (the real suffix is "_struct").

Remember: typing out something is not bad. It's _especially_ not bad if
the typing makes it more clear what the thing is.

I've done a global search-and-replace on the patch. The resulting patch is
actually _cleaner_, because it also matches more closely the old code
(which used "struct tq_struct"), so things like tabbed comment alignment
etc tend to be more correct (not always, but closer).

                Linus


Newsgroups: fa.linux.kernel
From: torvalds@transmeta.com (Linus Torvalds)
Subject: Re: [patch] Workqueue Abstraction, 2.5.40-H7
Original-Message-ID: <ancug3$iq1$1@penguin.transmeta.com>
Date: Tue, 1 Oct 2002 19:52:30 GMT
Message-ID: <fa.k1e80bv.530685@ifi.uio.no>

In article <Pine.LNX.4.33.0210011210030.1878-100000@penguin.transmeta.com>,
Linus Torvalds  <torvalds@transmeta.com> wrote:
>
>Pease don't introduce more typedefs. They only hide what the hell the
>thing is, which is actively _bad_ for structures, since passing a
>structure by value etc is something that should never be done, for
>example.

Btw, just to avoid counter-examples: Linux does use structures and
typedefs occasionally to hide and force compiler typechecking on small
structures on purpose. We have a few places where we do things like

        typedef struct {
                unsigned int value;
        } atomic_t;

(and similar things for the page table entries etc).

This is done because the things are often really regular scalars, but we
use the structure as a strict type checking mechanism. In this case,
using a typedef is fine, because we don't actually ever want to _access_
it as a structure, and the typedef provices exactly the kind of
information hiding that we need.

But type hiding for a real structure just doesn't make sense, since we
use it as a true structure, and hiding information just makes it harder
to see.

                        Linus

Newsgroups: fa.linux.kernel
From: Linus Torvalds <torvalds@transmeta.com>
Subject: Re: [patch] Workqueue Abstraction, 2.5.40-H7
Original-Message-ID: <Pine.LNX.4.33.0210011345260.1372-100000@penguin.transmeta.com>
Date: Tue, 1 Oct 2002 20:49:18 GMT
Message-ID: <fa.oa9nemv.gk45b9@ifi.uio.no>

On Tue, 1 Oct 2002, Ingo Molnar wrote:
>
> Despite all the previous fuss about the problems of typedefs, i've never
> had *any* problem with using typedefs in various code i wrote.

Big things should have big names. That's why "u8" is u8, because it's not
just physically small, it also has very little semantics associated with
it.

I want those variable declarations to stand out, and make people
understand that this is not just a variable, it's a structure, and it may
be taking up a noticeable amount of space on the stack, for example.

That's the main issue for me. I don't personally care so much about trying
to avoid dependencies in the header files that can also be problematic.
That's probably partly because I use fast enough machines that parsing
them a few extra times doesn't much bother me, and circular requirements
tend to be rare enough not to bother me unduly.

So the thing is a big red warning sign that you're now using a complex
data structure, and you should be aware of the semantics that go with it.

                        Linus


From: Linus Torvalds <torvalds@osdl.org>
Newsgroups: fa.linux.kernel
Subject: Re: [RFC][PATCH 1/5] Virtualization/containers: startup
Date: Fri, 03 Feb 2006 17:16:47 UTC
Message-ID: <fa.4bkWs6R4XPzyMAJare3mNZgSBgI@ifi.uio.no>
Original-Message-ID: <Pine.LNX.4.64.0602030905380.4630@g5.osdl.org>

On Fri, 3 Feb 2006, Kirill Korotaev wrote:
>
> This patch introduces some abstract container/VPS kernel structure and tiny
> amount of operations on it.

Please don't use things like "vps_t".

It's a _mistake_ to use typedef for structures and pointers. When you see
a

        vps_t a;

in the source, what does it mean?

In contrast, if it says

        struct virtual_container *a;

you can actually tell what "a" is.

Lots of people think that typedefs "help readability". Not so. They are
useful only for

(a) totally opaque objects (where the typedef is actively used to _hide_
     what the object is).

     Example: "pte_t" etc opaque objects that you can only access using
     the proper accessor functions.

     NOTE! Opaqueness and "accessor functions" are not good in themselves.
     The reason we have them for things like pte_t etc is that there
     really is absolutely _zero_ portably accessible information there.

(b) Clear integer types, where the abstraction _helps_ avoid confusion
     whether it is "int" or "long".

     u8/u16/u32 are perfectly fine typedefs.

     NOTE! Again - there needs to be a _reason_ for this. If something is
     "unsigned long", then there's no reason to do

        typedef long myflags_t;

     but if there is a clear reason for why it under certain circumstances
     might be an "unsigned int" and under other configurations might be
     "unsigned long", then by all means go ahead and use a typedef.

(c) when you use sparse to literally create a _new_ type for
     type-checking.

Maybe there are other cases too, but the rule should basically be to NEVER
EVER use a typedef unless you can clearly match one of those rules.

In general, a pointer, or a struct that has elements that can reasonably
be directly accessed should _never_ be a typedef.

                Linus

From: Linus Torvalds <torvalds@osdl.org>
Newsgroups: fa.linux.kernel
Subject: Re: Slab: Remove kmem_cache_t
Date: Wed, 29 Nov 2006 16:12:48 UTC
Message-ID: <fa.QqBcP76GmvQ7hKoj8Em059Dwf50@ifi.uio.no>

On Wed, 29 Nov 2006, Nick Piggin wrote:
>
> You are saying that they should only be used to create new "primitive"
> types (ie. that you can use in arithmetic / logical ops) that can
> change depending on the config.

Well, it doesn't have to be something that is "arithmetic".

For an example of a primitive type that isn't arithmetic, the page table
entries are (pgt_t/pud_t/pmd_t/pte_t) are excellent - they don't do any
arithmetic or logical ops, but they do change depending on config, and no,
they aren't always opaque structures.

(Actually, these days they mostly are, but on many architectures it's much
slower to pass even a small struct around than it is to pass an integer
around - due simply to calling conventions - so for truly opaque things,
the typedef has the advantage that it _can_ be an opaque integer type, and
nobody will notice).

> That's fair enough. I'm sure you've also said in the past that they can
> be used (IIRC you even encouraged it) when the type is opaque in the
> context it is being used.

I'm sure I've been inconsistent, but in general, typedefs are bad. I think
you'll notice that I almost never use them myself. I much prefer passing
an opaque structure around, _unless_ I know the structure is so small that
it makes sense to do the above optimization (ie allow the case where the
opaque thing actually ends up being an integer).

Opaque integer types are generally useless in C, because they lose all the
type information _way_ too easily. There are no warnings for mis-use,
unless you use a sparse "bitwise" type and actually run sparse on the
thing. So even when there are performance reasons to use opaque integer
types (and on x86, the page table things were one such thing), usign a
struct is often preferable just for type-checking.

And as mentioned, there _are_ exceptions. Some types just get _sooo_
complex that it's inconvenient to type them out, even if they are
perfectly regular types, and don't depend on any config option. The
"filldir_t" typedef in fs.h is such an example - it's not really opaque,
_nor_ is it a config option, but it sure as hell would be inconvenient for
all low-level filesystems to do

        int my_readdir(struct file *filp, void *dirent,
                int (*filldir)(void *, const char *, int, loff_t,
                u64, unsigned))
        {
                ...
        }

because let's face it, having to write out that "filldir" type just made
me use two lines (and potential for totally unnecessary tupos) because the
thing was so complex. So at that point, using a typedef is just common
sense, and we can do

        int my_readdir(struct file *filp, void *dirent, filldir_t filldir)
        {
                ...
        }

instead.

But it's really quite hard to make that kind of complex type in C. It's
almost always a function pointer that takes complex arguments.

[ That said, I generally won't _complain_ if people use typedefs, but on
  the other hand, some people definitely are too eager to do it, and I'll
  happily remove them if people send me a patch. For example, we used to
  have "task_t" for "struct task_struct", and that was just _unnecessary_,
  and made it just harder to pick out what it was. Sometimes long names
  and the explicit "struct" is a _good_ thing. ]

One final thing: for _small_ structures, typedefs are much better than for
large ones. Why? Because of stack usage. I want people to really _think_
about local variable sizes, and that's one thing that a typedef sometimes
causes - especially if it's opaque, so that users don't have any "handle"
on whether it is big or small, it's really nasty to use them for automatic
storage on the stack, because you may simply blow your stack usage on a
single (or a couple) of structures.

Making things be "struct something_or_other" makes at least _me_ think
more about it than if it's "file_t". Maybe it's just me, but I immediately
think "complex structure" when I see "struct", but "file_t" to me mentally
says "single word".

                        Linus
Index Home About Blog

出0入93汤圆

发表于 2014-10-31 09:43:55 | 显示全部楼层
end2000 发表于 2014-10-31 08:29
在C中使用typedef,可能是个不好的实践,Linus大神就反对这种写法,他认为如果没有一个真的原因就搞类型抽 ...

Linus吐槽的多了,你是不是都都学他啊?Linus吐槽C++是一坨shit,于是我们不用C++了;Linus吐槽XML是垃圾,于是我们不用XML了。整个世界清静了。
不用typedef,那你用#define,这样程序就高大上了,呵呵。
要写出健壮的程序,我还是习惯遵循MISRA C的。不知道您对
MISRA-C 鼓励使用 typedef。
这句话怎么理解?把ISO枪毙算了?

出0入0汤圆

发表于 2014-10-31 10:10:04 | 显示全部楼层
takashiki 发表于 2014-10-31 09:43
Linus吐槽的多了,你是不是都都学他啊?Linus吐槽C++是一坨shit,于是我们不用C++了;Linus吐槽XML是垃圾 ...

请联系上下文,MISRA-C 2004是在“6.10.2 隐式转换的类型”这节谈到“鼓励使用typedef” 来进行整数提升(Integral promotion)转换的。而这点是和
“规则 6.3(建议): 应该使用指示了大小和符号的 typedef以代替基本数据类型。”相连系的。
你别推广到全部了。

出0入93汤圆

发表于 2014-10-31 10:24:57 | 显示全部楼层
end2000 发表于 2014-10-31 10:10
请联系上下文,MISRA-C 2004是在“6.10.2 隐式转换的类型”这节谈到“鼓励使用typedef” 来进行整数提升 ...

请搜索一下MISRA C自己弄的typedef吧,看完了再喷,尤其看那些带“强制”字眼的:
规则 1.5(建议): 浮点应用应该适应于已定义的浮点标准
typedef float float32_t;
规则 5.6(建议): 一个命名空间中不应存在与另外一个命名空间中的标识符拼写相同的标识符,除了结构和联合中的成员名字。
typedef struct vector ( uint16_t x ; uint16_t y ; uint16_t z ; ) vector ;
规则 6.3(建议): 应该使用指示了大小和符号的 typedef 以代替基本数据类型。
BLABLABLA一大堆
规则 17.5(建议): 对象声明所包含的间接指针不得多于 2 级
typedef int8_t * INTPTR;
变量录取
/* The fields common to all CCP messages */  
typedef struct {  
        uint8_t msg_type;
        uint8_t sequence_no;  
} ccp_common_t;
规则 19.4(强制):C 的宏只能扩展为用大括号括起来的初始化、常量、小括号括起来的表达式、类型限定符、存储类标识符或的宏只能扩展为用大括号括起来的初始化、常量、小括号括起来的表达式、类型限定符、存储类标识符或 do-while-zero 结构。
#define int32_t long  /* use typedef instead */

出0入0汤圆

发表于 2014-10-31 10:33:48 | 显示全部楼层
takashiki 发表于 2014-10-31 10:24
请搜索一下MISRA C自己弄的typedef吧,看完了再喷,尤其看那些带“强制”字眼的:
...

这些typedef基本是关于类型转换的,有什么问题吗?

出0入93汤圆

发表于 2014-10-31 10:37:39 | 显示全部楼层
end2000 发表于 2014-10-31 10:33
这些typedef基本是关于类型转换的,有什么问题吗?

typedef跟类型转换有关系?对不起,你的语文水平已经达到了我无法理解的程度了,我不再回复。如果你觉得你做得对,就继续做下去。
typedef仅仅就是取个小名,图个方便而已。

出0入0汤圆

发表于 2014-10-31 11:03:21 | 显示全部楼层
我建议讨论范围限制在c的typedef上,以后有机会再讨论语文水平,Linus的吐槽能力,C++, XML好吧。

SO上这个帖子关于typedef的干货比较多,完整读完定会有所收获。供参考。

http://stackoverflow.com/questio ... -so-often-in-c?rq=1

出0入0汤圆

发表于 2014-10-31 11:11:56 | 显示全部楼层
Mark!!!!!!

出0入0汤圆

发表于 2014-12-18 14:11:25 | 显示全部楼层
好好学习,天天向上

出0入296汤圆

 楼主| 发表于 2014-12-18 15:12:30 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2014-12-18 15:15 编辑
end2000 发表于 2014-10-31 08:29
在C中使用typedef,可能是个不好的实践,Linus大神就反对这种写法,他认为如果没有一个真的原因就搞类型抽 ...


的确不要乱用typedef,尤其是不要用typedef来定义指针,这也是为什么我处理函数指针的时候要求
只用typedef定义原型,但不定义指针。typedef非常适合定义类,这也是符合Linus所说的三种情况。
至于很多用且仅用一次的场合,最好还是不要用typedef了。

另外,用typedef处理过的多维数组,函数指针都能极大的简化我们代码的编写,避免出错,让代码变得非常干净。
否则请想想一个函数指针,指向一个函数,这个函数以某个函数指针为返回值,接收某个类型的函数指针作为参数,
并接收某个类型的二维数组作为参数……

写出这样的原型,如果不用typedef……可想而知,完全不可阅读,你认为这是很极端的情况么?恰恰相反,这类
接口代码很容易出现。

出0入0汤圆

发表于 2014-12-21 13:52:06 | 显示全部楼层
“假设我们约定queue.c将不包含queue.h(这么做的好处很多...”
如果queue.c包含queue.h(平时都是这么干的),会有什么问题?
请傻孩子老师指导

出0入0汤圆

发表于 2014-12-21 15:09:29 | 显示全部楼层
同问楼上的 我也是queue.c包含queue.h

出0入296汤圆

 楼主| 发表于 2014-12-22 22:35:26 | 显示全部楼层
chenguanghua 发表于 2014-12-21 13:52
“假设我们约定queue.c将不包含queue.h(这么做的好处很多...”
如果queue.c包含queue.h(平时都是这么干的 ...

queue.h是接口头文件,用于模块从内向外提供接口——就是把别人用你这个模块所需的最小信息公开出去——
这就是最小信息公开原则。如果你.c包含.h那么你肯定要把很多信息都放在这个.h里面,那么这个.h就包含了
很多别人不需要知道的东西,不仅冗余了,而且破坏了封装。另外.c包含自己的.h造成循环包含的可能性很高。

出0入0汤圆

发表于 2014-12-23 10:23:55 | 显示全部楼层
Gorgon_Meducer 发表于 2014-12-22 22:35
queue.h是接口头文件,用于模块从内向外提供接口——就是把别人用你这个模块所需的最小信息公开出去——
...

那.c文件中要用到的宏不是定义在同名的.h文件中吗?比如说key_scan.c中用到了的 define key_1 P1.0 不应该放在key_scan.h中吗?

出0入296汤圆

 楼主| 发表于 2014-12-23 16:49:49 | 显示全部楼层
sbk100 发表于 2014-12-23 10:23
那.c文件中要用到的宏不是定义在同名的.h文件中吗?比如说key_scan.c中用到了的 define key_1 P1.0 不应 ...

.c和.h各自定义一份。通常来说.c里面定义的是最全的,.h里面的信息是最小的。二者可能根本就是不同的,
比如我的掩码结构体技术,.h和.c里面的部分完全不同。

出0入0汤圆

发表于 2015-1-30 23:42:05 | 显示全部楼层
哪位给解释下“PIC的地址空间不是扁平的,不能用掩码结构体。”?

出0入0汤圆

发表于 2015-3-4 15:06:54 | 显示全部楼层
好帖,必须收藏,仔细研究哇!

出0入4汤圆

发表于 2015-3-4 16:55:50 | 显示全部楼层
掩码结构体,M

出0入0汤圆

发表于 2015-3-5 11:23:08 | 显示全部楼层
经典!mark下。

出0入0汤圆

发表于 2015-5-20 01:14:37 | 显示全部楼层
傻孩子,图片中的语句,没看懂能解释一下吗?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入296汤圆

 楼主| 发表于 2015-5-21 21:44:14 | 显示全部楼层
cgbabc 发表于 2015-5-20 01:14
傻孩子,图片中的语句,没看懂能解释一下吗?

从字面理解,你觉得这句话是做什么的?话说掩码结构体的原理和目的你看了么?

出0入0汤圆

发表于 2015-5-21 22:39:35 | 显示全部楼层
Gorgon_Meducer 发表于 2015-5-21 21:44
从字面理解,你觉得这句话是做什么的?话说掩码结构体的原理和目的你看了么? ...

我想问的是第五行的那个,现在看明白了,是判断输入合法性的。谢谢!

出0入0汤圆

发表于 2015-5-26 10:45:06 | 显示全部楼层
mark一下,很有用啊,

出0入0汤圆

发表于 2015-9-1 09:04:15 | 显示全部楼层
学习了,谢谢

出130入0汤圆

发表于 2015-9-8 09:12:01 | 显示全部楼层
不错,mark

出0入0汤圆

发表于 2016-6-23 17:16:12 | 显示全部楼层
感谢楼主和52楼的解释

出0入0汤圆

发表于 2016-6-23 20:55:57 来自手机 | 显示全部楼层
mark。占位学习

出0入0汤圆

发表于 2017-2-27 00:10:17 | 显示全部楼层
问个小问题,ANSI C不是不支持可变参数宏吗?
另外问下大师,C99的新特性使用的多不多,因为本人开始慢慢发现时常写了一些C99才支持的东西(因为大部分编译器支持C99),然后开始担心了可移植性问题,毕竟移动性ANSI C肯定是没问题了。

出0入296汤圆

 楼主| 发表于 2017-3-1 08:42:34 | 显示全部楼层
Ray______ 发表于 2017-2-27 00:10
问个小问题,ANSI C不是不支持可变参数宏吗?
另外问下大师,C99的新特性使用的多不多,因为本人开始慢慢发 ...

C99 是ANSIC的一个版本

出0入296汤圆

 楼主| 发表于 2017-5-31 00:00:53 | 显示全部楼层

2017-5-30 Update

    更新了掩码结构体的宏,增强了对嵌套宏的支持。根据最新的宏,更新理论讲解。提供了oopc.h头文件的下载。

出0入0汤圆

发表于 2017-6-1 10:30:17 | 显示全部楼层
挖坟。。。。。

出0入0汤圆

发表于 2017-6-1 12:40:43 | 显示全部楼层
Gorgon_Meducer 发表于 2012-12-5 10:26
这种方式同样限定了外部不能使用对应类型的大小信息。

其实我现在也是和楼上的写法差不多,如果遇到需要大小的,加一个变量初始化的时候计算大小或者一个计算大小的函数指针;

出0入0汤圆

发表于 2017-6-25 21:01:04 | 显示全部楼层
声明一个class,里面有数据和处理数据的接口。和单独定义def_interface有什么区别么

出0入296汤圆

 楼主| 发表于 2017-6-29 18:33:04 | 显示全部楼层
soga238 发表于 2017-6-25 21:01
声明一个class,里面有数据和处理数据的接口。和单独定义def_interface有什么区别么 ...

class有掩码结构体保护,看不到成员,interface没有掩码结构体保护(保护了就没有意义了),所有成员都是公开的,理论上也只放函数指针。

出0入0汤圆

发表于 2017-6-30 09:48:49 | 显示全部楼层
Gorgon_Meducer 发表于 2017-6-29 18:33
class有掩码结构体保护,看不到成员,interface没有掩码结构体保护(保护了就没有意义了),所有成员都是 ...

好的。懂了

出0入0汤圆

发表于 2017-6-30 11:39:03 | 显示全部楼层
本帖最后由 ilcvm 于 2017-6-30 13:53 编辑

我觉得LZ封装得还是不够彻底,其实在所有成员还是暴露在queue.h里的,单纯通过queue.h包含的信息要访问内部成员还是有办法的。

我自己也喜欢搞这种面向对象方式的模块,我只会暴露调用函数,对象对外只是一个整数。跟LZ方法相比,我觉得这种做法有以下好处:

1. 模块封闭性更高。外部完全无法直接访问对象成员,连对象实体的地址也获取不了。
2. 能用很简单的方法准确判断输入对象的合法性。LZ的方法只能判断是否空指针,但判读不了野指针。这个对有指针函数的在对象成员里的情况非常重要,如果对象不合法,很容易造成Hard Fault
3. 容易扩展。如果要增加新成员,LZ的方法要改两个地方,而且必须要保证一致,如果只改了一个地方运行就会出错而且编译器不会有任何提示。

还是以queue为例子,我会这样封装成这样

//queue.h
#include <stdint.h>

typedef uint32_t queue_t;

extern queue_t queue_init( uint8_t *pchBuffer, uint16_t hwSize);


extern bool enqueue(queue_t ptQueue, uint8_t chByte);
extern bool dequeue(queue_t ptQueue, uint8_t *pchByte);
extern bool is_queue_empty(queue_t ptQueue);

========================================
//queue.c
#include <stdlib.h>
#include "queue.h"

typedef struct {
    uint8_t *pchBuffer;    //!< queue buffer   
    uint16_t hwBufferSize; //!< buffer size
    uint16_t hwHead;       //!< head pointer
    uint16_t hwTail;       //!< tail pointer
    uint16_t hwCounter;    //!< byte counter
}__queue_t;

#define MAX_QTY 16

static  __queue_t * m_Obj[MAX_QTY];
static queue_t m_ObjQty;

queue_t queue_init( uint8_t *pchBuffer, uint16_t hwSize)
{
      m_Obj[m_ObjQty] = malloc(sizeof(__queue_t ))
      m_ObjQty++;
      ......
      return m_ObjQty - 1;
}

bool is_queue_empty(queue_t ptQueue)
{
    if (m_ObjQty < ptQueue) {
        return true;
    }
    __queue_t *ptQ = m_Obj[ptQueue];
    return ((ptQ->hwHead == ptQ->hwTail) && (0 == ptQ->Counter));
}


出0入296汤圆

 楼主| 发表于 2017-6-30 16:09:50 | 显示全部楼层
ilcvm 发表于 2017-6-30 11:39
我觉得LZ封装得还是不够彻底,其实在所有成员还是暴露在queue.h里的,单纯通过queue.h包含的信息要访问内部 ...

应该说各有各的考虑。你这个方法的确有你说的优点,但是内存分配方式限制住了,只能用malloc。
然而,我就是要避免“限制他人只能用malloc”。我的考虑如下:

1、这种类封装方法可以直接继承
2、防君子不妨小人——C语言你怎么都防不了小人的,因为它不是type safe的
3、因为有了类型的大小信息,别人可以自由的根据他的需要选择内存的分配方式——无论是从栈,堆还是静态分配。

基于以上考虑,使用的人可以权衡,他们更关心C语言实现OOPC时候的信息隐蔽性(比如你的信息隐蔽性就很好),还是
一定语法级别的保护加上更灵活的内存分配方式+可能更方便的类的继承特性(扩展特性)。

各取所需吧。没有更好。如果我要是考虑更强的隐蔽性,做出来的封装估计也和你类似吧。
另外,注意到,你实际上用了句柄来限制可用的对象数量——这其实有点尴尬——论隐蔽性,如果你公开了源代码给别人,
别人可以很容易就获取你的对象信息(把“static  __queue_t * m_Obj[MAX_QTY];”的 static去掉,然后在外面加extern引用)
所以你这个方法也是防君子不妨小人的——如果要完全隐蔽,你就要提供.a,而不是源代码,既然是.a,那么这里的m_Obj
数组的大小就必须在library编译阶段固化,16个究竟是够用还是会浪费,这个都已成定局。

总结来说——你现有的方式还是有点尴尬的,一方面,隐蔽性仍然是防君子不防小人,另外一方面,又牺牲了灵活性。
我觉得既然如此,不如考虑对灵活性有所权重,而不是两个都丢掉了。

出0入0汤圆

发表于 2017-6-30 17:20:36 | 显示全部楼层
本帖最后由 ilcvm 于 2017-6-30 22:12 编辑
Gorgon_Meducer 发表于 2017-6-30 16:09
应该说各有各的考虑。你这个方法的确有你说的优点,但是内存分配方式限制住了,只能用malloc。
然而,我 ...


1.  继承我自己也有用,只是习惯只在模块内部做。
2.  我把内存分配控制在模块内目的不是为了让程序员不可修改对象成员,而是让外部模块代码不可修改对象成员,保证其他模块的代码出现怎样的错误都不会对模块内部运行造成影响。
3. 我的方法并不一定要用malloc,也可用静态分配内存static  __queue_t m_Obj[MAX_QTY],至于在栈内分配内存给对象我自己还碰上过这种需求。

各人需求不一样,实现方法自然有所取舍。我更注重使用过程中的安全性。如果我要更灵活更高效的内存分配,我会把成员定义在头文件里的queue_t里,实际上我自己写的队列模块就是这种方式,因为要用到的地方比较多而且对象很小,而在一些对象成员比较多代码较复杂而且使用对象数量比较有限的模块(如UART)才用上述方法。对于你介绍的方法我最担心的是在两处定义对象成员带来的隐患,在单处增减成员或改变成员大小甚至改变成员排序都有可能造成致命错误而编译器不会有任何警报。很多代码编辑器里,删一行或上移一个就是一个快捷键的操作。


出0入296汤圆

 楼主| 发表于 2017-6-30 23:32:03 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2017-6-30 23:43 编辑
ilcvm 发表于 2017-6-30 17:20
1.  继承我自己也有用,只是习惯只在模块内部做。
2.  我把内存分配控制在模块内目的不是为了让程序员不 ...


其实我说了,你只要给源代码,总归安全性就是一个纸糊的门。我说的内存分配的灵活性,意义在于,当你做一个库的时候,
使用的人可以自己决定如何分配内存,而不是由你决定。

另外,模块化很重要的一点就是要做到,写好的模块不允许修改:

—— 如果提供源代码,那么源代码也不允许修改,只能通过配置头文件传入配置宏来进行可控的条件编译和宏替换;
——如果不提供源代码,只提供.a,那么一个库仍然要保留必要的灵活性,而不能把类似内存分配方式做死了,否则
     以后使用的时候会是个问题。

针对你说的你也可以支持静态分配,这里我要澄清一下应用场景:

1、你做了一个模块,模块给别人用,你不希望别人修改你的代码,或者你根本没有时间写文档告诉别人如何修改
2、在这种情况下,把内存分配方式从动态改为静态,别人必须要看你模块的代码,理解,并找到需要修改的地方,
3、如果用你模块的人根本不在本地,不认识你,也只是图方便,那么阅读代码,修改代码给项目的开发速度,代码
    质量,以及潜在的对你模块的理解的不足带来的修改隐患  影响都很大
4、如果你提供的是.a,那么一旦发布了模块,不同的用户可能就无法修改内存分配方式。

总结来说,你的应用场景假设的是:我的代码只有我自己用,或者是我身边的认识的人用,陌生人是没法简单方便的
用的——除非你写文档,别人还要愿意修改你的模块。然而,我们做OO,做模块的意义,就是不光自己用,别人也能
用,而且你关心的也是,如果别人不小心,也不会破坏内部代码逻辑——这一点我们做信息隐藏都是一样的——但,
你现在的做法真的可以让陌生人方便的使用你的模块么?——你要考虑的不光是自己用的时候(自己掌握着所有的信息,
可以动态的根据情况调整代码),而是在用户没有你黑盒子实现逻辑的情况下,如何简单方便的使用。

让更多的人能方便的用自己的模块,就是我们的初衷。我就是基于这个考虑,才坚持一定要附加尺寸信息在类型上。
至于服务于我干刚刚说的这些内容,你可以看我专栏里面的几个公开的模块,都是以方便客户快速使用,并提供必要的
配置灵活性为前提的。

我觉得你先有的解决方案都是可行的,只是,很多建立模块复用的时候需要用户更多的干预里面的已有逻辑。我觉得这并不
能加快代码复用的效率。你担心的.c和头文件内容不一致的问题,的确是个问题,但并不是一个大问题。另外,从理论上,
我在另外一个帖子讨论了我这种做法的基本思路和原因。欢迎参与到讨论中。

https://www.amobbs.com/thread-5675247-1-1.html

讨论到现在,我可以给一个我的结论:

1、如果要真正好的信息保护,用C++,C语言无论怎么隐藏都是防君子不防小人,特别是你还要给人源代码。
2、为类型提供大小信息,会极大的简化用户的使用,掩码结构体只是一个更具体的规则——别人要遵守就遵守,不遵守,
    怎么玩你都行。
3、C++的继承本质上也就是结构体扩展,我的方法其实只是模拟C++对面向对象的二进制级别的实现。

最后,这个帖子放了这么久,才有人和你一样针锋相对的提出自己的观点,进行讨论,从我的角度看来其他人真的是做的没有你好!
这里非常感谢!感谢你的时间和耐心讨论,希望后面能继续简单直接的提出你的想法,继续讨论。

技术越讨论越清晰。很多时候,讨论到最后不是搞清楚好坏的问题,而是搞清楚了不同方案的“边界”在哪里,基于什么考虑,哪个
方案更好,缺点是什么。这很重要。没有 Fit for all 的终极解决方案。嵌入式系统本身就是专用系统,如果什么都通用了,这个
专(裁剪,针对性)带来的好处就很可能会受到影响。

出0入0汤圆

发表于 2017-7-1 16:02:31 | 显示全部楼层
Gorgon_Meducer 发表于 2017-6-30 23:32
其实我说了,你只要给源代码,总归安全性就是一个纸糊的门。我说的内存分配的灵活性,意义在于,当你做一 ...

你说的很对,我写模块的场景就是“只有我自己用,或者是我身边的认识的人用"。”身边的人“指的是同事,他们如果发现对模块的使用和配置有什么疑问我很容易就解答。但如果他们一些模块外的代码可以导致运行异常,那么如果模块出现运行异常查错对我来说就是一件非常麻烦的事情,所以防止使用者不小心”破坏内部代码逻辑“是我的设计模块的主意考虑方向。当然,我也不希望他们在使用过程中需要更改c文件里的代码,所以一些配置(如最大对象数量,内存是动态分配还是静态分配)都是放在模块头文件里,虽然其实他们大部分时间连这些都不改就用了。而你的模块是公布在网上供大家参考,使用场景可能千差万别,更多考虑灵活性也是正常的。

出0入296汤圆

 楼主| 发表于 2017-7-1 23:31:05 | 显示全部楼层
ilcvm 发表于 2017-7-1 16:02
你说的很对,我写模块的场景就是“只有我自己用,或者是我身边的认识的人用"。”身边的人“指的是同事, ...

我们本质上追求的事情是一样的。握手。

出0入0汤圆

发表于 2017-12-10 17:03:35 | 显示全部楼层
这用法不错 学习了

出0入0汤圆

发表于 2018-7-18 17:06:01 | 显示全部楼层
union queue_t {                                  \
    uint8_t *pchBuffer;    //!< queue buffer   
    uint16_t hwBufferSize; //!< buffer size
    uint16_t hwHead;       //!< head pointer
    uint16_t hwTail;       //!< tail pointer
    uint16_t hwCounter;    //!< byte counter                                 
    uint_fast8_t queue_t__chMask[(sizeof(struct{
    uint8_t *pchBuffer;    //!< queue buffer   
    uint16_t hwBufferSize; //!< buffer size
    uint16_t hwHead;       //!< head pointer
    uint16_t hwTail;       //!< tail pointer
    uint16_t hwCounter;    //!< byte counter
     }) + sizeof(uint_fast8_t) - 1) / sizeof(uint_fast8_t)];\
    };
这个.h文件展开后是个联合体,那除了数组外其它变量也可以操作了,难道是哪里还理解的不对

出0入0汤圆

发表于 2018-7-18 18:01:47 | 显示全部楼层
lzly0302 发表于 2018-7-18 17:06
union queue_t {                                  \
    uint8_t *pchBuffer;    //!< queue buffer   
  ...

这么搞会把自己绕死, 现在的编译器,基本上都支持C++,何必这么麻烦。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-19 05:27

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表