ChatGPT解决这个技术问题 Extra ChatGPT

如何找到数组的长度?

有没有办法找到一个数组有多少个值?检测我是否已经到达数组的末尾也可以。

数组从何而来?通常采用数组的函数也采用长度参数来处理这个问题。
好吧,我正在制作一个“疯狂的库”程序,其中包含一个包含所有文本的数组,以及用户必须填写的名词/动词的位置。我想使用一个函数来运行整个数组,用用户输入的文本替换“[名词]”和“[动词]”值。
Computing length of array 的可能重复项
请注意,在 C 中,数组不是对象或结构。因此,默认情况下,它们在任何地方都没有存储长度参数。如果您想在 C++ 中将它们作为对象使用,请尽可能使用 C++ 对象 std::vector 或 C++11 的 std::array。如果您必须使用指针,请始终将数组的长度作为第二个参数传递给每个使用它的函数。
如果您使用的是 C++20,那么我也为此添加了答案。它很容易被错过,因为这里有很多答案。

D
Drew Dormann

如果您的意思是 C 风格的数组,那么您可以执行以下操作:

int a[7];
std::cout << "Length of array = " << (sizeof(a)/sizeof(*a)) << std::endl;

这不适用于指针(即它不适用于以下任何一种):

int *p = new int[7];
std::cout << "Length of array = " << (sizeof(p)/sizeof(*p)) << std::endl;

或者:

void func(int *p)
{
    std::cout << "Length of array = " << (sizeof(p)/sizeof(*p)) << std::endl;
}

int a[7];
func(a);

在 C++ 中,如果你想要这种行为,那么你应该使用容器类;可能std::vector


如果您将数组传递给不同的函数并尝试在那里执行它,它也不起作用:)
@San:在这种情况下创建一个 function template
@San Jacinto:不,无论您在哪个函数中,这都有效(在数组上)。但是,将可变长度的数组作为参数传递给函数是不可能的(它会衰减为指针)-但是如果您传递一个结构内的数组,然后按预期工作。
@OliverCharlesworth 如果您将数组按值传递给另一个函数并在那里尝试,它不会工作,对吧?问题是为什么
@A_Matar - 您不能在 C 或 C++ 中按值传递数组。
T
Toby Speight

正如其他人所说,您可以使用 sizeof(arr)/sizeof(*arr),但是对于不是数组的指针类型,这会给您错误的答案。

template<class T, size_t N>
constexpr size_t size(T (&)[N]) { return N; }

这具有无法为非数组类型编译的好特性(Visual Studio 有 _countof 可以做到这一点)。 constexpr 使它成为编译时表达式,因此它对宏没有任何缺点(至少我不知道)。

您还可以考虑使用 C++11 中的 std::array,它公开了它的长度,而不会超过原生 C 数组的开销。

C++17<iterator> 标头中有 std::size(),它的作用相同,也适用于 STL 容器(感谢 @Jon C)。


编译时出现两个错误(我什至没有尝试使用它):错误 C2265:'':对零大小数组的引用是非法错误 C2266:'':对非常量有界数组是非法的 有什么问题?
@yau 这就是您编写对数组的引用see this answer的方式。我的版本看起来有点不同,因为我省略了参数的名称,因为没有使用参数,只需要它的类型。如果有一个名称,它将是 T(arg&)[N]
谢谢莫蒂!遗漏的参数名称对我来说已经很清楚了。但令人难以置信的是,我以前从未使用过指向数组的引用/指针。并且将来可能不会,因为这样的阵列正在消亡得更多。
如果使用 C++11 不是 std::extent 更好的解决方案???? en.cppreference.com/w/cpp/types/extent
@IsaacPascual 我不熟悉 extent,现在看它有两个特性,使它不如上面的函数有用(对于这个用例)。 (1) 它为指针返回零(而不是编译错误)。 (2) 它需要一个类型参数,所以为了检查一个变量你必须做 decltype
T
Toby Speight

执行 sizeof myArray 将获得为该数组分配的总字节数。然后,您可以通过除以数组中一个元素的大小来找出数组中元素的数量:sizeof myArray[0]

所以,你会得到类似的东西:

size_t LengthOfArray = sizeof myArray / sizeof myArray[0];

