我查看了一些代码并注意到约定是将指针类型转换为
SomeStruct*
进入
typedef SomeStruct* pSomeStruct;
这有什么优点吗?
我查看了一些代码并注意到约定是将指针类型转换为
SomeStruct*
进入
typedef SomeStruct* pSomeStruct;
这有什么优点吗?
当指针本身可以被视为一个“黑匣子”,即其内部表示应该与代码无关的一段数据时,这可能是合适的。
本质上,如果您的代码永远不会取消引用指针,而您只是将它传递给 API 函数(有时通过引用),那么 typedef 不仅会减少*
代码中 s 的数量,而且还会向程序员建议指针应该真的不要被插手。
如果需要,这也使得将来更改 API 变得更容易。例如,如果您更改为使用 ID 而不是指针(反之亦然),现有代码不会中断,因为从一开始就不应该取消引用指针。
不是我的经验。隐藏 ' *
' 会使代码难以阅读。
我在 typedef 中使用指针的唯一一次是在处理指向函数的指针时:
typedef void (*SigCatcher(int, void (*)(int)))(int);
typedef void (*SigCatcher)(int);
SigCatcher old = signal(SIGINT, SIG_IGN);
否则,我发现它们比有用更令人困惑。
signal()
函数的指针的正确类型,而不是信号捕获器的指针。可以通过以下方式使其更清晰(使用SigCatcher
上面更正的类型):
typedef SigCatcher (*SignalFunction)(int, SigCatcher);
或者,声明signal()
函数:
extern SigCatcher signal(int, SigCatcher);
也就是说, aSignalFunction
是一个指向函数的指针,该函数接受两个参数(anint
和 a SigCatcher
)并返回 a SigCatcher
。signal()
它本身是一个函数,它接受两个参数(an和int
a SigCatcher
)并返回 a SigCatcher
。
这可以帮助您避免一些错误。例如在以下代码中:
int* pointer1, pointer2;
pointer2 不是int *,它是简单的int。但是使用 typedefs 这不会发生:
typedef int* pInt;
pInt pointer1, pointer2;
他们现在都是int *。
我的回答是明确的“不”。
为什么?
好吧,首先,您只需将一个字符换成*
另一个字符p
。那是零收益。仅此一项就可以阻止您这样做,因为做多余的毫无意义的事情总是不好的。
其次,这也是重要的原因,不好隐藏的*
携带意义。如果我将某些东西传递给这样的函数
void foo(SomeType bar);
void baz() {
SomeType myBar = getSomeType();
foo(myBar);
}
我不希望myBar
通过将其传递给foo()
. 毕竟,我是按价值传递的,所以foo()
只能看到副本myBar
对吗?不是 whenSomeType
被别名为某种指针!尤其是当该指针充当对某种对象的引用时,该对象的值基本上就是指针的含义:我不在乎指针本身不会改变(由于按值传递),我感兴趣的是对象是否改变(指针后面的对象)。
这适用于 C 指针和 C++ 智能指针:如果您隐藏它们是指向您的用户的指针这一事实,您将造成完全不必要的混淆。所以,请不要给你的指针起别名。
(我相信 typedefing 指针类型的习惯只是一种错误的尝试,试图隐藏一个程序员有多少颗星http://wiki.c2.com/?ThreeStarProgrammer。)
这是风格问题。您在 Windows 头文件中经常看到这种代码。尽管他们更喜欢全大写版本,而不是以小写 p 为前缀。
我个人避免使用 typedef。让用户明确表示他们想要 Foo* 比 PFoo 要清楚得多。如今,Typedef 最适合使 STL 可读:)
typedef stl::map<stl::wstring,CAdapt<CComPtr<IFoo>> NameToFooMap;
它(就像很多答案一样)取决于。
在 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);
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.
假设感兴趣的语言是 C 进行讨论。尚未考虑 C++ 的分支。
定义为指针的结构的大小问题引发了关于使用typedef
for (结构) 指针的有趣的侧面光。
考虑无标记的具体(非不透明)结构类型定义:
typedef struct { int field1; double field2; } *Information;
成员的细节与本次讨论完全无关;重要的是这不是一个不透明的类型typedef struct tag *tag;
(你不能通过没有typedef
标签的 a 来定义这种不透明的类型)。
提出的问题是“你怎么能找到那个结构的大小”?
简短的回答是“仅通过类型的变量”。没有与 . 一起使用的标签sizeof(struct tag)
。例如,您不能有用地编写andsizeof(*Information)
sizeof(Information *)
是指向指针类型的指针的大小,而不是结构类型的大小。
事实上,如果你想分配这样的结构,除了通过动态分配(或模拟动态分配的代理技术)之外,你无法创建一个。没有办法创建指针被调用的结构类型的局部变量,也没有办法创建结构类型的Information
文件范围(全局或static
)变量,也没有办法嵌入这样的结构(如与指向此类结构的指针相反)转换为另一个结构或联合类型。
你可以——必须——写:
Information info = malloc(sizeof(*info));
除了指针隐藏在 中之外typedef
,这是一个很好的做法——如果类型发生info
变化,大小分配将保持准确。但在这种情况下,它也是获取结构体大小和分配结构体的唯一方法。并且没有其他方法可以创建结构的实例。
这取决于你的目标。
这不是一个不透明的类型——结构的细节必须在指针类型为typedef
'd 时定义。
它是一种只能用于动态内存分配的类型。
这是一种无名的类型。指向结构类型的指针有名称,但结构类型本身没有。
如果您想强制执行动态分配,这似乎是一种方法。
不过,总的来说,它更容易引起混乱和焦虑,而不是启蒙。
通常,使用typedef
定义指向无标记结构类型的指针是一个坏主意。
不。
混在一起的那一刻,它会让你的生活变得悲惨const
typedef foo *fooptr;
const fooptr bar1;
const foo *bar2
bar1
和bar2
是同一类型吗?
是的,我只是在引用 Herb Sutter 的 Guru。她说了很多实话。;)
- 编辑 -
添加引用文章的链接。
http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835
typedef 用于使代码更具可读性,但是将指针作为 typedef 会增加混乱。最好避免使用 typedef 指针。
如果这样做,您将无法创建 const pSomeStruct 的 STL 容器,因为编译器会读取:
list<const pSomeStruct> structs;
作为
list<SomeStruct * const> structs;
这不是合法的 STL 容器,因为元素不可分配。
看到这个问题。
Win32 API 对几乎所有结构(如果不是全部)都执行此操作
POINT => *LPPOINT
WNDCLASSEX => *LPWNDCLASSEX
RECT => *LPRECT
PRINT_INFO_2 => *LPPRINT_INFO_2
它的一致性很好,但在我看来它并没有增加任何优雅。
typedef 的目的是隐藏实现细节,但是 typedef 指针属性隐藏太多,使代码更难阅读/理解。所以请不要那样做。
如果你想隐藏实现细节(这通常是一件好事),不要隐藏指针部分。以标准FILE
接口的原型为例:
FILE *fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, FILE *stream);
这里 fopen 返回一个指向某个结构的指针FILE
(您不知道其实现细节)。也许FILE
不是一个很好的例子,因为在这种情况下,它可以与一些隐藏它是指针的事实的 pFILE 类型一起工作。
pFILE fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, pFILE stream);
但是,这只会起作用,因为您永远不会弄乱直接指向的内容。根据我的经验,当您键入一些指针时,您在某些地方修改代码变得非常难以阅读。
前段时间,我会对这个问题回答“不”。现在,随着智能指针的兴起,指针不再总是用星号'*'定义。因此,类型是否是指针没有什么明显的。
所以现在我想说:typedef 指针很好,只要非常清楚它是一个“指针类型”。这意味着您必须专门为它使用前缀/后缀。不,例如,“p”不是一个足够的前缀。我可能会选择“ptr”。
一般来说,没有。在特定情况下,是的。
有一些其他答案暗示了一些结构,那就是仅指针类型。我想到了几个仅指针类型的构造。如果有人想到更多,我会将它们添加到列表中。
这些类型的实现对用户完全隐藏。您通常会在标头中看到一个结构 typedef,但没有该结构的实现。因此,您不能取消引用这些类型的值。对这种类型进行操作的所有函数都采用指向这些类型的指针。在这些情况下添加指向 typedef 的指针是合适的。您经常会看到这些称为“句柄”的类型。
typedef struct handle_ * handle;
handle get_handle(string s);
void mutate_handle(handle h, value v);
void release_handle(handle h);
另一种仅指针类型是使用灵活数组成员 (FAM) 定义的类型。FAM 类型中的最后一个成员是不受约束的数组。您打算为这些类型动态分配存储空间,并且灵活数组被视为与结构内联。您可以访问 FAM 类型中的字段,但不能取消引用整个对象。在这里添加指向 typedef 的指针也是合适的。
typedef struct string {
size_t capacity;
size_t length;
char buffer[];
} * string;
string string_new(void);
size_t string_length(string s);
void string_append(string * s, char c);
void string_delete(string * s);