ฉันจะหาความยาวของอาร์เรย์ได้อย่างไร


539

มีวิธีการค้นหาว่ามีหลายค่าอาร์เรย์? การตรวจสอบว่าฉันไปถึงจุดสิ้นสุดของอาร์เรย์หรือไม่


22
อาร์เรย์มาจากไหน โดยทั่วไปฟังก์ชั่นที่ใช้อาร์เรย์ยังใช้พารามิเตอร์ความยาวเพื่อจัดการกับปัญหานี้
Michael Myers

2
ฉันกำลังสร้างโปรแกรม "libs บ้า" ที่มีอาเรย์พร้อมข้อความทั้งหมดรวมถึงตำแหน่งของคำนาม / คำกริยาที่ผู้ใช้ต้องกรอกฉันต้องการใช้ฟังก์ชั่นเพื่อเรียกใช้ผ่าน ทั้งอาร์เรย์แทนที่ค่า "[คำนาม]" และ "[คำกริยา]" ด้วยข้อความที่ป้อนโดยผู้ใช้
Maxpm

ความเป็นไปได้ที่ซ้ำกันของการคำนวณความยาวของอาเรย์
Maxpm

5
โปรดทราบว่าในอาร์เรย์ C ไม่ใช่วัตถุหรือโครงสร้าง เช่นนี้พวกเขาไม่มีพารามิเตอร์ความยาวที่จัดเก็บไว้ที่ใดก็ได้โดยค่าเริ่มต้น หากคุณต้องการทำงานกับพวกมันเป็นวัตถุใน C ++ ให้ใช้วัตถุ C ++ std :: vector หรือ std :: array ของ C ++ 11 ถ้าทำได้ หากคุณต้องใช้พอยน์เตอร์ให้ส่งค่าความยาวของอาเรย์เป็นพารามิเตอร์ตัวที่สองให้กับทุกฟังก์ชั่นที่ใช้งานได้
Pihhan

หากคุณใช้ C ++ 20 แสดงว่าฉันได้เพิ่มคำตอบสำหรับสิ่งนั้นด้วย อาจพลาดได้ง่ายเนื่องจากมีคำตอบมากมายที่นี่
gprathour

คำตอบ:


511

ถ้าคุณหมายถึงอาเรย์แบบ 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 ++ ถ้าคุณต้องการพฤติกรรมแบบนี้คุณควรใช้คลาส container std::vectorอาจ


86
นอกจากนี้ยังไม่ทำงานถ้าคุณผ่านอาร์เรย์ไปยังฟังก์ชั่นที่แตกต่างกันและพยายามที่จะทำมันมี :)
San Jacinto

23
@San Jacinto: ไม่มันใช้งานได้ (ในอาร์เรย์ ) ไม่ว่าคุณจะใช้ฟังก์ชั่นใดการส่งผ่านอาร์เรย์ของความยาวตัวแปรไปยังฟังก์ชั่นเป็นพารามิเตอร์อย่างไรก็ตามเป็นไปไม่ได้ (จะสลายตัวเป็นพอยน์เตอร์) - อาร์เรย์ภายใน struct จากนั้นจะทำงานตามที่คาดไว้
eq-

1
@OliverCharlesworth ถ้าคุณผ่านอาร์เรย์ด้วยค่าไปยังฟังก์ชันอื่นและลองใช้ที่นั่นมันจะไม่ทำงานใช่ไหม? คำถามคือเหตุผล
A_Matar

5
@A_Matar - คุณไม่สามารถผ่านอาร์เรย์ตามค่าใน C หรือ C ++
Oliver Charlesworth

1
@yusha - พวกมันเหมือนกัน
Oliver Charlesworth

142

อย่างที่คนอื่นพูดว่าคุณสามารถใช้sizeof(arr)/sizeof(*arr)แต่สิ่งนี้จะให้คำตอบที่ผิดสำหรับประเภทตัวชี้ที่ไม่ใช่อาร์เรย์

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

นี่คือคุณสมบัติที่ดีของความล้มเหลวในการรวบรวมสำหรับประเภทอาเรย์ที่ไม่ (Visual Studio มี_countofซึ่งทำเช่นนี้) การconstexprทำนี้เป็นการแสดงออกของเวลาคอมไพล์ดังนั้นจึงไม่มีข้อเสียเหนือมาโคร (อย่างน้อยก็ไม่มีใครรู้)

