Có giới hạn chiều dài mảng tối đa trong C ++ không?


183

Có độ dài tối đa cho một mảng trong C ++ không?

Đây có phải là giới hạn C ++ hay không phụ thuộc vào máy của tôi? Có thể điều chỉnh? Có phụ thuộc vào loại mảng được làm bằng?

Tôi có thể phá vỡ giới hạn đó bằng cách nào đó hay tôi phải tìm kiếm cách lưu trữ thông tin tốt hơn? Và cách đơn giản nhất là gì?

Những gì tôi phải làm là lưu trữ int dài dài trên một mảng, tôi đang làm việc trong môi trường Linux. Câu hỏi của tôi là: tôi phải làm gì nếu tôi cần lưu trữ một mảng gồm N số nguyên dài với N> 10 chữ số?

Tôi cần điều này bởi vì tôi đang viết một số thuật toán mã hóa (ví dụ như p-Pollard) cho trường học, và đánh vào bức tường số nguyên và độ dài của biểu diễn mảng.

Câu trả lời:


163

Có hai giới hạn, cả hai không được thi hành bởi C ++ mà là phần cứng.

Giới hạn đầu tiên (không bao giờ đạt được) được đặt theo các giới hạn của loại kích thước được sử dụng để mô tả một chỉ mục trong mảng (và kích thước của nó). Nó được đưa ra bởi giá trị tối đa mà hệ thống std::size_tcó thể lấy. Kiểu dữ liệu này đủ lớn để chứa kích thước tính theo byte của bất kỳ đối tượng nào

Giới hạn khác là giới hạn bộ nhớ vật lý. Các đối tượng của bạn trong mảng càng lớn thì giới hạn này càng đạt được sớm vì bộ nhớ đã đầy. Ví dụ, một vector<int>kích thước nhất định n thường chiếm nhiều bộ nhớ hơn một mảng loại vector<char>(trừ một giá trị không đổi nhỏ), vì intthường lớn hơn char. Do đó, a vector<char>có thể chứa nhiều mục hơn vector<int>bộ nhớ trước khi đầy. Cùng tính cho các mảng kiểu C thô như int[]char[].

Ngoài ra, giới hạn trên này có thể bị ảnh hưởng bởi loại allocatorđược sử dụng để xây dựng vectorvì an allocatorcó thể quản lý bộ nhớ theo bất kỳ cách nào nó muốn. Một bộ cấp phát có thể hiểu được rất kỳ lạ nhưng không cần thiết có thể gộp bộ nhớ theo cách sao cho các thể hiện giống hệt nhau của một đối tượng chia sẻ tài nguyên. Bằng cách này, bạn có thể chèn rất nhiều đối tượng giống hệt nhau vào một thùng chứa có thể sử dụng hết bộ nhớ khả dụng.

Ngoài ra, C ++ không thực thi bất kỳ giới hạn nào.


20
Ngoài ra, thông thường bạn có thể dễ dàng đạt giới hạn kích thước ngăn xếp, đặc biệt nếu sử dụng các luồng một lần nữa là triển khai cụ thể (nhưng có thể thay đổi).
Alaric

@Alaric: Đúng. Tôi không muốn đi quá sâu vào chi tiết cụ thể của hệ thống vì chúng khác nhau rất nhiều và tôi không phải là chuyên gia trong số chúng.
Konrad Rudolph

@Konrad, điểm thú vị về các loại phân bổ và không phải là điều tôi biết. Cảm ơn bạn về thông tin.
SmacL

11
std :: size_t thường là (luôn luôn?) kích thước của một con trỏ, không phải kích thước của số nguyên lớn nhất có hỗ trợ phần cứng riêng trong đơn vị toán học số nguyên. Trên mọi HĐH x86 tôi đã sử dụng, size_t là 32 bit cho HĐH 32 bit và 64 bit cho HĐH 64 bit.
Ông Fooz