由于 sizeof 产生 size_t,结果 LengthOfArray 也将属于这种类型。


这是一个非常简单易行的解决方案,可以克服似乎是一个古老的问题。
不适用于指针持有的 C++“新”数组。如果取消引用,您将获得指针的大小(4 个字节)或第一个元素的大小。
@DragonLord 是的,尽管任何使用关键字 new 声明数组大小的人都会在运行时知道数组的大小,因此在这种情况下无需使用 sizeof 运算符来查找数组的大小。我相信你知道这一点。这只是为了任何不这样做的人的利益。
@surega 它不会崩溃
A
Arnav Borborah

虽然这是一个老问题,但值得更新 C++17 的答案。在标准库中现在有模板函数 std::size(),它返回 std 容器或 C 样式数组中的元素数。例如:

#include <iterator>

uint32_t data[] = {10, 20, 30, 40};
auto dataSize = std::size(data);
// dataSize == 4

并且在 C++20 中,std::ssize() 将任何范围的 std::size() 获取为有符号整数,这对于避免在循环中包含恐怖、避免前者的冗长强制转换等很有用。
您应该注意,这不适用于传递给函数的数组,您需要在定义数组的块中执行此操作并将其作为附加参数传递给函数。
P
Prasoon Saurav

有没有办法找到一个数组有多少个值?

是的!

试试sizeof(array)/sizeof(array[0])

检测我是否已经到达数组的末尾也可以。

除非您的数组是字符数组(即字符串),否则我看不到任何方法。

PS:在 C++ 中总是使用 std::vector。有几个内置功能和扩展功能。


这不适用于可变的单个数组大小
向量+1。很少有强有力的案例可以再使用旧式 C++ 数组了。除非数组的大小永远不会改变,但即便如此,您也应该使用数组容器类。最好使用像vector这样的容器类来进行动态数组存储。使用容器类的优点远远超过必须管理自己的内存的缺点。
@MartynShutt当您受缓存限制时,例如在gamedev中,有时您无法负担使用向量。
如果一个数组有 0 个元素,那么 array[0] 合法吗?
@mercury0114 0 长度数组在 C++ 中是非法的。即使它们不是,您仍然可以对 array[0] 上的 sizeof 运算符求值,因为它实际上并不在运行时求值,只是在编译时查找它的类型以获取大小。
e
eq-

std::vector 有一个方法 size(),它返回向量中的元素数。

(是的,这是半开玩笑的回答)


可能是开玩笑,但几乎可以肯定这是正确的方法。
你为什么说它的舌头在脸颊?对我(一个 c++ 新手)来说,这似乎是正确的答案。
@dbliss 这是开玩笑的,因为 OP 询问了 array 的长度,并且 eq- 告诉他们如何获取 vector 的长度,这是一个不同的C++ 中的东西。但是,它在更深层次上是正确的,因为 if you need to get the length at run time, a vector is a much better choice
您还可以使用 std::list 或我相信的其他一些容器。
这个答案特别棒的是,您可以使用数组文字初始化向量或列表。
J
JukkaP
#include <iostream>

int main ()
{
    using namespace std;
    int arr[] = {2, 7, 1, 111};
    auto array_length = end(arr) - begin(arr);
    cout << "Length of array: " << array_length << endl;
}

我相信这仅适用于堆栈上的局部变量。
这是最好的答案。 @DragonLord,它也适用于成员变量。请参阅cpp.sh/92xvv
C
Community

从 C++11 开始,引入了一些新模板来帮助减少处理数组长度时的痛苦。它们都在标题 <type_traits> 中定义。

std::rank::value 如果 T 是数组类型,则提供等于数组维数的成员常量值。对于任何其他类型,值为 0。

std::extent::value 如果 T 是数组类型,则提供等于沿数组第 N 维的元素数的成员常量值,如果 N 在 [0, std::rank< T>::值)。对于任何其他类型,或者如果 T 是沿其第一个维度的未知边界数组并且 N 为 0,则值为 0。

std::remove_extent::type 如果 T 是某个 X 类型的数组,则提供等于 X 的成员 typedef type,否则 type 是 T。注意如果 T 是多维数组,则仅删除第一个维度。