นอกจากนี้คุณยังสามารถพิจารณาใช้std::arrayจาก C ++ 11 ซึ่งแสดงความยาวโดยไม่มีโอเวอร์เฮดเหนืออาร์เรย์ C ดั้งเดิม

C ++ 17มีstd::size()อยู่ใน<iterator>ส่วนหัวซึ่งไม่เหมือนกันและการทำงานสำหรับบรรจุ STL เกินไป (ขอบคุณ@ จอน C )


3
@yau มันเป็นวิธีที่คุณเขียนการอ้างอิงไปยังอาร์เรย์ , ดูคำตอบนี้ เวอร์ชันของฉันดูแตกต่างไปเล็กน้อยเนื่องจากฉันไม่ได้ใช้ชื่อพารามิเตอร์เนื่องจากไม่ได้ใช้พารามิเตอร์จึงจำเป็นต้องใช้ประเภทเท่านั้น T(arg&)[N]ที่มีชื่อมันจะเป็น
Motti

1
ขอบคุณ Motti! ชื่อพารามิเตอร์ด้านซ้ายไม่เห็นชัดเจนสำหรับฉัน แต่ไม่น่าเชื่อว่าฉันไม่เคยใช้refs / pointersมาก่อน และอาจจะไม่เกิดขึ้นอีกในอนาคตเนื่องจากอาร์เรย์ดังกล่าวกำลังจะตายไปมากกว่านี้
เหยา


1
ถ้าใช้ C ++ 11 ไม่ใช่ std :: scope ทางออกที่ดีกว่า ???? en.cppreference.com/w/cpp/types/extent
Isaac Pascual

2
@IacacPascual ฉันไม่คุ้นเคยกับการextentดูมันตอนนี้มีสองลักษณะที่ทำให้มีประโยชน์น้อยกว่าฟังก์ชั่นด้านบน (สำหรับ usecase นี้) (1) มันคืนค่าศูนย์สำหรับพอยน์เตอร์ (แทนที่จะเป็นข้อผิดพลาดในการคอมไพล์) (2) มันต้องมีพารามิเตอร์ชนิดดังนั้นเพื่อที่จะตรวจสอบตัวแปรที่คุณจะต้องทำdecltype
Motti

86

การทำเช่นนี้sizeof( myArray )จะทำให้คุณได้รับจำนวนไบต์ทั้งหมดที่จัดสรรให้กับอาร์เรย์นั้น จากนั้นคุณสามารถค้นหาจำนวนองค์ประกอบในอาร์เรย์โดยหารด้วยขนาดขององค์ประกอบหนึ่งในอาร์เรย์:sizeof( myArray[0] )


3
นี่เป็นวิธีที่ง่ายและสะดวกในการเอาชนะสิ่งที่ดูเหมือนจะเป็นปัญหาเก่า

4
ไม่ทำงานสำหรับอาร์เรย์ C ++ "ใหม่" ที่ถือโดยตัวชี้ คุณได้รับขนาดของตัวชี้ (4 ไบต์) หรือขนาดขององค์ประกอบแรกถ้าคุณตรวจสอบมัน
DragonLord

1
@DragonLord ใช่แม้ว่าใครก็ตามที่ประกาศขนาดของอาเรย์โดยใช้คีย์เวิร์ด new จะรู้ขนาดของอาเรย์ตอนรันไทม์อยู่แล้วดังนั้นไม่จำเป็นต้องใช้ตัวดำเนินการ sizeof เพื่อหาขนาดของอาเรย์ในกรณีนั้น ฉันแน่ใจว่าคุณรู้ นี่เป็นเพียงเพื่อประโยชน์ของทุกคนที่ไม่ได้
Martyn Shutt

@surega มันจะไม่ผิดพลาด
CITBL

60

แม้ว่านี่จะเป็นคำถามเก่า แต่ก็ควรปรับปรุงคำตอบของ C ++ 17 ในไลบรารีมาตรฐานขณะนี้มีฟังก์ชัน templated std::size()ซึ่งส่งคืนจำนวนองค์ประกอบในทั้งคอนเทนเนอร์ std หรืออาร์เรย์สไตล์ C ตัวอย่างเช่น:

#include <iterator>

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

58

มีวิธีการค้นหาว่ามีหลายค่าอาร์เรย์?

ใช่

ลอง sizeof(array)/sizeof(array[0])

การตรวจสอบว่าฉันไปถึงจุดสิ้นสุดของอาร์เรย์หรือไม่

ฉันไม่เห็นวิธีการนี้นอกจากอาร์เรย์ของคุณจะเป็นอาร์เรย์ของอักขระ (เช่นสตริง)

PS: ใน C ++ std::vectorใช้งานเสมอ มีฟังก์ชั่นหลายอย่างในตัวและฟังก์ชั่นเสริม


สิ่งนี้จะไม่ทำงานสำหรับขนาดอาเรย์แต่ละตัวแปร
Don Larynx

4
+1 สำหรับเวกเตอร์ มีกรณีที่แข็งแกร่งน้อยมากที่จะใช้อาร์เรย์ C ++ แบบเก่าอีกต่อไป เว้นแต่ขนาดของอาเรย์จะไม่เปลี่ยนแปลง แต่คุณควรใช้คลาสคอนเทนเนอร์อาเรย์แทน จะดีกว่าถ้าใช้คลาส container เช่น vector สำหรับหน่วยเก็บข้อมูลอาร์เรย์แบบไดนามิก ข้อดีของการใช้คลาสของคอนเทนเนอร์นั้นมีมากกว่าข้อเสียของการจัดการหน่วยความจำของคุณเอง
Martyn Shutt

@MartynShutt เมื่อคุณถูกแคชเช่นใน gamedev คุณไม่สามารถใช้เวกเตอร์ได้ในบางครั้ง
ธารา

30

std::vectorมีวิธีการsize()ที่ส่งกลับจำนวนองค์ประกอบในเวกเตอร์

(ใช่นี่เป็นคำตอบแบบลิ้น - แก้ม)


10
ลิ้นในแก้มอาจเป็นไปได้ แต่มันก็เป็นแนวทางที่ถูกต้อง
Jerry Coffin

ทำไมคุณถึงพูดว่าแก้มเป็นลิ้น สำหรับฉัน (มือใหม่ c ++) ดูเหมือนว่าเป็นคำตอบที่ถูกต้อง
dbliss

6
@dbliss มันใช้ลิ้นเป็นแก้มเพราะ OP ถามเกี่ยวกับความยาวของอาร์เรย์และ eq- บอกพวกเขาถึงวิธีรับความยาวของเวกเตอร์ซึ่งเป็นสิ่งที่แตกต่างใน C ++ อย่างไรก็ตามมันถูกต้องในระดับที่ลึกกว่าเพราะถ้าคุณต้องการระยะเวลาในการรันเวกเตอร์เป็นตัวเลือกที่ดีกว่ามาก
poolie

คุณสามารถใช้ std :: list หรือคอนเทนเนอร์อื่นที่ฉันเชื่อ
BuvinJ

1
สิ่งที่ยอดเยี่ยมเกี่ยวกับคำตอบนี้คือคุณสามารถเริ่มต้นเวกเตอร์หรือรายการด้วยตัวอักษรอาร์เรย์
BuvinJ

26
#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;
}

10
ฉันเชื่อว่าอันนี้ใช้งานได้กับตัวแปรท้องถิ่นที่อยู่ในสแต็กเท่านั้น
DragonLord

นี่คือคำตอบที่ดีที่สุด @DragonLord ก็ใช้ได้กับสมาชิก vars เช่นกัน ดูcpp.sh/92xvv
Shital Shah

24