2
Sự hiểu biết của tôi là giới hạn tối đa của một mảng là giá trị tối đa của bộ vi xử lý từ . Điều này là do toán tử lập chỉ mục. Ví dụ, một máy có thể có kích thước từ 16 bit nhưng thanh ghi địa chỉ là 32 bit. Một đoạn bộ nhớ bị giới hạn kích thước bởi tham số được truyền tới newhoặc malloc. Một đoạn bộ nhớ lớn hơn một mảng có thể được truy cập thông qua con trỏ.
Thomas Matthews

171

Không ai đề cập đến giới hạn về kích thước của khung stack .

Có hai vị trí bộ nhớ có thể được phân bổ:

  • Trên heap (bộ nhớ được phân bổ động).
    Giới hạn kích thước ở đây là sự kết hợp giữa phần cứng khả dụng và khả năng mô phỏng không gian của HĐH bằng cách sử dụng các thiết bị khác để tạm thời lưu trữ dữ liệu không sử dụng ( tức là di chuyển các trang vào đĩa cứng).
  • Trên ngăn xếp (Các biến được khai báo cục bộ).
    Giới hạn kích thước ở đây là trình biên dịch được xác định (với giới hạn phần cứng có thể). Nếu bạn đọc tài liệu biên dịch, bạn có thể thường xuyên điều chỉnh kích thước này.

