【问题标题】:Macro to both get (void*) address of item and length, for arrays and structs用于获取数组和结构的 (void*) 项目地址和长度的宏
【发布时间】:2010-08-06 23:30:39
【问题描述】:

我正在尝试设计一个宏来生成与需要初始化的事物相关的几个相关数据结构。代码必须在 C 和 C++ 下编译。我们的目标是:

MUNGE_THING(struct1); MUNGE_THING(array1);

变成等价的东西

munge_thing((void*)&struct1, sizeof(struct1)); munge_thing((void*)array1, sizeof(array1));

是否有任何句法的东西我可以围绕宏参数,以便它在获取地址和获取大小时都能正确处理数组和结构?最可能的上下文将在初始化列表的常量声明中。

如果这是不可能的,并且必须为结构和数组使用单独的宏,那么确保错误传递某些内容会产生编译错误而不是伪造代码的最佳语法是什么?

在“旧”C 中,在数组地址前加上“&”会产生警告,但不会阻止编译。在 C++ 中,它似乎产生了存储数组地址的位置的地址。

MUNGE_THING 宏将位于另一个宏中,该宏将使用不同的 MUNGE_THING 定义多次调用,因此为数组和结构设置单独的宏会令人厌烦。我能想到的最好的方法是给 MUNGE_THING 一个额外的参数来表示“可选”&符号,但这似乎很难看。

【问题讨论】:

  • 如果C和C++需要不同的定义,你可以使用#ifdef __cplusplus

标签: c++ c


【解决方案1】:

如果数组实际上是一个数组(这似乎是sizeof 工作所必需的),为什么不使用简单的宏:

#define MUNGE_THING( x ) munge_thing((void*)&(x), sizeof(x))

这应该适用于数组和结构:

int array[10];
assert( (void*)array == (void*)&array );

您已将问题标记为 C 和 C++,在 C++ 中,您可以同时使用模板并避免使用宏。

【讨论】:

  • 请注意,sizeof(&array) 会产生整个数组的大小,而sizeof(array) 会产生数组第一个元素的大小。这个宏可能还是不行。
  • @David Rodríguez - dribeas:正如我所指出的,这个特定的代码必须同时编译为 C 和 C++;模板将使其仅可用于 C++。对于仅 C++ 的项目模板可能有用。
  • @Nathon:这是完全错误的。 sizeof arr 产生整个数组的字节大小,而sizeof &arr 产生指向该数组的指针的大小。 6.3.2.1 第 3 段:" 除非它是 sizeof 运算符的操作数 或一元 & 运算符,或者是用于初始化数组的字符串字面量,否则表达式类型为 ''array of type'' 被转换为类型为 ''pointer to type'' 的表达式,它指向数组对象的初始元素并且不是左值。"
  • 我不太了解@Luther Blissett 或@Nathon 的cmets。 @Luther:在munge_thing 中,您会收到void*int。你根本不能说什么——我只能假设这只会用于处理原始字节(通过网络发送?)。 @Nathon:数组的地址和第一个元素的地址相同。 (void*)array(void*)(&array[0]),即 (void*)&array。请注意,我没有在sizeof 中应用& 运算符,仅在指针端应用。代码是正确的。
【解决方案2】:

我不确定您对&array1 有什么问题。这个 C++ 完全按预期工作(所有值都相同)

int main(int argc, char* argv[])
{
    int array1[10];

    printf("%x %x\n", array1, &array1);
    cout << array1 << " " << &array1 << endl;

    void* ptr1 = array1;
    void* ptr2 = &array1;

    printf("%x %x\n", ptr1, ptr2);
    cout << ptr1 << " " << ptr2 << endl;
    return 0;
}

【讨论】:

【解决方案3】:

好吧,我明白我的困惑了。在 C++ 中,&array 的类型与数组的类型不兼容,并且正如链接的讨论所指出的, (&array)+1 与 (array+1) 不同,但强制转换未下标的指针实际上会产生适当的结果。 C 中数组和指针之间的区别非常令人困惑。感谢您的帮助。

【讨论】:

  • 数组和第一个元素在内存中是对齐的,所以&amp;array&amp;array[0]是同一个地址,即使是不同的类型。棘手的部分是数组 decay 很容易变成指向第一个元素的指针(只要它们被用作右值),因此void *p = array; 被编译器处理为void *p = &amp;array[0],即数组衰减为指向第一个元素的指针——它属于包含的类型。类型上的差异是导致(void*)((&amp;array)+1) != (void*)(array + 1) 的原因(左侧是另一个衰减示例)
猜你喜欢
  • 1970-01-01
  • 2019-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多