ตั้งแต่ C ++ 11 เป็นต้นมาเทมเพลตใหม่บางตัวจะช่วยลดความเจ็บปวดเมื่อต้องเผชิญกับความยาวของอาเรย์ <type_traits>ทั้งหมดของพวกเขาจะมีการกำหนดในส่วนหัว

  • std::rank<T>::value

    ถ้าTเป็นประเภทอาร์เรย์ให้ค่าคงที่สมาชิกเท่ากับจำนวนมิติของอาร์เรย์ สำหรับประเภทอื่น ๆ ค่าเป็น 0

  • std::extent<T, N>::value

    หากTเป็นประเภทอาร์เรย์ให้ค่าคงที่สมาชิกเท่ากับจำนวนองค์ประกอบตามNมิติที่สามของอาร์เรย์ถ้าNอยู่ใน [0, std::rank<T>::value) สำหรับประเภทอื่น ๆ หรือถ้าTเป็นอาร์เรย์ที่ไม่ทราบขอบเขตตามมิติแรกและNเป็น 0 ค่าคือ 0

  • std::remove_extent<T>::type

    ถ้าTเป็นอาร์เรย์บางประเภทXให้สมาชิก typedef พิมพ์เท่ากับมิฉะนั้นประเภทคือX Tโปรดทราบว่าหากTเป็นอาร์เรย์หลายมิติจะมีการลบเฉพาะมิติแรกเท่านั้น

  • std::remove_all_extents<T>::type

    ถ้าTเป็นอาร์เรย์หลายมิติบางประเภทXให้สมาชิก typedef พิมพ์เท่ากับชนิดอย่างอื่นคือXT

เพื่อให้ได้ความยาวในมิติของอาร์เรย์ multidimential ใด ๆสามารถนำมาใช้รวมกับdecltype std::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;
}

ตัวอย่างเพิ่มเติมของวิธีการใช้พวกเขาสามารถพบได้โดยไปที่ลิงค์


18

นอกจากนี้ยังมี 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

9

แทนที่จะใช้ฟังก์ชันอาเรย์ในตัว:

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

คุณควรใช้คลาสอาเรย์และเทมเพลตอาร์เรย์ ลอง:

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

ดังนั้นหากคุณต้องการหาความยาวของอาเรย์สิ่งที่คุณต้องทำคือการใช้ฟังก์ชั่นขนาดในคลาสอาเรย์

Name_of_Array.size();

และนั่นควรคืนความยาวขององค์ประกอบในอาร์เรย์


6

ใน 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;
}

ในความเป็นจริงคลาสอาเรย์มีฟังก์ชั่นอื่น ๆ อีกมากมายที่ให้เราใช้อาเรย์คอนเทนเนอร์มาตรฐาน
การอ้างอิง 1 ถึง C ++ std :: array class
อ้างอิง 2 ถึง std :: array class
ตัวอย่างในการอ้างอิงมีประโยชน์


2
นีซ; ฉันเห็นคุณมีทักษะมากมาย และ ... แนวทางที่ดี ฉันคิดว่าควรเขียนคำตอบสำหรับคำถามที่มีชื่อเสียงเช่นนี้ด้วยเช่นกัน ;-)
GhostCat

5

นี่เป็นคำถามที่ค่อนข้างเก่าและเป็นตำนานและมีคำตอบที่น่าอัศจรรย์อยู่มากมาย แต่เมื่อเวลาผ่านไปมีฟังก์ชั่นใหม่ที่ถูกเพิ่มเข้าไปในภาษาดังนั้นเราจึงจำเป็นต้องปรับปรุงสิ่งต่าง ๆ ตามคุณสมบัติใหม่ที่มีให้

ฉันเพิ่งสังเกตเห็นว่าไม่มีใครพูดถึง 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 มีวิธีที่ดีกว่า (ในเวลานั้น) สำหรับเดียวกันซึ่งเป็นที่ที่กำหนดไว้ในstd::size()iterator

#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;
}

เพียง FYI ถ้าคุณสงสัยว่าทำไมวิธีนี้ไม่ทำงานเมื่ออาร์เรย์ถูกส่งไปยังฟังก์ชั่นอื่น เหตุผลคือ,

อาร์เรย์ไม่ได้ถูกส่งผ่านโดยค่าใน C ++ แทนการส่งตัวชี้ไปยังอาร์เรย์ ในบางกรณีที่ผ่านอาร์เรย์ทั้งหมดอาจเป็นการดำเนินการที่มีราคาแพง คุณสามารถทดสอบสิ่งนี้ได้โดยส่งผ่านอาเรย์ไปยังฟังก์ชั่นบางอย่างและทำการเปลี่ยนแปลงบางอย่างในอาเรย์แล้วพิมพ์อาเรย์เป็นหลักอีกครั้ง คุณจะได้รับผลลัพธ์ที่อัปเดต