Do đó, nếu bạn phân bổ một mảng động (giới hạn là lớn và được mô tả chi tiết bởi các bài viết khác.

int* a1 = new int[SIZE];  // SIZE limited only by OS/Hardware

Ngoài ra, nếu mảng được phân bổ trên ngăn xếp thì bạn bị giới hạn bởi kích thước của khung ngăn xếp. Các vectơ NB và các thùng chứa khác có sự hiện diện nhỏ trong ngăn xếp nhưng thường thì phần lớn dữ liệu sẽ nằm trên đống.

int a2[SIZE]; // SIZE limited by COMPILER to the size of the stack frame

4
Phân bổ ưa thích của các mảng lớn không nằm trên một ngăn xếp hoặc được xác định toàn cầu mà là thông qua phân bổ động (thông qua newhoặc malloc).
Thomas Matthews

1
@Thomas Matthews: Không có trong thế giới của tôi. Đối tượng phân bổ động đòi hỏi phải quản lý. Nếu nó cần được phân bổ động, tôi sẽ sử dụng một đối tượng ngăn xếp đại diện cho bản ghi nhớ được phân bổ động, như một std :: vector.
Martin York

2
Có một trường hợp bị thiếu: Global Arraystrong khi không phải là một vẻ đẹp và tốt nhất nên tránh, những điều này không thuộc các hạn chế của stack, và bạn không cần malloc/ freelàm việc với chúng.
ted

1
@ted, tại sao mảng toàn cầu nên "tốt nhất nên tránh"? Nói chính xác hơn tôi nghĩ bạn có nghĩa là mảng được phân bổ tĩnh. Phạm vi của họ không phải là toàn cầu. Tôi cho rằng chúng tốt hơn mảng động vì bạn có thể sử dụng địa chỉ tuyệt đối với chúng (ít nhất là trên Linux) mà bạn không thể làm với mảng được phân bổ động.
Z boson

2
Điểm rất quan trọng. Gần đây tôi đã bắt gặp một dự án nguồn mở "chất lượng sản xuất" cung cấp kích thước bộ đệm tối đa có thể định cấu hình. Tất cả các bộ đệm đã được phân bổ trên ngăn xếp, do đó, việc định cấu hình một giá trị đủ lớn sẽ khiến chương trình bị tách ra ngay lập tức khi khởi chạy.
aroth

13

Nhìn từ góc độ thực tế thay vì lý thuyết, trên hệ thống Windows 32 bit, tổng dung lượng bộ nhớ tối đa có sẵn cho một quy trình là 2 GB. Bạn có thể phá vỡ giới hạn bằng cách truy cập hệ điều hành 64 bit với bộ nhớ vật lý nhiều hơn, nhưng việc thực hiện việc này hay tìm kiếm các lựa chọn thay thế phụ thuộc rất nhiều vào người dùng dự định và ngân sách của họ. Bạn cũng có thể mở rộng nó bằng cách sử dụng PAE .

Kiểu của mảng là rất quan trọng, vì căn chỉnh cấu trúc mặc định trên nhiều trình biên dịch là 8 byte, rất lãng phí nếu việc sử dụng bộ nhớ là một vấn đề. Nếu bạn đang sử dụng Visual C ++ để nhắm mục tiêu Windows, hãy xem chỉ thị gói #pragma như một cách khắc phục điều này.

Một điều cần làm là xem xét những gì trong các kỹ thuật nén bộ nhớ có thể giúp bạn, chẳng hạn như ma trận thưa thớt, khi nén, v.v ... Một lần nữa, điều này phụ thuộc rất nhiều vào ứng dụng. Nếu bạn chỉnh sửa bài đăng của mình để cung cấp thêm một số thông tin về những gì thực sự có trong mảng của bạn, bạn có thể nhận được nhiều câu trả lời hữu ích hơn.

Chỉnh sửa: Cung cấp thêm một chút thông tin về các yêu cầu chính xác của bạn, nhu cầu lưu trữ của bạn dường như nằm trong khoảng từ 7.6 GB đến 76 GB không nén, sẽ cần một hộp 64 bit khá đắt tiền để lưu trữ dưới dạng một mảng trong bộ nhớ trong C ++. Nó đặt ra câu hỏi tại sao bạn muốn lưu trữ dữ liệu trong bộ nhớ, trong đó người ta cho rằng tốc độ truy cập và cho phép truy cập ngẫu nhiên. Cách tốt nhất để lưu trữ dữ liệu này bên ngoài một mảng là khá nhiều dựa trên cách bạn muốn truy cập nó. Nếu bạn cần truy cập ngẫu nhiên các thành viên mảng, đối với hầu hết các ứng dụng có xu hướng nhóm các cụm dữ liệu có xu hướng được truy cập cùng một lúc. Ví dụ, trong các cơ sở dữ liệu không gian và GIS lớn, dữ liệu thường được sắp xếp theo khu vực địa lý. Trong thuật ngữ lập trình C ++, bạn có thể ghi đè toán tử mảng [] để tìm nạp các phần dữ liệu của mình từ bộ nhớ ngoài theo yêu cầu.


1
Có các cuộc gọi hệ thống cho phép phân bổ bộ nhớ ngoài không gian chương trình; nhưng đây là hệ điều hành phụ thuộc và không di động. Chúng tôi đã sử dụng chúng trong các hệ thống nhúng.
Thomas Matthews

4

Tôi đồng ý với ý kiến ​​trên, rằng nếu bạn đang định hướng mảng của mình với

 int myArray[SIZE] 

thì SIZE bị giới hạn bởi kích thước của một số nguyên. Nhưng bạn luôn có thể malloc một đoạn bộ nhớ và có một con trỏ tới nó, lớn như bạn muốn miễn là malloc không trả về NULL.


Tôi không chắc chắn nếu điều này là không chính xác, hoặc tôi đã hiểu lầm bạn, hoặc một cái gì đó khác. Ví dụ: điều này bị ngăn chặn bởi trình biên dịch MSVC17: int oops[INT_MAX]{0};Nó tạo ra,C2148 - total size of array must not exceed 0x7fffffff bytes
kayleeFrye_onDeck

Với 16 GB DDR4 và về 66%bộ nhớ hiện đang được sử dụng trước khi khởi chạy ứng dụng của tôi dưới dạng gỡ lỗi trên Windows 10 với VS2017, tôi có một giới hạn không xác định về mức độ lớn của một mảng int tôi có thể khởi tạo 0. Đôi khi tôi có thể làm điều đó với ~ 256k phần tử, đôi khi tôi nhận được một ngăn xếp tràn. Nếu tôi thêm bất cứ điều gì vào ứng dụng của mình ngoài mảng chính và mảng, con số đó sẽ giảm (rõ ràng). Tôi đã phải thử nghiệm để xác định con số này, vì vậy tôi không thấy số liệu này có thể dựa vào như thế nào ngoài việc biết giới hạn lý thuyết của bạn trong chân không.
kayleeFrye_onDeck

4

Để tóm tắt các câu trả lời, hãy mở rộng chúng và trả lời trực tiếp câu hỏi của bạn:

Không, C ++ không áp đặt bất kỳ giới hạn nào cho kích thước của một mảng.

Nhưng vì mảng phải được lưu trữ ở đâu đó trong bộ nhớ, nên các giới hạn liên quan đến bộ nhớ được áp đặt bởi các phần khác của hệ thống máy tính được áp dụng. Lưu ý rằng các giới hạn này không liên quan trực tiếp đến kích thước (= số phần tử) của mảng, mà thay vào đó là kích thước của nó (= lượng bộ nhớ đã lấy). Kích thước ( D ) và kích thước trong bộ nhớ ( S ) của một mảng là không giống nhau, vì chúng có liên quan bởi bộ nhớ thực hiện bởi một yếu tố duy nhất ( E ): S = D * E .

Hiện nayE phụ thuộc vào:

  • loại phần tử mảng (phần tử có thể nhỏ hơn hoặc lớn hơn)
  • căn chỉnh bộ nhớ (để tăng hiệu suất, các phần tử được đặt tại các địa chỉ là bội số của một số giá trị, điều này giới thiệu
    'không gian bị lãng phí' (phần đệm) giữa các phần tử
  • kích thước của các phần tĩnh của các đối tượng (trong lập trình hướng đối tượng Các thành phần tĩnh của các đối tượng cùng loại chỉ được lưu trữ một lần, độc lập với số lượng các đối tượng cùng loại đó)

Cũng lưu ý rằng bạn thường nhận được các giới hạn liên quan đến bộ nhớ khác nhau bằng cách phân bổ dữ liệu mảng trên ngăn xếp (dưới dạng biến tự động int t[N]:) hoặc trên heap (sắp xếp động với malloc()/ newhoặc sử dụng cơ chế STL) hoặc trong phần tĩnh của bộ nhớ quy trình (như một biến tĩnh static int t[N]:). Ngay cả khi phân bổ trên heap, bạn vẫn cần một lượng bộ nhớ nhỏ trên ngăn xếp để lưu trữ các tham chiếu đến các khối bộ nhớ được phân bổ heap (nhưng thông thường là không đáng kể).

Kích thước của size_tloại không ảnh hưởng đến lập trình viên (Tôi giả sử lập trình viên sử dụng size_tloại để lập chỉ mục, vì nó được thiết kế cho nó), vì nhà cung cấp trình biên dịch phải typedefchuyển sang loại số nguyên đủ lớn để giải quyết lượng bộ nhớ tối đa có thể cho nền tảng đã cho ngành kiến ​​trúc.

Các nguồn giới hạn kích thước bộ nhớ bắt nguồn từ

  • dung lượng bộ nhớ khả dụng cho quá trình (giới hạn ở 2 ^ 32 byte cho các ứng dụng 32 bit, ngay cả trên các nhân hệ điều hành 64 bit),
  • sự phân chia bộ nhớ tiến trình (ví dụ: lượng bộ nhớ tiến trình được thiết kế cho stack hoặc heap),
  • sự phân mảnh của bộ nhớ vật lý (nhiều mảnh bộ nhớ nhỏ rải rác không thể áp dụng để lưu trữ một cấu trúc nguyên khối),
  • dung lượng bộ nhớ vật lý,
  • và dung lượng bộ nhớ ảo.

Chúng không thể được 'điều chỉnh' ở cấp ứng dụng, nhưng bạn có thể tự do sử dụng một trình biên dịch khác (để thay đổi giới hạn kích thước ngăn xếp) hoặc chuyển ứng dụng của bạn sang 64 bit hoặc chuyển nó sang HĐH khác hoặc thay đổi vật lý / cấu hình bộ nhớ ảo của máy (ảo? vật lý?).

Không có gì lạ (và thậm chí được khuyến khích) coi tất cả các yếu tố trên là nhiễu bên ngoài và do đó có thể là nguồn gây ra lỗi thời gian chạy, và kiểm tra cẩn thận & phản ứng với các lỗi liên quan đến cấp phát bộ nhớ trong mã chương trình của bạn.

Vì vậy, cuối cùng: trong khi C ++ không áp đặt bất kỳ giới hạn nào, bạn vẫn phải kiểm tra các điều kiện bất lợi liên quan đến bộ nhớ khi chạy mã của bạn ... :-)


3

Như nhiều câu trả lời xuất sắc đã lưu ý, có rất nhiều giới hạn phụ thuộc vào phiên bản trình biên dịch C ++, hệ điều hành và đặc tính máy tính của bạn. Tuy nhiên, tôi đề nghị đoạn script sau trên Python kiểm tra giới hạn trên máy của bạn.

Nó sử dụng tìm kiếm nhị phân và trên mỗi lần kiểm tra lặp lại nếu kích thước trung bình có thể bằng cách tạo mã cố gắng tạo một mảng có kích thước. Kịch bản lệnh cố gắng biên dịch nó (xin lỗi, phần này chỉ hoạt động trên Linux) và điều chỉnh tìm kiếm nhị phân tùy thuộc vào thành công. Kiểm tra xem nó:

import os

cpp_source = 'int a[{}]; int main() {{ return 0; }}'

def check_if_array_size_compiles(size):
        #  Write to file 1.cpp
        f = open(name='1.cpp', mode='w')
        f.write(cpp_source.format(m))
        f.close()
        #  Attempt to compile
        os.system('g++ 1.cpp 2> errors')
        #  Read the errors files
        errors = open('errors', 'r').read()
        #  Return if there is no errors
        return len(errors) == 0

#  Make a binary search. Try to create array with size m and
#  adjust the r and l border depending on wheather we succeeded
#  or not
l = 0
r = 10 ** 50
while r - l > 1:
        m = (r + l) // 2
        if check_if_array_size_compiles(m):
                l = m
        else:
                r = m

answer = l + check_if_array_size_compiles(r)
print '{} is the maximum avaliable length'.format(answer)

Bạn có thể lưu nó vào máy của mình và khởi chạy nó, và nó sẽ in kích thước tối đa bạn có thể tạo. Đối với máy của tôi, nó là 2305843009213693951.


2

Một điều tôi không nghĩ đã được đề cập trong các câu trả lời trước.

Tôi luôn cảm nhận được "mùi hôi" theo nghĩa tái cấu trúc khi mọi người đang sử dụng những thứ như vậy trong thiết kế của họ.

Đó là một mảng lớn và có thể không phải là cách tốt nhất để thể hiện dữ liệu của bạn cả từ quan điểm hiệu quả và quan điểm hiệu suất.

chúc mừng

Cướp


Bạn có gợi ý nào về những gì tôi nên sử dụng không?
luiss

Nếu bạn có thể cho chúng tôi biết dữ liệu bạn đang lưu trữ thì có lẽ chúng ta có thể. (-:
Rob Wells

Xin lỗi Luis phản ứng đầu tiên của tôi rất thiếu sót. Nó sẽ được điều khiển bởi bản chất của dữ liệu của bạn. Các mối quan hệ của dữ liệu của bạn sẽ điều khiển mô hình bạn sử dụng để thể hiện dữ liệu. Sau đó, bộ sưu tập nên được rõ ràng từ đó. Nếu không, tôi sẽ lo lắng về mô hình dữ liệu.
Rob Wells

không quá dễ hiểu với tôi: làm thế nào về một cơ sở dữ liệu được lưu trữ với một món đồ chơi như thế này? Tunetown.com/news/22066/ từ

2

Nếu bạn phải xử lý dữ liệu lớn, bạn sẽ cần chia dữ liệu thành các phần có thể quản lý được. Tất cả sẽ không vừa với bộ nhớ trên bất kỳ máy tính nhỏ nào. Bạn có thể có thể tải một phần dữ liệu từ đĩa (bất cứ điều gì hợp lý), thực hiện các tính toán của bạn và thay đổi nó, lưu trữ vào đĩa, sau đó lặp lại cho đến khi hoàn thành.


Xem thêm để Hợp nhất Sắp xếp trên một thuật toán ví dụ để xử lý dữ liệu quá lớn để vừa với bộ nhớ.
Thomas Matthews

2

Khó chịu không cụ thể như tất cả các câu trả lời hiện tại, hầu hết đều đúng nhưng có nhiều cảnh báo, không phải lúc nào cũng được đề cập. Ý chính là, bạn có hai giới hạn trên và chỉ một trong số chúng là một cái gì đó thực sự được xác định, vì vậy YMMV :

1. Giới hạn thời gian biên dịch

Về cơ bản, những gì trình biên dịch của bạn sẽ cho phép. Đối với Visual C ++ 2017 trên hộp Windows 10 x64, đây là giới hạn tối đa của tôi tại thời gian biên dịch trước khi phát sinh giới hạn 2GB,

unsigned __int64 max_ints[255999996]{0};

Nếu tôi làm điều này thay vào đó,

unsigned __int64 max_ints[255999997]{0};

Tôi sẽ nhận được:

Error C1126 automatic allocation exceeds 2G

Tôi không chắc cách 2G tương ứng với 255999996/ 7. Tôi đã googled cả hai số, và điều duy nhất tôi có thể tìm thấy có thể liên quan là câu hỏi * nix này về một vấn đề chính xác vớidc . Dù bằng cách nào, dường như không có vấn đề gì về loại mảng int bạn đang cố gắng điền, chỉ có bao nhiêu phần tử có thể được phân bổ.

2. Giới hạn thời gian chạy

Ngăn xếp và đống của bạn có những hạn chế riêng của họ. Các giới hạn này là cả hai giá trị thay đổi dựa trên tài nguyên hệ thống có sẵn, cũng như mức độ "nặng" của ứng dụng của bạn. Ví dụ: với tài nguyên hệ thống hiện tại của tôi, tôi có thể chạy nó:

int main()
{
    int max_ints[257400]{ 0 };
    return 0;
}

Nhưng nếu tôi tinh chỉnh nó một chút ...

int main()
{
    int max_ints[257500]{ 0 };
    return 0;
}

Bế! Chồng tràn!

Exception thrown at 0x00007FF7DC6B1B38 in memchk.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000AA8DE03000). Unhandled exception at 0x00007FF7DC6B1B38 in memchk.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000AA8DE03000).