std::remove_all_extents::type 如果 T 是某个类型 X 的多维数组,则提供等于 X 的成员 typedef type,否则 type 为 T。

要获得多维数组任意维度的长度,可以使用 decltypestd::extent 组合。例如:

#include <iostream>
#include <type_traits> // std::remove_extent std::remove_all_extents std::rank std::extent

template<class T, size_t N>
constexpr size_t length(T(&)[N]) { return N; }

template<class T, size_t N>
constexpr size_t length2(T(&arr)[N]) { return sizeof(arr) / sizeof(*arr); }

int main()
{
    int a[5][4][3]{{{1,2,3}, {4,5,6}}, { }, {{7,8,9}}};

    // New way
    constexpr auto l1 = std::extent<decltype(a)>::value;     // 5
    constexpr auto l2 = std::extent<decltype(a), 1>::value;  // 4
    constexpr auto l3 = std::extent<decltype(a), 2>::value;  // 3
    constexpr auto l4 = std::extent<decltype(a), 3>::value;  // 0

    // Mixed way
    constexpr auto la = length(a);
    //constexpr auto lpa = length(*a);  // compile error
    //auto lpa = length(*a);  // get at runtime
    std::remove_extent<decltype(a)>::type pa;  // get at compile time
    //std::remove_reference<decltype(*a)>::type pa;  // same as above
    constexpr auto lpa = length(pa);
    std::cout << la << ' ' << lpa << '\n';

    // Old way
    constexpr auto la2 = sizeof(a) / sizeof(*a);
    constexpr auto lpa2 = sizeof(*a) / sizeof(**a);
    std::cout << la2 << ' ' << lpa2 << '\n';

    return 0;
}

BTY,获取多维数组中的元素总数:

constexpr auto l = sizeof(a) / sizeof(std::remove_all_extents<decltype(a)>::type);

或者把它放在一个函数模板中:

#include <iostream>
#include <type_traits>
    

template<class T>
constexpr size_t len(T &a)
{
    return sizeof(a) / sizeof(typename std::remove_all_extents<T>::type);
}

int main()
{
    int a[5][4][3]{{{1,2,3}, {4,5,6}}, { }, {{7,8,9}}};
    constexpr auto ttt = len(a);
    int i;
    std::cout << ttt << ' ' << len(i) << '\n';
    
    return 0;
}

通过以下链接可以找到更多使用它们的示例。


g
gprathour

这是一个非常古老和传奇的问题,并且已经有许多惊人的答案。但随着时间的推移,语言中添加了新功能,因此我们需要根据可用的新功能不断更新内容。

我刚刚注意到有人还没有提到 C++20。所以想写答案。

C++20

在 C++20 中,标准库中添加了一种新的更好的方法来查找数组的长度,即 std:ssize()。此函数返回 signed value

#include <iostream>

int main() {
    int arr[] = {1, 2, 3};
    std::cout << std::ssize(arr);
    return 0;
}

C++17

在 C++17 中,有一个更好的方法(当时)用于 iterator 中定义的 std::size()

#include <iostream>
#include <iterator> // required for std::size

int main(){
    int arr[] = {1, 2, 3};
    std::cout << "Size is " << std::size(arr);
    return 0;
}

PS 此方法也适用于 vector

老的

许多其他答案中已经提到了这种传统方法。

#include <iostream>

int main() {
    int array[] = { 1, 2, 3 };
    std::cout << sizeof(array) / sizeof(array[0]);
    return 0;
}

仅供参考,如果您想知道为什么将数组传递给另一个函数时这种方法不起作用。原因是,

在 C++ 中,数组不是按值传递的,而是传递指向数组的指针。在某些情况下,传递整个数组可能是昂贵的操作。您可以通过将数组传递给某个函数并在那里对数组进行一些更改来测试这一点,然后再次在 main 中打印该数组。您将获得更新的结果。

正如您已经知道的那样,sizeof() 函数给出了字节数,因此在其他函数中它将返回分配给指针的字节数,而不是整个数组。所以这种方法行不通。

但我相信你可以根据你的要求找到一个好方法来做到这一点。

快乐编码。


m
metal

还有 TR1/C++11/C++17 方式(见 Live on Coliru):

