如何在C函数参数中不允许文本字符串而不允许动态字符串指针



我想这是我在这里的第一个问题。我写了我的C代码,试图尊重"-Wall-Wextra-Weror-ansi-迂腐";,但我可以很灵活。

我用以下原型编写了一个函数:

int messagequeue_add(messagequeue_t *p_queue, char* p_msg, const size_t p_size)

我使用";realloc(p_msg,XXX("在这个函数中。因此,它不应该接收字符串文字指针,而应该只接收动态指针。如何禁止字符串文字指针并仅允许字符串动态指针,在函数原型中,如果可能,使用标准C89或C99

我已经遇到过不允许在原型参数中使用文字字符串的函数(编译时出现错误/警告(,但我不记得它是在哪里以及如何定义的。

我试着用谷歌搜索了很多,去了我的整个纸质图书馆,这个问题太具体了,不可能大海捞针。我很有经验,但这次我确实需要帮助。

完整功能代码为:

int messagequeue_add(messagequeue_t *p_queue, char* p_msg, const size_t p_size) {
messagequeueitem_t l_messagequeueitem;
/* Parameters sanity checks for early return */
if (!p_queue) {
warnx("%s:%s():%d (%s@%s): p_queue can not be NULL",
__FILE__, __func__, __LINE__, __DATE__, __TIME__);
return -1;
}
if (!(*p_queue)) {
warnx("%s:%s():%d (%s@%s): *p_queue can not be NULL",
__FILE__, __func__, __LINE__, __DATE__, __TIME__);
return -1;
}
if ((!p_msg)&&(p_size)) {
warnx("%s:%s():%d (%s@%s): p_msg can not be NULL with p_size>0",
__FILE__, __func__, __LINE__, __DATE__, __TIME__);
return -1;
}
ASSERT(p_queue);
ASSERT(*p_queue);
ASSERT( ((NULL==(*p_queue)->head)&&(NULL==(*p_queue)->tail))
||((NULL!=(*p_queue)->head)&&(NULL!=(*p_queue)->tail)));
ASSERT((p_msg)||((!p_msg)&&(!p_size)));
/* Create messagequeueitem_t structure */
if (NULL == ((l_messagequeueitem) = (messagequeueitem_t)malloc(sizeof(struct messagequeueitem_s)))) {
warn("%s:%s():%d (%s@%s): malloc failed",
__FILE__, __func__, __LINE__, __DATE__, __TIME__);
return -1;
}
ASSERT(l_messagequeueitem);
l_messagequeueitem->size = p_size;
l_messagequeueitem->next=NULL;
/* Do not create a copy of the message but take ownership of the allocated
* contents. */
/* Resize the memory allocation to fit in the case sizeof(p_msg) != p_size */
DBG_PRINTF("p_msg=%p",p_msg);
if (NULL == ( l_messagequeueitem->msg = realloc( p_msg, l_messagequeueitem->size))) {
warn("%s:%s():%d (%s@%s): realloc failed",
__FILE__, __func__, __LINE__, __DATE__, __TIME__);
free(l_messagequeueitem);
return -1;
}
if ((*p_queue)->tail)
(*p_queue)->tail->next = l_messagequeueitem;
else
(*p_queue)->head = l_messagequeueitem;
(*p_queue)->tail = l_messagequeueitem;
return 0;
}

我用以下原型编写了一个函数:

int messagequeue_add(messagequeue_t *p_queue, char* p_msg, const size_t p_size)

我使用";realloc(p_msg,XXX("在这个函数中。因此,不应该以接收字符串文字指针,但仅接收动态指针。怎样禁止字符串文字指针并允许字符串动态指针仅在功能原型中,如果可能,使用标准C89或C99

标准C的任何版本都不提供区分字符串文字的指针(in(和其他字符指针的机制。字符串文字表示的数组元素的类型为char,因此指向它们的指针的类型可以为char *,C不指定是否存在任何元数据,通过这些元数据可以将它们与相同类型的其他值区分开来。

这通常通过编码约定来处理。具体来说,作为一种代码约定

  1. 指向或指向字符串文字的指针只能分配给作为指向const数据和的指针的变量和函数参数

  2. 严格遵守const的正确性(不丢弃const或通过其他方式丢弃它(。

这意味着在要接受可能指向字符串文字的指针的地方,可以使用类型const char *

遵守这样的约定排除了向期望指向可修改数据的指针的代码提供指向字符串文本的指针。


特定的编译器可能会提供一些有用的功能。例如,许多方法可以针对违反const正确性的情况生成警告和/或错误。有些选项专门用于检测修改字符串文字的尝试。例如,如果使用GCC进行编译并启用其静态分析器,则它将检测到(至少一些(写入const数据和字符串文字的尝试。

但是

你把你的问题描述得太狭隘了。如果您希望能够realloc()传递给函数的p_msg指针,那么该指针必须是以前通过动态分配获得的(而不是自free()d以来(。这是一个比不指向字符串文字强得多的要求,所以关注字符串文字角度可能没有那么有用。

您绝对应该文档这个需求,并且您应该适当地将该需求传播到其他函数的文档中。但是,如果要求只是可以修改指向的数据,那么您不太可能获得像这样的编译器帮助。C不提供任何值或数据类型属性来描述可修改但不可取消/重新分配的数据。然而,有一些工具可以在运行时检测此类问题。例如,Valgrind可以做到这一点。

最新更新