Và chỉ để chi tiết toàn bộ độ nặng của điểm ứng dụng của bạn, điều này thật tuyệt:

int main()
{
    int maxish_ints[257000]{ 0 };
    int more_ints[400]{ 0 };
    return 0;
}  

Nhưng điều này gây ra một tràn ngăn xếp:

int main()
{
    int maxish_ints[257000]{ 0 };
    int more_ints[500]{ 0 };
    return 0;
}  

1

Tôi ngạc nhiên khi hàm thành viên max_size () của std :: vector chưa được đề cập ở đây.

"Trả về số lượng phần tử tối đa mà bộ chứa có thể giữ do các giới hạn triển khai của hệ thống hoặc thư viện, tức là std :: distance (started (), end ()) cho container lớn nhất."

Chúng tôi biết rằng std::vectorđược triển khai như một mảng động bên dưới mui xe, do đó, max_size()nên đưa ra một xấp xỉ rất gần với độ dài tối đa của mộtmảng động trên máy của bạn.

Chương trình sau đây xây dựng một bảng có độ dài mảng tối đa gần đúng cho các loại dữ liệu khác nhau.

#include <iostream>
#include <vector>
#include <string>
#include <limits>

template <typename T>
std::string mx(T e) {
    std::vector<T> v;
    return std::to_string(v.max_size());
}