const std::string s[3] = { "1"s, "2"s, "3"s };
constexpr auto n       = std::extent<   decltype(s) >::value; // From <type_traits>
constexpr auto n2      = std::extent_v< decltype(s) >;        // C++17 shorthand

const auto     a    = std::array{ "1"s, "2"s, "3"s };   // C++17 class template arg deduction -- http://en.cppreference.com/w/cpp/language/class_template_argument_deduction
constexpr auto size = std::tuple_size_v< decltype(a) >;

std::cout << n << " " << n2 << " " << size << "\n"; // Prints 3 3 3

N
NAND

而不是使用内置的数组函数又名:

 int x[3] = {0, 1, 2};

您应该使用数组类和数组模板。尝试:

#include <array>
array<type_of_the_array, number_of_elements_in_the_array> Name_of_Array = {};

所以现在如果你想找到数组的长度,你所要做的就是使用数组类中的 size 函数。

Name_of_Array.size();

并且应该返回数组中元素的长度。


C
Community

回答:

int number_of_elements = sizeof(array)/sizeof(array[0])

解释:

由于编译器为每种数据类型设置了特定大小的内存块,而数组只是这些数据的一组,您只需将数组的大小除以数据类型的大小即可。如果我有一个包含 30 个字符串的数组,我的系统会为数组的每个元素(字符串)留出 24 个字节。在 30 个元素中,总共 720 个字节。 720/24 == 30 个元素。小而紧凑的算法是:

int number_of_elements = sizeof(array)/sizeof(array[0]) 相当于

number_of_elements = 720/24

请注意,您不需要知道数组是什么数据类型,即使它是自定义数据类型。


2019 年不需要这种过时且容易出错的方法。stackoverflow.com/a/59109106/560648 而且这只是对现有答案的欺骗。
然而,它简单、雄辩、快速、低需求、独立于平台,并且不需要包含向量或指针。至于重复其他答案,似乎只有一个具有相同算法的其他答案,并且没有像我的答案那样解释问题的基本机制。我恭敬地建议,它不是容易出错,而是相当健壮。
T
Tarun Maganti

在 C++ 中,使用 std::array 类来声明一个数组,可以很容易地找到数组的大小以及最后一个元素。

#include<iostream>
#include<array>
int main()
{
    std::array<int,3> arr;

    //To find the size of the array
    std::cout<<arr.size()<<std::endl;

    //Accessing the last element
    auto it=arr.end();
    std::cout<<arr.back()<<"\t"<<arr[arr.size()-1]<<"\t"<<*(--it);

    return 0;
}

实际上,数组类还有很多其他功能,可以让我们使用数组作为标准容器。
Reference 1 to C++ std::array class
Reference 2 to std::array class
参考资料中的示例很有帮助。


好的;我看到你有很多技能;和......很好的方法。我认为自己也应该为这些著名问题写更多答案;-)
I
Ito

您有很多选项可用于获取 C 数组大小。

int myArray[] = {0, 1, 2, 3, 4, 5, 7};

1) sizeof(<array>) / sizeof(<type>):

std::cout << "Size:" << sizeof(myArray) / sizeof(int) << std::endl;

2) sizeof(<array>) / sizeof(*<array>):

std::cout << "Size:" << sizeof(myArray) / sizeof(*myArray) << std::endl;

3) sizeof(<array>) / sizeof(<array>[<element>]):

std::cout << "Size:" << sizeof(myArray) / sizeof(myArray[0]) << std::endl;

N
NAND

sizeof(array_name) 给出整个数组的大小,sizeof(int) 给出每个数组元素的数据类型的大小。

因此,将整个数组的大小除以数组的单个元素的大小就可以得到数组的长度。

 int array_name[] = {1, 2, 3, 4, 5, 6};
 int length = sizeof(array_name)/sizeof(int);

虽然此代码段可能会解决问题,但它没有解释为什么或如何回答问题。请包括对您的代码的解释,因为这确实有助于提高您的帖子的质量。请记住,您是在为将来的读者回答问题,而那些人可能不知道您的代码建议的原因
z
zangw

这是来自 Google ProtobufArraySize 的一种实现。

#define GOOGLE_ARRAYSIZE(a) \
  ((sizeof(a) / sizeof(*(a))) / static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))

