【问题标题】:Argument without type in CC中没有类型的参数
【发布时间】:2014-12-12 23:21:28
【问题描述】:

我对编程语言相当陌生,想知道是否可以将没有特定类型的参数传递给函数。例如,我有以下代码,它定义了一个函数add,它将占用一块内存,检查它是否通过另一个函数填充,然后将一个元素添加到与该内存块相关的列表中。

此元素可以是 int、float 或 char。所以我想写:

add(arrs1,20); //or also
add(arrs2,'b'); //or also
add(arrs3, 4.5);

arrs# 由struct arrs arrs# 定义,它们指的是浮点数、整数或字符数组,但不混合。我怎么能做到这一点?

int add(arrs list, NEW_ELEMENT){//adds NEW_ELEMENT at the end of an arrs
  int check_if_resize;
  check_if_resize=resize(list, list->size + 1);
  list->ptr[list->used++] = NEW_ELEMENT;
  return check_if_resize;
}

感谢您的帮助。

【问题讨论】:

  • 不,但有些人会使用宏来执行此操作,或者他们会使用void*(和内存大小)并使用memcpy 将数据写入必要的位置。
  • @Cornstalks 你能给我一个使用宏的例子吗?你的意思是像定义 add 不是一个 int 函数,而是一个宏,例如#define add(list,NEW_ELEMENT) (here what?).
  • qsort() 不就是这样吗?不仅是数据类型,还有它的 compare() 函数参数。
  • 如果您真的需要这样做,请使用 glib 及其变体对象
  • C 是一种强类型 语言,但有一些方法可以通过类型转换来解决这个问题。关于这个主题有几个以前的 SO 问题,例如。 stackoverflow.com/questions/2351190/…

标签: c arguments argument-passing


【解决方案1】:

C 在设计上不允许单个函数为每个参数接受多个类型。不过,有多种方法可以在 C 中做一些等效的事情:

首先,您可以编写多个不同的函数,它们的功能相同,但类型不同。例如,除了add,您还可以使用三个名为add_intadd_charadd_float 的函数。我建议在大多数情况下这样做,因为它是迄今为止最简单且最不容易出错的。

其次,您可能已经注意到printf 是如何同时打印字符串和数字的?所谓的可变参数函数,比如printf,可以接受不同类型的参数,但是对于printf,你仍然必须在格式字符串中指定你想要的参数类型。

最后,如果您需要使用对象占用的内存,无论其类型如何,都可以使用void 指针。像memcpymemset 这样的函数就是这样做的,例如将一个对象的内容直接复制到另一个对象。这有点难以正确管理,因为很容易出错并最终破坏内存,但它仍然可行(有时甚至是最佳选择)。

但是,如果您是 C 的初学者,正如您所说,第一个选项可能是最简单的,尤其是在处理几种不同的数据类型(在本例中为三种)时。

【讨论】:

  • 我要补充一点,如果你想对 void 指针指向的数据做任何事情(除了按字节处理),你必须提供某种运行时类型信息,例如枚举作为类型标记等,因为 C 没有内在的运行时类型信息,即内存不携带有关如何解释其内容的信息。
  • #define ADD(list,new_element) (*(list->ptr+list->used++)=new_element) 为什么这行不通?
  • @NotStrang 这可以工作,但是因为new_element 将被转换为*(list->ptr) 的类型,您可能会丢失信息。例如,如果new_elementfloatlist->ptrint* 类型,那么new_element 将被转换为int,丢失所有小数位。
  • 如果 list->ptr 是 void* 类型?
  • @NotStrang 这不是有效的 C;你不能用void* 做加法,也不能取消引用void*(因为void 不是真正的普通类型,而是缺少它)。
【解决方案2】:

您可以在函数中将任何内容作为 void * 传递,该函数将通过使用 memcpy(甚至是安全的 memmove)将此内容添加到链表中。 只要您有指向列表下一个节点的指针,您就不必担心存储数据的类型。 请确保不要取消对 void * 的引用,而是对其进行转换并使用此转换后的变量(例如,如果您想逐字节处理此数据,则将其作为 char)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多