std::size_t maxColWidth(std::vector<std::string> v) {
    std::size_t maxWidth = 0;

    for (const auto &s: v)
        if (s.length() > maxWidth)
            maxWidth = s.length();

    // Add 2 for space on each side
    return maxWidth + 2;
}

constexpr long double maxStdSize_t = std::numeric_limits<std::size_t>::max();

// cs stands for compared to std::size_t
template <typename T>
std::string cs(T e) {
    std::vector<T> v;
    long double maxSize = v.max_size();
    long double quotient = maxStdSize_t / maxSize;
    return std::to_string(quotient);
}

int main() {
    bool v0 = 0;
    char v1 = 0;

    int8_t v2 = 0;
    int16_t v3 = 0;
    int32_t v4 = 0;
    int64_t v5 = 0;

    uint8_t v6 = 0;
    uint16_t v7 = 0;
    uint32_t v8 = 0;
    uint64_t v9 = 0;

    std::size_t v10 = 0;
    double v11 = 0;
    long double v12 = 0;

    std::vector<std::string> types = {"data types", "bool", "char", "int8_t", "int16_t",
                                      "int32_t", "int64_t", "uint8_t", "uint16_t",
                                      "uint32_t", "uint64_t", "size_t", "double",
                                      "long double"};

    std::vector<std::string> sizes = {"approx max array length", mx(v0), mx(v1), mx(v2),
                                      mx(v3), mx(v4), mx(v5), mx(v6), mx(v7), mx(v8),
                                      mx(v9), mx(v10), mx(v11), mx(v12)};

    std::vector<std::string> quotients = {"max std::size_t / max array size", cs(v0),
                                          cs(v1), cs(v2), cs(v3), cs(v4), cs(v5), cs(v6),
                                          cs(v7), cs(v8), cs(v9), cs(v10), cs(v11), cs(v12)};

    std::size_t max1 = maxColWidth(types);
    std::size_t max2 = maxColWidth(sizes);
    std::size_t max3 = maxColWidth(quotients);

    for (std::size_t i = 0; i < types.size(); ++i) {
        while (types[i].length() < (max1 - 1)) {
            types[i] = " " + types[i];
        }

        types[i] += " ";

        for  (int j = 0; sizes[i].length() < max2; ++j)
            sizes[i] = (j % 2 == 0) ? " " + sizes[i] : sizes[i] + " ";

        for  (int j = 0; quotients[i].length() < max3; ++j)
            quotients[i] = (j % 2 == 0) ? " " + quotients[i] : quotients[i] + " ";

        std::cout << "|" << types[i] << "|" << sizes[i] << "|" << quotients[i] << "|\n";
    }

    std::cout << std::endl;

    std::cout << "N.B. max std::size_t is: " <<
        std::numeric_limits<std::size_t>::max() << std::endl;

    return 0;
}