และอย่างที่คุณรู้อยู่แล้วsizeof()ฟังก์ชั่นนี้ให้จำนวนไบต์ดังนั้นในฟังก์ชั่นอื่นมันจะคืนค่าจำนวนไบต์ที่จัดสรรให้กับตัวชี้แทนที่จะเป็นทั้งอาร์เรย์ ดังนั้นวิธีนี้ใช้ไม่ได้ผล

แต่ฉันแน่ใจว่าคุณสามารถหาวิธีที่ดีในการทำเช่นนี้ตามความต้องการของคุณ

Happy Coding


4

คุณมีตัวเลือกมากมายที่จะใช้ในการรับขนาดอาร์เรย์ 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;

3

นี่คือหนึ่งในการดำเนินการArraySizeจากGoogle Protobuf

#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 อาจไม่สามารถเป็นอาร์เรย์ได้และเราสร้างข้อผิดพลาดคอมไพเลอร์เพื่อป้องกันไม่ให้โค้ดรวบรวม

เนื่องจากขนาดของบูลถูกกำหนดโดยการนำไปปฏิบัติเราจึงต้องส่ง! (sizeof (a) & sizeof (* (a))) เป็น size_t เพื่อให้แน่ใจว่าผลลัพธ์สุดท้ายจะมีประเภท size_t

มาโครนี้ไม่สมบูรณ์แบบเนื่องจากยอมรับพอยน์เตอร์ที่ไม่ถูกต้องโดยที่ขนาดพอยน์เตอร์หารด้วยขนาดพอยต์ เนื่องจากโค้ดทั้งหมดของเราต้องผ่านคอมไพเลอร์ 32 บิตโดยที่ตัวชี้คือ 4 ไบต์นี่หมายความว่าพอยน์เตอร์ทั้งหมดเป็นประเภทที่มีขนาด 3 หรือมากกว่า 4 จะถูกปฏิเสธ (อย่างถูกต้อง)


กับอาร์เรย์ของจำนวนเต็มเช่นต่อไปนี้: int nombres[5] = { 9, 3 };ฟังก์ชั่นนี้ส่งกลับแทน5 2
อันวาร์

GOOGLE_ARRAYSIZE(new int8_t)คืนค่า8env การทดสอบของฉันแทนที่จะเพิ่มข้อผิดพลาด ส่วนที่หล่อดูเหมือนซ้ำซ้อนไม่เอ่ยถึงมาโคร C ที่กรีดร้อง sizeof(a) / sizeof(*a)ทำงานได้ดีพอ ๆ กับวิธีแก้ปัญหาแบบเดิม

3

สำหรับ C ++ / CX (เมื่อเขียนเช่นแอพ UWP โดยใช้ C ++ ใน Visual Studio) เราสามารถหาจำนวนค่าในอาร์เรย์ได้โดยใช้size()ฟังก์ชั่น

รหัสแหล่งที่มา:

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

หากคุณการส่งออกจะได้รับ:coutsize_of_array

>>> 4

3

sizeof(array_name)ให้ขนาดของทั้งอาร์เรย์และsizeof(int)ให้ขนาดของชนิดข้อมูลของทุกองค์ประกอบของอาร์เรย์

ดังนั้นการหารขนาดของอาร์เรย์ทั้งหมดด้วยขนาดขององค์ประกอบเดียวของอาร์เรย์จึงให้ความยาวของอาร์เรย์

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

แม้ว่าข้อมูลโค้ดนี้อาจช่วยแก้ปัญหาได้ แต่ก็ไม่ได้อธิบายว่าทำไมหรือตอบคำถามอย่างไร โปรดระบุคำอธิบายสำหรับรหัสของคุณเนื่องจากช่วยปรับปรุงคุณภาพการโพสต์ของคุณได้อย่างแท้จริง จำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตและผู้คนเหล่านั้นอาจไม่ทราบสาเหตุของการแนะนำรหัสของคุณ
Balagurunathan Marimuthu

3

คำตอบ :

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นอกจากนี้ยังเป็นเพียงคำตอบที่มีอยู่
การแข่งขัน Lightness ใน Orbit

