选择一个元素数组而不是一个对象的原因是什么?

Reason for choosing an array of one element instead of one object?

我想知道是否有理由使用由一个元素对象组成的数组,而不是只使用一个对象。

喜欢,f.e。

int a[1] = {10};

而不仅仅是

int a = 10;

当然这两种情况在后面的代码中访问10的值的上下文是有很大区别的,通过使用a

  1. a声明为数组时,如
int a[1] = {10};

a 衰减为指向 a 数组的第一个元素对象的指针,因此 a 计算为类型 int*,当 a后面程序会用到。

  1. a声明为某个对象的标识符时,如
int a = 10;

a 属于 int.

类型

如果我们想将 10 的值传递给一个函数,我们必须注意这一点并且 必须 区分这两种用法。

但这并没有回答我为什么使用一种方式而不是另一种方式的问题。


使用 C 和 C++ 标记的原因:我使用两种语言标记对其进行标记,因为这两种语句在 C 和 C++ 中均有效,而在实际情况下,我不知道两种语言之间有什么区别.如有差异,敬请谅解。

感谢您的帮助。

您不应声明由一个对象组成的数组。如果您需要单个变量,则将其声明为这样。但是要回答你的问题,你会想写这样的东西:

int a[1];

可能是为了方便使用以指针作为参数的函数。以函数 memset() 声明为:

为例
void * memset (void *ptr, int value, size_t num );

如果您声明了一个变量并想在其上使用 memset(),您必须将其命名为:

int a;
memset(&a, val, sizeof(int));

而如果您将 a 声明为 int a[1],那么您会称它为:

memset(a, val, sizeof(int));

然而,前者用于做一些奇怪或不寻常的事情!

Are there any places in C and/or C++, where an array is needed instead of just one object?

我想你大多会遇到一个 C 风格的数组,其中一个对象作为一个对象上的递归函数的最终情况。如果您有一个以类似 C 的方式接受数组的函数 (f(int* array, int length)),您可以使用它仅将函数应用于一个输入,而无需提供另一个重载。但是你可以用 int a = 42; f(&a, 1);.

做同样的事情

Is there are physical difference in the size of the allocation in memory?

没有。 int a[1] = {42}int a = 42 对堆栈执行完全相同的操作。

Do C and C++ differ in this context?

没有。

Why do I use an array of one element instead of just one object?

编译时大小为 1 的数组(就像您在上面所做的那样)可能很少使用。有区别

int a[1] = {42};
// and
int b = 42;
int *a = &b;

因为数组不是指针,而只是衰减到一个。但是 使用 它们的差别很小。使用它们的最显着区别(thx @Scheff)应该是您可以在 int a[1] 上使用 std::begin(a)std::end(a),但不能在 int *a 上使用。这只是 C++ 中的一个区别。请注意,一旦数组衰减为指针,它就会消失。然后分别用 aa+1 替换它们。

我可以想象,如果想在堆栈上初始化一个对象并直接有一个指向它的指针(而不是真正使用该值本身),那会做 int a[1] = {42};,因为它有点更短。但我自己从未见过,我实际上会认为这是糟糕的风格。我认为这在 C++ 代码中并不常见,因为原始指针本身并不常见。

我其实更经常看到长度为0的数组,用法见here。由于那些 在旧版本的 C 中在技术上似乎是非法的,在 C 中是无效的(thx for the comments),可以使用长度为 1 的数组来合法。但据我所知,大多数编译器几乎永远都实现了 0 长度数组,因此大多数人可能会忽略它并使用 0 长度数组。

没有理由使用 int a[1]; 而不是 int a;。在需要时使用 &a 将指针传递给它。如果您编写它,其他人会对 int a[1]; 感到非常困惑 - 它看起来像一个错误。

那么您可能会问为什么在语言中甚至需要它?

这很简单。假设您想要一个大小为 N 的固定数组,例如 int a[N]; 而您不知道 N 的值。这可以是宏、constexpr 计算的结果或模板的参数。因此 int a[1] 需要支持才能工作。

Are there any places in C and/or C++, where an array is needed instead of just one object?

Why do I use an array of one element instead of just one object?

有许多函数可以处理数组,它们接受一个指针参数。但是,正如 machine_1 已经指出的那样,您可以轻松获取指向常规 object 的指针并将其传递给函数。

但在某些情况下它确实有所作为。在 C++ 中,如果您想使用 range-for 来迭代多个 object,您可以这样写:

int a[1] = {42};
for (auto &value: a)
     ...

但是你不能写:

int a = 42;
for (auto &value: a)
     ...

上面的例子本身看起来很傻,但是当你使用模板定义泛型函数时,它就会成为一个真正的问题。所以有时候你想在长度为 1 的数组中存储一个值,只是为了更容易使用这些函数。

在C99及以后的版本中,但在C++中不行,你也可以使用flexible array members。这些成员像数组一样工作,但它们不占用 space,就好像它们的长度为零一样。考虑有一个带有 header 和可变数据量的网络数据包。表示数据包的结构可能如下所示:

struct packet {
    address_t source;
    address_t destination;
    size_t length;
    char data[]; // flexible array member
};

可以像这样为这样的结构分配内存:

size_t data_length;
...
struct packet *pkt = malloc(sizeof(*pkt) + data_length);

然后可以像这样读写数据部分:

for (size_t i = 0; i < data_length; i++)
     pkt->data[i] = ...;

这里不需要 data[] 数组,因为您也可以通过 ((char *)pkt + sizeof(*pkt))[i] 之类的方式访问数据,在结构末尾使用数组成员可以编写更多内容紧凑、可读且安全的代码。

可以使用长度为 1 的数组来完成 similar trick in C++

Is there are physical difference in the size of the allocation in memory?

没有

Do C and C++ differ in this context?

没有

有时为常见情况编写的函数意味着采用数组,例如在 C 中,您可能有类似的东西:

#define CULL_OBJECTS(objs) {\ 
           for(int i = 0; i < sizeof(objs)/sizeof(objs[0]); ++i)\ 
           {\ 
                ++culled_objects;\ 
                cull_subobjects(objs[i]);\ 
           }\

或者在 C++ 中:

template<typename T>
void CullObjects(T& objs)
{
    for(int i = 0; i < sizeof(objs)/sizeof(objs[0]); ++i)
    {
        ++culled_objects;
        cull_subobjects(objs[i]);
    }
}

可以通过传递 Obj objArr[1000]Obj obj[1] 来调用。

在我看来,为一个对象声明一个数组是没有意义的。我强烈建议使用基本的:a = 10 ;