Trên macOS của tôi (phiên bản clang 5.0.1), tôi nhận được như sau:

|  data types | approx max array length | max std::size_t / max array size |
|        bool |   9223372036854775807   |             2.000000             |
|        char |   9223372036854775807   |             2.000000             |
|      int8_t |   9223372036854775807   |             2.000000             |
|     int16_t |   9223372036854775807   |             2.000000             |
|     int32_t |   4611686018427387903   |             4.000000             |
|     int64_t |   2305843009213693951   |             8.000000             |
|     uint8_t |   9223372036854775807   |             2.000000             |
|    uint16_t |   9223372036854775807   |             2.000000             |
|    uint32_t |   4611686018427387903   |             4.000000             |
|    uint64_t |   2305843009213693951   |             8.000000             |
|      size_t |   2305843009213693951   |             8.000000             |
|      double |   2305843009213693951   |             8.000000             |
| long double |   1152921504606846975   |             16.000000            |

N.B. max std::size_t is: 18446744073709551615

Trên ideone gcc 8.3 tôi nhận được:

|  data types | approx max array length | max std::size_t / max array size |
|        bool |   9223372036854775744   |             2.000000             |
|        char |   18446744073709551615  |             1.000000             |
|      int8_t |   18446744073709551615  |             1.000000             |
|     int16_t |   9223372036854775807   |             2.000000             |
|     int32_t |   4611686018427387903   |             4.000000             |
|     int64_t |   2305843009213693951   |             8.000000             |
|     uint8_t |   18446744073709551615  |             1.000000             |
|    uint16_t |   9223372036854775807   |             2.000000             |
|    uint32_t |   4611686018427387903   |             4.000000             |
|    uint64_t |   2305843009213693951   |             8.000000             |
|      size_t |   2305843009213693951   |             8.000000             |
|      double |   2305843009213693951   |             8.000000             |
| long double |   1152921504606846975   |             16.000000            |

