输入deff指针是个好主意吗?

Unk*_*own 68 c c++ pointers typedef conventions

我查看了一些代码并发现惯例是将指针类型转换为

SomeStruct* 
Run Code Online (Sandbox Code Playgroud)

typedef SomeStruct* pSomeStruct;
Run Code Online (Sandbox Code Playgroud)

这有什么好处吗?

Art*_*ius 100

当指针本身可以被视为"黑盒子"时,这是适当的,即,其内部表示应该与代码无关的一段数据.

本质上,如果您的代码永远不会取消引用指针,并且您只是将其传递给API函数(有时通过引用),那么不仅typedef减少了*代码中的s 数量,而且还向程序员建议指针不应该真的被插手了.

如果需要,这也可以在将来更容易地更改API.例如,如果您更改为使用ID而不是指针(反之亦然),现有代码将不会中断,因为指针永远不应该首先被解除引用.

  • 反例:FILE*fp?实际上,我同意你的观点,但有相反的先例. (12认同)
  • "当然,如果你这样做,你就不要将opaque类型命名为"pFoo". (10认同)
  • 真实世界的例子:在OS X中,CoreFoundation框架广泛使用了这种技术,将它们称为"不透明"数据类型. (9认同)
  • 同样在OS X中:pthread_t是一个不透明的类型; 它的typedef是一个指向'struct _opaque_pthread_t'的指针,它本身就是一个不透明的字节数组. (3认同)
  • @MattJoiner:`FILE*`不是typedef'd作为一个不透明指针的原因是允许诸如`getc()`和`putc()`之类的宏直接操作FILE结构并避免大多数情况下的函数调用开销. (2认同)

sig*_*ice 70

不是我的经验.隐藏' *'会使代码难以阅读.


Jon*_*ler 28

我在typedef中使用指针的唯一一次是处理指向函数的指针时:

typedef void (*SigCatcher(int, void (*)(int)))(int);
Run Code Online (Sandbox Code Playgroud)

typedef void (*SigCatcher)(int);

SigCatcher old = signal(SIGINT, SIG_IGN);
Run Code Online (Sandbox Code Playgroud)

否则,我发现它们比有用更令人困惑.


被删除的声明是指向signal()函数的指针的正确类型,而不是信号捕获器的指针.SigCatcher通过编写可以使其更清晰(使用上面更正的类型):

 typedef SigCatcher (*SignalFunction)(int, SigCatcher);
Run Code Online (Sandbox Code Playgroud)

或者,声明signal()函数:

 extern SigCatcher signal(int, SigCatcher);
Run Code Online (Sandbox Code Playgroud)

也就是说,a SignalFunction是一个指向函数的指针,该函数接受两个参数(a int和a SigCatcher)并返回a SigCatcher.而signal()本身是有两个参数(一个函数int和一个SigCatcher)并返回SigCatcher.

  • 凉爽的。恕我直言,带有显式 * 的等效声明看起来并没有那么糟糕。typedef void SigCatcher(int); extern SigCatcher *signal(int, SigCatcher *); (2认同)

Sad*_*per 14

这可以帮助您避免一些错误.例如,在以下代码中:

int* pointer1, pointer2;
Run Code Online (Sandbox Code Playgroud)

pointer2不是int*,它是简单的int.但是对于typedef,这不会发生:

typedef int* pInt;
pInt pointer1, pointer2;
Run Code Online (Sandbox Code Playgroud)

他们现在都是int*.

  • 如果你把*触摸指针1而不是触摸"int",那么声明更有意义指针2不是指针,只是一个int. (12认同)
  • 我认为C程序员会争辩说在声明指针变量时使用解除引用操作符更像是一种惯用的东西.为了检查,在K&R中,他们说:"'int*ip'意图作为助记符;它表示'*ip'是一个int." (3认同)
  • 但每个人都知道这种语法,最好一次声明并初始化一个变量......我很少写int*pointer1,*pointer2; 因为在下一行中你有两个带有未定义值的好指针. (2认同)
  • Roalt 的意思是:'int \*pointer1' 而不是 'int\* pointer1'。 (2认同)
  • @Daniel Daranas:`int*p1 = NULL,*p2 = NULL;` (2认同)
  • 用更糟糕的做法来捍卫不良做法的典型例子。永远不要在一行中声明多个变量,因为永远没有理由这样做,句号。它只会导致错误。整个“指针接触”辩论都是无稽之谈,因为如果你首先编写好的代码,`*` 的位置并不重要。 (2认同)

cma*_*ter 12

我的回答是明确的"不".

为什么?

好吧,首先,你只需要*为另一个角色交换一个角色p.这是增益.仅此一点就应该让你不要这么做,因为做一些没有意义的额外的东西总是很糟糕.

其次,这就是重要的原因,隐藏着不好*携带意义.如果我将某些东西传递给这样的函数

void foo(SomeType bar);

void baz() {
    SomeType myBar = getSomeType();
    foo(myBar);
}
Run Code Online (Sandbox Code Playgroud)