อย่างไรก็ตามมันเป็นแพลตฟอร์มที่เรียบง่ายมีคารมคมชัดรวดเร็วและมีความต้องการต่ำและไม่จำเป็นต้องมีเวกเตอร์หรือพอยน์เตอร์ เท่าที่คิดคำตอบอื่น ๆ ดูเหมือนว่าจะมีเพียงคำตอบเดียวที่มีอัลกอริทึมเดียวกันและไม่มีคำอธิบายใด ๆ เกี่ยวกับกลไกพื้นฐานของปัญหาดังที่คำตอบของฉันทำ ฉันขอแสดงความนับถือว่าแทนที่จะเป็นข้อผิดพลาดได้ง่ายมันค่อนข้างแข็งแกร่ง
Bob Warner

1

แค่คิด แต่เพิ่งตัดสินใจสร้างตัวแปรตัวนับและเก็บขนาดอาร์เรย์ไว้ในตำแหน่ง [0] ฉันลบโค้ดส่วนใหญ่ที่ฉันมีในฟังก์ชั่น แต่คุณจะเห็นหลังจากออกจากลูปไพรม์ [0] จะถูกกำหนดค่าสุดท้ายของ 'a' ฉันลองใช้เวกเตอร์ แต่ VS Express 2013 ไม่ชอบแบบนั้นมาก นอกจากนี้โปรดทราบว่า 'a' จะเริ่มต้นที่จุดหนึ่งเพื่อหลีกเลี่ยงการเขียนทับ [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;
}

1

ทางออกที่ดีที่ใช้ยาชื่อสามัญ:

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

จากนั้นเรียกใช้arraysize(_Array);เพื่อรับความยาวของอาร์เรย์

แหล่ง


@bbbogo ทำงานร่วมกับ inline หรือ constexpr, บางทีคุณมี inline off หรือไม่ก็ได้? ideone.com/VxogJ4
QuentinUK

@QentinUK constexprเป็นการแก้ไข inlineไม่ใช่. constexprแม้ว่าจะค่อนข้างทันสมัย คุณแน่ใจหรือว่าโปรแกรมทดสอบของคุณไม่ได้ใช้คุณสมบัติที่ทันสมัยอื่นซึ่งคุณสามารถประกาศอาร์เรย์ท้องถิ่นที่มีความยาวที่ตัวแปรกำหนด ลองใช้กับสองอาร์เรย์ทั่วโลก
bobbogo

1

สำหรับคอมไพเลอร์ 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 ++ ใช้งานไม่ได้กับพอยน์เตอร์รวมทั้งคำตอบมีให้ในเวลารวบรวม
bobbogo

1

ฉันให้ทางออกที่ยุ่งยากที่นี่:

คุณสามารถจัดเก็บlengthในองค์ประกอบแรกได้เสมอ:

// malloc/new

arr[0] = length;
arr++;

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

free(--arr); 

คุณต้องเสียค่าใช้จ่าย--arrเมื่อใดfree


2
ใช้งานได้เฉพาะเมื่อarrเป็นชนิดที่เข้ากันได้กับintและอาร์เรย์ไม่เกินค่าสูงสุดของประเภท เช่นสตริงปาสคาลเป็นอาร์เรย์ไบต์ที่ใช้เคล็ดลับนี้ ความยาวสูงสุดของสตริงใน Pascal คือ 255 อักขระ
Palec

ฉันคิดว่าหนึ่งสามารถสำรองพูด 8 ไบต์ที่จุดเริ่มต้นของแต่ละแถวและใช้ไม่ได้ลงนามยาวหากพวกเขาต้องการเก็บวัตถุ ฉันคิดว่าเวกเตอร์น่าจะง่ายกว่า แต่เป็นทางออกที่ดีสำหรับระบบฝังตัว
aj.toulan

1

คุณสามารถค้นหาความยาวของอาเรย์โดยทำตาม:

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;
QuentinUK

1

เพียงแค่คุณสามารถใช้ตัวอย่างนี้:

#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/


0

หลีกเลี่ยงการใช้ชนิดร่วมกับ sizeof เช่นในsizeof(array)/sizeof(char)ทันทีที่เกิดความเสียหายหากคุณเปลี่ยนประเภทของอาร์เรย์

ใน visual studio คุณมีความหมายเทียบเท่าsizeof(array)/sizeof(*array)กัน คุณสามารถพิมพ์_countof(array)


0