N.B. max std::size_t is: 18446744073709551615

Cần lưu ý rằng đây là giới hạn lý thuyết và trên hầu hết các máy tính, bạn sẽ hết bộ nhớ trước khi bạn đạt đến giới hạn này. Ví dụ, chúng ta thấy rằng đối với loại chartrên gcc, số phần tử tối đa bằng với tối đa std::size_t. Đang thử cái này , chúng tôi nhận được lỗi:

prog.cpp: In function int main()’:
prog.cpp:5:61: error: size of array is too large
  char* a1 = new char[std::numeric_limits<std::size_t>::max()];

Cuối cùng, như @MartinYork chỉ ra, đối với mảng tĩnh, kích thước tối đa bị giới hạn bởi kích thước của ngăn xếp của bạn.


0

Như đã được chỉ ra, kích thước mảng bị giới hạn bởi phần cứng và hệ điều hành của bạn (man ulimit). Phần mềm của bạn mặc dù, chỉ có thể bị giới hạn bởi sự sáng tạo của bạn. Ví dụ, bạn có thể lưu trữ "mảng" của mình trên đĩa không? Bạn có thực sự cần int dài dài? Bạn có thực sự cần một mảng dày đặc? Bạn thậm chí có cần một mảng không?

Một giải pháp đơn giản là sử dụng Linux 64 bit. Ngay cả khi bạn không có đủ ram cho mảng của mình, HĐH sẽ cho phép bạn phân bổ bộ nhớ như thể bạn làm vì bộ nhớ ảo có sẵn cho quá trình của bạn có thể lớn hơn nhiều so với bộ nhớ vật lý. Nếu bạn thực sự cần truy cập mọi thứ trong mảng, số tiền này sẽ lưu trữ trên đĩa. Tùy thuộc vào các mẫu truy cập của bạn, có thể có nhiều cách hiệu quả hơn để thực hiện việc này (ví dụ: sử dụng mmap () hoặc đơn giản là lưu trữ dữ liệu tuần tự trong một tệp (trong trường hợp Linux 32 bit sẽ đủ)).


2
Hmm, đĩa, mảng, ... bất cứ ai cũng nghe thấy bộ nhớ ảo . Các hệ điều hành hỗ trợ bộ nhớ ảo sẽ bắt đầu sử dụng một thiết bị bên ngoài cho bộ nhớ, chẳng hạn như đĩa cứng và trao đổi các phần với bộ nhớ trong.
Thomas Matthews

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.