// test codes...
char* ptr[] = { "you", "are", "here" };
int testarr[] = {1, 2, 3, 4};
cout << GOOGLE_ARRAYSIZE(testarr) << endl;
cout << GOOGLE_ARRAYSIZE(ptr) << endl;

ARRAYSIZE(arr) 通过检查 sizeof(arr)(数组中的字节数)和 sizeof(*(arr))(一个数组元素中的字节数)来工作。如果前者可以被后者整除,则可能 arr 确实是一个数组,在这种情况下,除法结果是数组中元素的#。否则, arr 不可能是数组,我们会生成编译器错误以阻止代码编译。由于 bool 的大小是实现定义的,我们需要将 !(sizeof(a) & sizeof(*(a))) 转换为 size_t 以确保最终结果具有 size_t 类型。这个宏并不完美,因为它错误地接受了某些指针,即指针大小可以被指针大小整除。由于我们所有的代码都必须通过一个 32 位编译器,其中一个指针是 4 个字节,这意味着所有指向大小为 3 或大于 4 的类型的指针都将被(正确地)拒绝。


使用如下整数数组:int nombres[5] = { 9, 3 }; 此函数返回 5 而不是 2
GOOGLE_ARRAYSIZE(new int8_t) 在我的测试环境中返回 8,而不是引发错误。铸造的部分似乎是多余的,更不用说尖叫的 C 宏了。 sizeof(a) / sizeof(*a) 作为传统解决方案已经足够了。
P
Przemek Marcinkiewicz

对于 C++/CX(例如在 Visual Studio 中使用 C++ 编写 UWP 应用程序时),我们可以通过简单地使用 size() 函数来查找数组中值的数量。

源代码:

string myArray[] = { "Example1", "Example2", "Example3", "Example4" };
int size_of_array=size(myArray);

如果您 cout size_of_array,输出将是:

>>> 4

D
Das_Newb

只是一个想法,但只是决定创建一个计数器变量并将数组大小存储在位置 [0] 中。我删除了函数中的大部分代码,但您会在退出循环后看到,prime[0] 被分配了最终值“a”。我尝试使用向量,但 VS Express 2013 不太喜欢。另请注意,“a”从 1 开始以避免覆盖 [0],并且在开始时对其进行初始化以避免错误。我不是专家,只是想分享一下。

int prime[] = {0};
int primes(int x, int y){
    using namespace std; int a = 1;
    for (int i = x; i <= y; i++){prime[a] = i; a++; }
    prime[0] = a; return 0;
}

M
Menelaos Kotsollaris

使用泛型的一个很好的解决方案:

template <typename T,unsigned S>
inline unsigned arraysize(const T (&v)[S]) { return S; }

然后只需调用 arraysize(_Array); 即可获取数组的长度。

Source


@bobbogo 与 inline 或 constexpr 一起使用,也许您关闭了 inline 或者它是可选的? ideone.com/VxogJ4
@QentinUK constexpr 是解决方法。 inline 不是。 constexpr 虽然很现代。您确定您的测试程序没有使用另一个现代功能,您可以在其中声明一个长度由变量给出的本地数组吗?尝试使用两个全局数组。
S
Scy

对于旧的 g++ 编译器,你可以这样做

template <class T, size_t N>
char (&helper(T (&)[N]))[N];

#define arraysize(array) (sizeof(helper(array)))

int main() {
    int a[10];
    std::cout << arraysize(a) << std::endl;
    return 0;
}

这是正确的答案。在 C++ 版本中非常可移植,不适用于指针,而且答案在编译时可用
R
Rezoanul Alam Riad

您可以通过以下方式找到数组的长度:

int  arr[] = {1, 2, 3, 4, 5, 6}; 
int size = *(&arr + 1) - arr; 
cout << "Number of elements in arr[] is "<< size; 
return 0;

简化为 (&arr)[1] - arr;
A
Amado Saladino

只需您可以使用此代码段:

#include <iostream>
#include <string>
#include <array>

using namespace std;

int main()
{

  array<int,3> values;
  cout << "No. elements in valuea array: " << values.size() << " elements." << endl;
  cout << "sizeof(myints): " << sizeof(values) << endl;

}

这是参考:http://www.cplusplus.com/reference/array/array/size/


S
Success Infotech

