函数参数中的 struct 关键字和 const 正确性
Posted
技术标签:
【中文标题】函数参数中的 struct 关键字和 const 正确性【英文标题】:struct keyword in function parameter, and const-correctness 【发布时间】:2011-06-29 19:36:35 【问题描述】:我的库中有一个不透明类型定义为:
typedef struct MyOpaqueType* MyType; // easier to type for client code
我不能使用 typedef 传递指向 const 结构的指针,所以一些函数看起来像:
void UsePointerToConst ( const struct MyOpaqueType * )
代替:
void UserPointerToConst( const MyType ) // can't use, is really constant pointer
因此,鉴于此,我有两个问题: 参数列表中的 struct 关键字是否仅在 C 中是必需的? 有一个更好的方法吗?我应该创建一个 typedef,例如:
typedef const struct MyOpaqueType* ConstantMyType; ?
【问题讨论】:
第二种typedef是解决问题的合理方法。参数列表中的struct关键字是否只有C语言才需要?
是的。参见 Jens Gustedt 的回答。
有没有更好的方法来做到这一点?
只是typedef
结构,而不是指针。这更好,因为
typedef
而不是 MyOpaqueType
、MyOpaqueType *
、MyOpaqueType const *
、MyOpaqueType *const
和 MyOpaqueType const *const
以及所有涉及 restrict
的变体(不存在)在 C++ 中),
用户很清楚指针语义适用,即传递数据类型实际上是指针复制的问题(无需担心性能),用户不太可能在使用后忘记清理,C++ 用户可以使用智能指针,和
这是一个常见的 C 约定(想想FILE *
)。
也没有危险;当有人忘记*
时,会出现编译器错误。
【讨论】:
@Cat 存在,但不完整。你仍然可以 typedef 它。 是的,但隐藏这个不透明句柄是指针的概念是我想保留的。 typedef struct MyOpaqueType* MyType 是该代码使用多年的库惯用语。不过,我可能不明白你在说什么。 @Cat 这是一个常见的 C 习语。 C++ 有点不同——例如,struct 关键字引入了一个新的类型名称。您可以使用两种类型定义(用于 const 和非 const),但惯用的 C++ 可能会按照我在回答中的建议这样做。 @Cat:当我输入这个答案时,我很着急。扩展它为什么指针typedef
对您的问题来说是个坏主意。
+1 建议不要隐藏 typedef
的目标是指针。【参考方案2】:
在 C++ 中,只要不存在具有该名称的其他标识符,就会假定 typedef
与 struct
同名。所以类似于函数stat
接收struct stat*
作为参数:
int stat(const char *path, struct stat *buf);
在 C++ 中甚至是允许的。 (这是一个真实的例子。)
所以你总是更好地使用像
这样的前向声明typedef struct toto toto;
在标识符和结构名称空间中保留标记toto
。然后你可以为 C 和 C++ 声明你的函数接口。但是,如果您也想从 C 中访问它,请不要忘记 extern "C"
。
另请参阅:this answer on SO 和 struct tags are not identifiers in C++。
【讨论】:
准确地说,用户定义类型的标识符和其他标识符在 C++ 中以与 C 中相同的方式保持分开,但是,在查找标识符时在一个范围内,如果标识符不在全局标识符空间中,那么它也在用户定义的类型标识符空间中搜索......有点微妙的区别。 @David,是的,它甚至允许更荒谬的事情,例如首先使用裸词作为对struct
的引用,然后再定义一个变量。 C++ 是一种对上下文非常敏感的语言,但我们已经知道了,不是吗。【参考方案3】:
在 C++ 中你根本不需要 typedef。只需使用前向声明:
struct MyType;
然后在需要时传递MyType const *
、MyType *
、MyType const &
等。
【讨论】:
我不想传递结构指针以外的任何东西,因为结构不存在,只是为了类型安全而存在。 @Cat 它绝对存在;你声明了它,所以它存在。您不必为上述工作定义它。试试看! 即使您从未定义该结构的外观,您仍然可以使用这样的前向声明来允许您创建指向具有该名称的结构的指针。如果您尚未定义结构,请不要尝试取消引用它们... 哦,我明白你的意思了。对不起,我读你的评论太快了。 C代码参数不是必须写成PublicFunction(struct MyType* t)吗?我认为 PF(MyType t) 更容易阅读。 @Cat 写typedef struct MyType MyType;
如果你需要它在 C 和 C++ 中工作。 PF(MyType * t)
既易于阅读,又能明确说明正在发生的事情。以上是关于函数参数中的 struct 关键字和 const 正确性的主要内容,如果未能解决你的问题,请参考以下文章