ฉันขอแนะนำเป็นการส่วนตัว (ถ้าคุณไม่สามารถทำงานกับฟังก์ชั่นพิเศษไม่ว่าด้วยเหตุผลใดก็ตาม) เพื่อขยายความเข้ากันได้ของอาร์เรย์ก่อนสิ่งที่คุณมักจะใช้เป็น (ถ้าคุณเก็บค่า≥ 0:

unsigned int x[] -> int x[]

มากกว่าที่คุณจะทำให้องค์ประกอบอาร์เรย์ 1 มีขนาดใหญ่กว่าที่คุณต้องการ สำหรับองค์ประกอบสุดท้ายคุณจะใส่ประเภทที่รวมอยู่ในตัวระบุชนิดขยาย แต่โดยปกติคุณจะไม่ใช้เช่นใช้ตัวอย่างก่อนหน้าองค์ประกอบสุดท้ายจะเป็น -1 สิ่งนี้ช่วยให้คุณ (โดยใช้สำหรับวง) เพื่อค้นหาองค์ประกอบสุดท้ายของอาร์เรย์


0

หนึ่งในสาเหตุที่พบบ่อยที่สุดที่คุณจะมองหาคือเพราะคุณต้องการส่งผ่านอาร์เรย์ไปยังฟังก์ชั่นและไม่ต้องผ่านอาร์กิวเมนต์อื่นสำหรับขนาดของมัน โดยทั่วไปคุณต้องการให้ขนาดอาร์เรย์เป็นแบบไดนามิก อาร์เรย์นั้นอาจมีวัตถุไม่ใช่แบบดั้งเดิมและวัตถุอาจซับซ้อนเช่น size_of () เป็นตัวเลือกที่ไม่ปลอดภัยสำหรับการคำนวณจำนวน

ตามที่คนอื่น ๆ แนะนำให้ลองใช้ std :: vector หรือ list ฯลฯ แทนการใช้ array ดั้งเดิม สำหรับคอมไพเลอร์เก่าคุณยังคงไม่มีวิธีแก้ปัญหาขั้นสุดท้ายที่คุณอาจต้องการโดยทำอย่างนั้นเพราะการบรรจุคอนเทนเนอร์นั้นต้องใช้บรรทัด push_back () น่าเกลียด หากคุณเป็นเหมือนฉันต้องการโซลูชันบรรทัดเดียวที่เกี่ยวข้องกับวัตถุที่ไม่ระบุชื่อ

ถ้าคุณใช้คอนเทนเนอร์ STL แทนอาเรย์แบบดั้งเดิมโพสต์ SO นี้อาจใช้กับคุณเพื่อหาวิธีเริ่มต้น: วิธีที่ง่ายที่สุดในการเริ่มต้น std :: vector ด้วยองค์ประกอบ hardcoded คืออะไร?

นี่เป็นวิธีการที่ฉันใช้สำหรับสิ่งนี้ซึ่งจะใช้ได้กับคอมไพเลอร์และแพลตฟอร์ม:

สร้าง struct หรือคลาสเป็นคอนเทนเนอร์สำหรับชุดของวัตถุ กำหนดฟังก์ชั่นการทำงานเกินพิกัดสำหรับ <<

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) );

ด้วยวิธีนี้คุณสามารถสร้างและส่งต่อคอลเลกชันวัตถุที่มีขนาดแบบไดนามิกไปยังฟังก์ชั่นในหนึ่งบรรทัดใหม่!


-4

ให้บอกว่าคุณมีอาร์เรย์ส่วนกลางที่ประกาศที่ด้านบนของหน้า

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

เมื่อต้องการค้นหาจำนวนองค์ประกอบที่มี (ใน c ++) ในอาร์เรย์ให้พิมพ์รหัสต่อไปนี้:

sizeof(global) / 4;

ขนาดของ (NAME_OF_ARRAY) / 4 จะให้คุณกลับจำนวนองค์ประกอบสำหรับชื่ออาร์เรย์ที่กำหนด


8
sizeof (int) ขึ้นอยู่กับแพลตฟอร์ม ไม่มีการรับประกันว่ามันจะเป็น 4 (แม้ว่านี่จะเป็นกรณีที่พบบ่อยที่สุด)
ผู้ชนะ

ยิ่งกว่าคุณ
miksiii

ตัวเลขเวทย์มนตร์ !!
การแข่งขัน Lightness ใน Orbit
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.