我有一个公共函数,它对缓冲区执行读操作并执行摘要。它有一个const uint8_t *
参数。
void do_digest(const uint8_t *buf, size_t size);
在内部,我将所有指针大小对包装在一个简单的缓冲区结构中:
typedef struct {
uint8_t *buf;
size_t size;
} myBuffer;
然而,作为一个迂腐的开发者,我想摆脱一个警告,指出在分配给myBuffer
结构时参数的常量被剥离。
myBuffer foo = { buf, size }; // Warning: discards 'const' qualifier
因此,最简单和最明确的解决方案是创建一个与const缓冲区一起使用的新结构类型:
typedef struct {
const uint8_t *buf;
size_t size;
} myConstBuffer;
myConstBuffer cfoo = { buf, size }; // No warnings, woohoo!
但是,有一个问题;在内部我传递指向这些缓冲区结构的指针。现在,如果我有一个可变的myBuffer
实例并且我想将它传递给一个带有myConstBuffer
指针的函数,我会收到一个抱怨不兼容类型的警告。
void some_internal_func(const myConstBuffer *b);
...
myBuffer mutable_buf = { ... };
some_internal_func(&mutable_buf); // Warning: incompatible types.
似乎我正在为另一个警告交易。有更好的解决方案吗?
提前致谢。
答案 0 :(得分:1)
回答你的问题:标准库中的函数经常会遇到这种情况,我不知道有什么更好的解决方案来构建参数,使其包含const
限定符(即,如果你不要选择忽略警告:))
当函数在其原型中定义其参数之一具有类型<type> const *
时,这并不是要求您提供类型const
的参数,因为它表明函数不会尝试修改该地址的内容。函数通过指定const
请求的是,在该函数调用期间,您(可能来自不同的线程)不会修改该地址的内容。
通常你会在库函数中看到这个,这些函数通常没有在C中实现。但是如果它们是,那么尝试修改<type> *const param
指向的位置会导致编译器错误。
在我看来,方式更有可能发出与const
相关的警告,而不是incompatible type
,因为通过将变量强制转换为{{const
更加安全。将它作为参数传递而不是传递给其他类型时。
答案 1 :(得分:0)
没有简单的解决方案,因为如果您使用const <type> *
和<type> *
结构,则它们不兼容。
但是,如果您可以使用C11或至少C99,则可以自己buff
struct
个typedef struct {
size_t size;
uint8_t data[];
} Buffer;
,其中包含大小和数据:
malloc
请注意,您无法从中创建静态或自动变量,因此您必须使用size_t buffer_length = 10;
Buffer *buff = malloc(sizeof(*buff) + buffer_length);
if ( buff != NULL ) {
buff->size = buffer_length;
...
&amp;朋友:
struct
此buff
可以像上面的const Buffer *
一样传递到Buffer *
或struct
,但您不再需要跟踪大小/长度,从而改变界面。
这称为灵活数组成员。它必须是sizeof(Buffer)
的最后一个成员。 struct
就好像数组有0个条目(在C中不允许,但是对于C99之前的代码是gcc扩展遗留。
更新:当然,只有在所有级别使用此struct
时,这才有意义。因此,您只需将此{{1}}传递给使用此类数组加上长度/大小的所有函数。否则你将不得不复制数据,这通常是不需要的(没有例外的规则)。
在开发软件时,内部接口的设计通常需要很长一段时间的设计时间。但正如你现在看到的那样,值得付出努力。