C的常见数组长度宏?

Mat*_*ner 32 c c++ arrays c-preprocessor

我已经看到了几个浮动数组长度的宏:

这个问题:

  • #define length(array) (sizeof(array)/sizeof(*(array)))
  • #define ARRAY_LENGTH(array) (sizeof((array))/sizeof((array)[0]))
  • #define SIZE(array, type) (sizeof(array) / (sizeof(type))

和Visual Studio的_countof:

#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
Run Code Online (Sandbox Code Playgroud)

我想知道的是:

  1. 那些使用array[0]和有*array什么区别?
  2. 为什么要首选?
  3. 它们在C++方面有区别吗?

Mic*_*urr 63

这是一个更好的C版本(来自Google的Chromium项目):

#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
Run Code Online (Sandbox Code Playgroud)

它通过使用改进了array[0]*array版本0[array],这相当于array[0]普通数组,但如果array碰巧是重载的C++类型,则无法编译operator[]().

对于许多(但不是全部)指针作为array参数传递的情况,除法会导致除零操作(应该在编译时捕获,因为它是编译时常量表达式).

请参阅C中是否存在可返回数组长度的标准函数?更多细节.

C++代码有更好的选择.有关详细信息,请参阅编译时使用sizeof_array而不使用宏.

  • 为了防止在C++中被错误地使用,这是非常神秘的,考虑到C++中应该使用其他东西. (11认同)
  • 你是对的,这不应该在 C++ 中使用,但是专门为 C++ 提供一些安全性的位并不是真的太神秘(这只是不寻常的索引)。真正神秘的部分可以防止 C 中某些类型的误用,这实际上很难防范(并且宏甚至不能完美地防止这种误用)。它所防止的误用(传递指针而不是数组参数)经常发生,因此复杂性是值得的。包裹在一个宏中,复杂性并不是太大的问题(而且这个宏比我遇到的许多宏更不神秘)。 (2认同)
  • @Matt:`[]`运算符是可交换的(由于它是根据指针运算定义的).然而宏观的那部分是不那么重要的"安全" - 我很抱歉它似乎得到了关注. (2认同)

Che*_*Alf 15

  1. 使用array [0]和*array的那些有什么区别?
  2. 为什么要首选?
  3. 它们在C++方面有区别吗?

(1)C没有区别C++中的实际原始数组没有区别.

(2)没有技术理由偏好一个或另一个,但新手可能会被指针解除引用混淆.

(3)在C++中,你通常不会使用宏,因为它非常不安全.如果传入指针而不是实际的原始数组,代码将编译但产生不正确的结果.所以在C++中你应该/应该使用函数模板,比如...

#include <stddef.h>

typedef ptrdiff_t Size;

template< class Type, Size n >
Size countOf( Type (&)[n] ) { return n; }
Run Code Online (Sandbox Code Playgroud)

这只接受实际的原始数组作为参数.

它是三个函数的一部分startOf,endOf并且countOf定义非常方便,以便它们可以应用于原始数组和标准库容器.据我所知,这个三合会最初是由Dietmar Kuehl确定的.在C++ 0x中startOf,endOf很可能是std::beginstd::end.

干杯&hth.,

  • +1:有趣!是否有理由使用`<stddef.h>`而不是`<cstddef>`? (2认同)