您可以使用用于相同目的的 sizeof() 运算符。

请参阅下面的示例代码

#include <iostream>
using namespace std;
int main() {
  int arr[] = {10,20,30,40,50,60};
  int arrSize = sizeof(arr)/sizeof(arr[0]);
  cout << "The size of the array is: " << arrSize;
  return 0;
}

J
Johan Jönsson

避免将 type 与 sizeof 一起使用,因为 sizeof(array)/sizeof(char) 如果更改数组的类型会突然损坏。

在 Visual Studio 中,您有等效的 if sizeof(array)/sizeof(*array)。您只需输入 _countof(array)


C
Chen Li

我在这里提供了一个棘手的解决方案:

您始终可以将 length 存储在第一个元素中:

// malloc/new

arr[0] = length;
arr++;

// do anything. 
int len = *(arr-1);

free(--arr); 

代价是调用 free 时必须 --arr


仅当 arr 的类型与 int 兼容并且数组不超过该类型的最大值时才有效。例如,Pascal 字符串实际上是使用此技巧的字节数组; Pascal 中字符串的最大长度为 255 个字符。
我想可以在每个数组的开头保留 8 个字节,如果他们想存储对象,可以使用 unsigned long。我认为向量可能更容易。但对于嵌入式系统来说绝对是一个很好的解决方案。
b
bobbogo

您最终会寻找它的最常见原因之一是因为您想将数组传递给函数,而不必为它的大小传递另一个参数。您通常还希望数组大小是动态的。该数组可能包含对象,而不是基元,并且对象可能很复杂,因此 size_of() 不是计算计数的安全选项。

正如其他人所建议的那样,考虑使用 std::vector 或列表等代替原始数组。然而,在旧的编译器上,您仍然无法通过简单的方式获得您可能想要的最终解决方案,因为填充容器需要一堆丑陋的 push_back() 行。如果您像我一样,想要一个涉及匿名对象的单行解决方案。

如果您使用 STL 容器替代原始数组,则此 SO 帖子可能对您有用,以了解初始化它的方法:What is the easiest way to initialize a std::vector with hardcoded elements?

这是我为此使用的一种方法,它将在编译器和平台上通用:

为您的对象集合创建一个结构或类作为容器。为 << 定义一个运算符重载函数。

class MyObject;

struct MyObjectList
{
    std::list<MyObject> objects;
    MyObjectList& operator<<( const MyObject o )
    { 
        objects.push_back( o );
        return *this; 
    }
};

您可以创建将您的结构作为参数的函数,例如:

someFunc( MyObjectList &objects );

然后,您可以调用该函数,如下所示:

someFunc( MyObjectList() << MyObject(1) <<  MyObject(2) <<  MyObject(3) );

这样,您可以在一条干净的行中构建动态大小的对象集合并将其传递给函数!


V
Vaibhav Vishal Singh

我认为这会起作用:

for(int i=0;array[i];i++)
{
 //do_something
}  

4
4ukh

干得好:

#include <iostream>
using namespace std;

int main() {
 int arr[] = {10,20,30,40,50,60};
 int arrSize = sizeof(arr)/sizeof(arr[0]);
 cout << "The size of the array is: " << arrSize;
return 0;
}

该解决方案与公认的答案几乎相同。如果您认为需要修改,请添加评论。
R
Raymond Iacobacci

我个人建议(如果您出于某种原因无法使用专用函数)首先将数组类型兼容性扩展到您通常使用它的范围之外(如果您存储的值≥0:

unsigned int x[] -> int x[]

比你使数组 1 元素比你需要的大。对于最后一个元素,您将放置一些包含在扩展类型说明符中但您通常不会使用的类型,例如使用前面的示例,最后一个元素将是-1。这使您能够(通过使用 for 循环)找到数组的最后一个元素。


m
miksiii

假设您在页面顶部声明了一个全局数组

int global[] = { 1, 2, 3, 4 };

要找出数组中有多少元素(在 C++ 中),请键入以下代码:

sizeof(global) / 4;

sizeof(NAME_OF_ARRAY) / 4 将返回给定数组名称的元素数。


sizeof(int) 取决于平台。不能保证它会是 4(尽管这是最常见的情况)
比你补充。
神奇的数字!!