我不希望myBar通过传递它来改变它的含义foo().毕竟,我正在经历价值,所以foo()只能看到一份myBar正确的副本?不是什么时候SomeType别名意味着某种指针!

这适用于C指针和C++智能指针:如果你隐藏它们指向用户的事实,你将产生完全不必要的混淆.所以,请不要别指你的指针.

(我相信typedefing指针类型的习惯只是误导了一个程序员http://wiki.c2.com/?ThreeStarProgrammer隐藏了多少个星星.)


Jon*_*ler 8

假设感兴趣的语言是 C 进行讨论。尚未考虑对 C++ 的影响。

\n\n

对未标记的结构使用指针 typedef

\n\n

定义为指针的结构的大小问题引发了关于使用(结构)指针的有趣侧面typedef

\n\n

考虑无标签具体(非不透明)结构类型定义:

\n\n
typedef struct { int field1; double field2; } *Information;\n
Run Code Online (Sandbox Code Playgroud)\n\n

成员的详细信息与本次讨论完全无关;重要的是这不是一个不透明类型typedef struct tag *tag;(并且您不能通过typedef不带标签的 a 来定义此类不透明类型)。

\n\n

提出的问题是“如何找到该结构的大小”?

\n\n

简短的答案是“仅通过该类型的变量”。没有可与 一起使用的标签sizeof(struct tag)sizeof(*Information)例如,您不能有效地编写, andsizeof(Information *)是指向指针类型的指针的大小,而不是结构类型的大小。

\n\n

事实上,如果您想分配这样的结构,除非通过动态分配(或模仿动态分配的代理技术),否则无法创建一个结构。没有办法创建其指针被调用的结构类型的局部变量Information,也没有办法创建static结构类型的文件范围(全局或)变量,也没有办法嵌入这样的结构(如与指向此类结构的指针相反)到另一个结构或联合类型。

\n\n

你可以\xe2\x80\x94必须\xe2\x80\x94写:

\n\n
Information info = malloc(sizeof(*info));\n
Run Code Online (Sandbox Code Playgroud)\n\n

除了指针隐藏在 中这一事实之外typedef,这是一个很好的做法 \xe2\x80\x94\xc2\xa0 如果类型发生info变化,大小分配将保持准确。但在这种情况下,它也是获取结构体大小并分配结构体的唯一方法。并且没有其他方法可以创建该结构的实例。

\n\n

这有害吗?

\n\n

这取决于你的目标。

\n\n

这不是不透明类型\xe2\x80\x94,当指针类型为typedef\'d 时,必须定义结构的详细信息。

\n\n

它是一种只能与动态内存分配一起使用的类型。

\n\n

这是一种无名的类型。指向结构类型的指针有名称,但结构类型本身没有名称。

\n\n

如果你想强制动态分配,这似乎是一种方法。

\n\n

但总的来说,它比启蒙更有可能引起困惑和焦虑。

\n\n

概括

\n\n

一般来说,使用typedef定义指向无标记结构类型的指针是一个坏主意。

\n

  • 实际上,您可以通过在“取消引用”的“NULL”强制转换为“Information”上应用“sizeof”来获得没有对象的大小。尝试“sizeof(*(信息)0)”。 (2认同)

Jar*_*Par 5

这是一种风格问题.您在Windows头文件中经常看到这种代码.虽然他们倾向于选择全部大写版本,而不是使用小写p作为前缀.

我个人避免使用typedef.让用户明确表示他们想要一个Foo*比PFoo更清楚.Typedef最适合这些天使STL可读:)

typedef stl::map<stl::wstring,CAdapt<CComPtr<IFoo>> NameToFooMap;
Run Code Online (Sandbox Code Playgroud)


Mar*_*ork 5

它(像许多答案一样)取决于.

在C中,这是非常常见的,因为你试图伪装一个对象是一个指针.你试图暗示这是你所有函数操作的对象(我们知道它是一个指针,但它代表你正在操作的对象).

MYDB   db = MYDBcreateDB("Plop://djdjdjjdjd");

MYDBDoSomthingWithDB(db,5,6,7);
CallLocalFuc(db); // if db is not a pointer things could be complicated.
MYDBdestroyDB(db);
Run Code Online (Sandbox Code Playgroud)

在MYDB下面可能是某个对象的指针.

在C++中,不再需要它.
主要是因为我们可以通过引用传递内容,并将方法合并到类声明中.

MyDB   db("Plop://djdjdjjdjd");

db.DoSomthingWithDB(5,6,7);
CallLocalFuc(db);   // This time we can call be reference.
db.destroyDB();     // Or let the destructor handle it.
Run Code Online (Sandbox Code Playgroud)


dgn*_*uff 5

不。

与它混在一起的那一刻,它会让你的生活变得悲惨 const

typedef foo *fooptr;
const fooptr bar1;
const foo *bar2
Run Code Online (Sandbox Code Playgroud)

bar1bar2同类型吗?

是的,我只是在引用 Herb Sutter 的 Guru。她说了很多实话。;)

- 编辑 -

添加引用文章的链接。

http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835