473,769 Members | 3,084 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Big arrays (confusion over FAQ 6.14)

I have a need to create an array that is larger than size_t - 1, which
I believe is the largest guaranteed array. I though I'd found
salvation in FAQ 6.14, but it appears I am not understanding
something.

The array is an array of pointers to structs. Here is an example
using a small array:

/* checks that malloc succeeded, main's return, etc. removed for
brevity */

#include <stdio.h>
#include <stdlib.h>

typedef struct {
int foo;
int bar;
} example_struct;

int main (void) {
example_struct * small_array[1000];
example_struct * a_single_struct ;

a_single_struct = malloc ( sizeof(example_ struct *) );
a_single_struct->foo = 4000;
printf ("a_single_stru ct foo: %i \n", a_single_struct->foo);

small_array[900] = a_single_struct ;
printf ("small_arra y 900 foo: %i\n",small_arr ay[900]->foo);

}

This works fine:

a_single_struct foo: 4000
small_array 900 foo: 4000

So far, so good. Now I want to do an array of, say, 3,000,000
members, too large for a simple big_array[3000000] declaration. So I
use the code from faq 6.14:

/* checks that malloc succeeded, main's return, etc. removed for
brevity */

#include <stdio.h>
#include <stdlib.h>

typedef struct {
int foo;
int bar;
} example_struct;

int main (void) {
example_struct * big_array;
example_struct * a_single_struct ;

a_single_struct = malloc ( sizeof(example_ struct *) );
a_single_struct->foo = 4000;
printf ("a_single_stru ct foo: %i \n", a_single_struct->foo);

big_array = malloc ( 3000000 * sizeof ( example_struct * ) );
big_array[1000000] = a_single_struct ; /* line 20, error below */
printf ("big_array foo: %i\n",big_array[1000000]->foo);

}

No go. The compiler (gcc in this case) returns:

test.c: In function 'main':
test.c:20: error: incompatible types in assignment
test.c:21: error: invalid type argument of '->'

So the example in FAQ 6.14 is:

"int *dynarray;
dynarray = malloc(10 * sizeof(int));

....you can reference dynarray[i] (for i from 0 to 9) almost as if
dynarray were a conventional, statically-allocated array (int a[10])"

Given that, I'm confused why

small_array[900] = a_simple_struct ;

works, while

big_array[1000000] = a_simple_struct ;

doesn't.

Is there some obvious error in my code? Have I just embarrassed
myself by displaying my obtusity before the comp.lang.c gods? Or is
there some better method of creating arrays (size_t - 1) ?

Thanks.

Aug 12 '07 #1
35 2067
Andrew Fabbro wrote:
>
I have a need to create an array that is larger than size_t - 1,
which I believe is the largest guaranteed array. I though I'd
found salvation in FAQ 6.14, but it appears I am not
understanding something.
You can't have it. No object whose size cannot be measured in a
size_t can exist. What are you trying to do?

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home .att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Aug 12 '07 #2

"CBFalconer " <cb********@yah oo.comwrote in message
news:46******** *******@yahoo.c om...
Andrew Fabbro wrote:
>>
I have a need to create an array that is larger than size_t - 1,
which I believe is the largest guaranteed array. I though I'd
found salvation in FAQ 6.14, but it appears I am not
understandin g something.

You can't have it. No object whose size cannot be measured in a
size_t can exist. What are you trying to do?
It can exist in the backing store.
As long as you don't need too many random accesses to your array, store it
on disk and read in chunks as you need.
Unfortunately the fseek() function quite often takes a long, which might not
be big enough. The fsetpos() takes yet another data type, fpos_t, and may
not be available.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Aug 12 '07 #3
On Sat, 11 Aug 2007 22:09:57 -0700, Andrew Fabbro wrote:
I have a need to create an array that is larger than size_t - 1, which
I believe is the largest guaranteed array. I though I'd found
salvation in FAQ 6.14, but it appears I am not understanding
something.
On modern PCs, (size_t)(-1) is one byte less than 4 GB (on 32-bit
processors), or about 2.8 GB times the human population of the
Earth (on 64-bit processors). You are very likely *not* to have
enough memory, and if you have I think is impossible (or almost so)
to access it. What the hell are you trying to do? You might store
all those structs on a disk file.
(If you're programming for MS-DOS or some other system where it is
not absurd to have more memory than (size_t)(-1), go to
comp.os.msdos.p rogramming or whatever.)
--
Army1987 (Replace "NOSPAM" with "email")
No-one ever won a game by resigning. -- S. Tartakower

Aug 12 '07 #4
Andrew Fabbro <an***********@ gmail.comwrote:
I have a need to create an array that is larger than size_t - 1, which
I believe is the largest guaranteed array. I though I'd found
salvation in FAQ 6.14, but it appears I am not understanding
something.
The array is an array of pointers to structs. Here is an example
using a small array:
/* checks that malloc succeeded, main's return, etc. removed for
brevity */
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int foo;
int bar;
} example_struct;
int main (void) {
example_struct * small_array[1000];
example_struct * a_single_struct ;
a_single_struct = malloc ( sizeof(example_ struct *) );
You already have a severe problem here: you don't allocate
enough memory. What you need to to allocate is not just a
pointer to an 'example_struct ' (that you already have with
'a_single_struc t'), but enough memory for an 'example_struct '.
So you need here

a_single_struct = malloc) sizeof( example_struct ) );
a_single_struct->foo = 4000;
With your alloction this only works by pure luck - if the
size of an 'example_struct ' is larger than that of a pointer
to such a structure then you may be overwriting memory you
didn't allocate (since on most machines the size of a pointer
is at least as large as that of an int you may just have
avoided disaster since you only wrote to the 'foo' member,
but if you also write to the 'bar' member then things will
look worse....)
printf ("a_single_stru ct foo: %i \n", a_single_struct->foo);
small_array[900] = a_single_struct ;
printf ("small_arra y 900 foo: %i\n",small_arr ay[900]->foo);
}
This works fine:
a_single_struct foo: 4000
small_array 900 foo: 4000
Unfortunately, it only looks like it works fine.
So far, so good. Now I want to do an array of, say, 3,000,000
members, too large for a simple big_array[3000000] declaration. So I
use the code from faq 6.14:
/* checks that malloc succeeded, main's return, etc. removed for
brevity */
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int foo;
int bar;
} example_struct;
int main (void) {
example_struct * big_array;
example_struct * a_single_struct ;
a_single_struct = malloc ( sizeof(example_ struct *) );
a_single_struct->foo = 4000;
printf ("a_single_stru ct foo: %i \n", a_single_struct->foo);
You have the same problem here as above...
big_array = malloc ( 3000000 * sizeof ( example_struct * ) );
'big_array' is a pointer to an 'example_struct ', but you
allocate memory for 3000000 pointers to 'example_struct '
which you then assign to 'big_array'.
big_array[1000000] = a_single_struct ; /* line 20, error below */
And here you get caught: since 'big_array' is of type
pointer to 'example_struct ' big_array[1000000] is of
type 'example_struct ', but what you try to assign it
is of type pointer to 'example_struct ' and that's why
the compiler tells you
test.c:20: error: incompatible types in assignment
Since you want an array of pointers to 'example_struct '
you must define 'big_array' to be a pointer to pointer
to 'example_struct ', i.e.

example_struct ** big_array;

to get things to work.
printf ("big_array foo: %i\n",big_array[1000000]->foo);
And since 'big_array[1000000]' is of type 'example_struct '
(and not pointer to such a structure) you can't use '->'
with that as the compiler tells you with
test.c:21: error: invalid type argument of '->'
Or is
there some better method of creating arrays (size_t - 1) ?
I don't think you really have a problem with 'size_t' here
and, BTW, size_t is a type and not a value, the maximum
value that can be stored in a variable of type size_t is
SIZE_MAX as defined in <stdint.h>, at least if your com-
piler supports this C99-ism (gcc does), which typically
is much larger than just 3 millions. I guess the problem
is rather that you want an array that's larger than the
amount of memory that the system allows you for local
"real" (fixed sized) array. But no, there's no better way
for creating large arrays (or arrays that have a variable
size) than using memory allocation at run-time.

Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\______________ ____________ http://toerring.de
Aug 12 '07 #5
Malcolm McLean wrote, On 12/08/07 08:25:
>
"CBFalconer " <cb********@yah oo.comwrote in message
news:46******** *******@yahoo.c om...
>Andrew Fabbro wrote:
>>>
I have a need to create an array that is larger than size_t - 1,
which I believe is the largest guaranteed array. I though I'd
found salvation in FAQ 6.14, but it appears I am not
understandi ng something.

You can't have it. No object whose size cannot be measured in a
size_t can exist. What are you trying to do?
It can exist in the backing store.
I C terms that is not an object.
As long as you don't need too many random accesses to your array, store
it on disk and read in chunks as you need.
Unfortunately the fseek() function quite often takes a long,
Actually, it *always* takes a long on a conforming implementation.
which might
not be big enough.
True.
The fsetpos() takes yet another data type, fpos_t,
No, it takes a pointer to fpos_t.
and may not be available.
It is not optional on hosted implementations so it will be available on
any hosted implementation claiming conformance to any version of the C
standard. It does, however, have the problem that the only value you can
portably pass to it is one obtained with fgetpos.

You also have the problem that the file system might not support a
sufficiently large file.
--
Flash Gordon
Aug 12 '07 #6
On Sun, 12 Aug 2007 11:13:38 +0200, in comp.lang.c , Army1987
<ar******@NOSPA M.itwrote:
>On modern PCs, (size_t)(-1) is one byte less than 4 GB (on 32-bit
processors), or about 2.8 GB times the human population of the
Earth (on 64-bit processors). You are very likely *not* to have
enough memory,
These days, blade PCs with 8+GB aren't that rare, especially in the
commercial sector.
>and if you have I think is impossible (or almost so)
to access it.
4 arrays of 2 GB ?

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Aug 12 '07 #7
Andrew Fabbro wrote:
I have a need to create an array that is larger than size_t - 1, which
I believe is the largest guaranteed array.
If you mean `(size_t)-1', you're out of luck: No object can
have more than SIZE_MAX bytes. Also, it's likely that the O/S
and the rest of your program will chew up some amount of memory,
so you won't even be able to get that high. It's a "theoretica l"
upper limit, not a practical one.

Note that if an array's elements are bigger than one byte
each, then the theoretical upper limit on element count will be
even lower. For example, an array of eight-byte elements cannot
possibly have more than `SIZE_MAX / 8' array slots to stay
within the allowable limit on overall byte count.
I though I'd found
salvation in FAQ 6.14, but it appears I am not understanding
something.

The array is an array of pointers to structs. Here is an example
using a small array:

/* checks that malloc succeeded, main's return, etc. removed for
brevity */

#include <stdio.h>
#include <stdlib.h>

typedef struct {
int foo;
int bar;
} example_struct;

int main (void) {
example_struct * small_array[1000];
example_struct * a_single_struct ;

a_single_struct = malloc ( sizeof(example_ struct *) );
This line requests enough memory for one struct pointer,
not for one struct. In this sample program you only make
use of the first int in the struct, and that's probably why
you seem to get away with the error. But if you tried to
use the second int you'd be very likely to get into trouble.

Avoiding this and similar errors is the big advantage of
the c.l.c. Approved Allocation Idiom:

a_single_struct = malloc(sizeof *a_single_struc t);

.... or more generally

pointer = malloc(count * sizeof *pointer);

One thing to be wary of when allocating "huge" arrays, even
with this improved form, is that the multiplication may not give
the right answer. If the mathematical product of the two terms
is larger than SIZE_MAX, the result is reduced modulo that
amount plus one and you'll wind up requesting a much smaller
block of memory. Your struct is probably about eight bytes
long; if `count' were `SIZE_MAX / 3', say, the mathematical
product would be about two and two-thirds times SIZE_MAX, and
the eventual result would be about two-thirds SIZE_MAX, or
roughly one-quarter the size you intended.

(Pedantry alert: The above description does not hold on
"exotic" machines where SIZE_MAX < INT_MAX. I've never heard
of such a machine, but the C Standard doesn't forbid them.)
a_single_struct->foo = 4000;
printf ("a_single_stru ct foo: %i \n", a_single_struct->foo);

small_array[900] = a_single_struct ;
printf ("small_arra y 900 foo: %i\n",small_arr ay[900]->foo);

}

This works fine:

a_single_struct foo: 4000
small_array 900 foo: 4000

So far, so good. Now I want to do an array of, say, 3,000,000
members, too large for a simple big_array[3000000] declaration. So I
use the code from faq 6.14:

/* checks that malloc succeeded, main's return, etc. removed for
brevity */

#include <stdio.h>
#include <stdlib.h>

typedef struct {
int foo;
int bar;
} example_struct;

int main (void) {
example_struct * big_array;
example_struct * a_single_struct ;

a_single_struct = malloc ( sizeof(example_ struct *) );
Same error as above.
a_single_struct->foo = 4000;
printf ("a_single_stru ct foo: %i \n", a_single_struct->foo);

big_array = malloc ( 3000000 * sizeof ( example_struct * ) );
This might be the same error as above, but if I understand
your purpose I think the actual error is that big_array is not
declared correctly. You may want

example_struct **big_array;

(The c.l.c. AAI works correctly with this declaration, too.)
big_array[1000000] = a_single_struct ; /* line 20, error below */
printf ("big_array foo: %i\n",big_array[1000000]->foo);
These would be correct with the revised big_array declaration.
As things stand, big_array[1000000] is not a struct pointer, but
a struct instance. If that's what you want, you could use

big_array[1000000] = *a_single_struc t;
printf (... big_array[1000000].foo);
>
}

No go. The compiler (gcc in this case) returns:

test.c: In function 'main':
test.c:20: error: incompatible types in assignment
test.c:21: error: invalid type argument of '->'

So the example in FAQ 6.14 is:

"int *dynarray;
dynarray = malloc(10 * sizeof(int));

...you can reference dynarray[i] (for i from 0 to 9) almost as if
dynarray were a conventional, statically-allocated array (int a[10])"

Given that, I'm confused why

small_array[900] = a_simple_struct ;

works, while

big_array[1000000] = a_simple_struct ;

doesn't.

Is there some obvious error in my code? Have I just embarrassed
myself by displaying my obtusity before the comp.lang.c gods? Or is
there some better method of creating arrays (size_t - 1) ?

Thanks.

--
Eric Sosman
es*****@ieee-dot-org.invalid
Aug 12 '07 #8
On Sun, 12 Aug 2007 13:47:21 +0100, Mark McIntyre wrote:
On Sun, 12 Aug 2007 11:13:38 +0200, in comp.lang.c , Army1987
<ar******@NOSPA M.itwrote:
>>On modern PCs, (size_t)(-1) is one byte less than 4 GB (on 32-bit
processors) , or about 2.8 GB times the human population of the
Earth (on 64-bit processors). You are very likely *not* to have
enough memory,

These days, blade PCs with 8+GB aren't that rare, especially in the
commercial sector.
What kind of processor do they have? How wide is their size_t?
I still think that having more than 4GB on a computer with a 32
bit processor is *very* silly.

--
Army1987 (Replace "NOSPAM" with "email")
No-one ever won a game by resigning. -- S. Tartakower

Aug 12 '07 #9
On Sun, 12 Aug 2007 15:34:35 +0200, in comp.lang.c , Army1987
<ar******@NOSPA M.itwrote:
>>
These days, blade PCs with 8+GB aren't that rare, especially in the
commercial sector.
>What kind of processor do they have?
Itanium and Amd-64, typically.
>I still think that having more than 4GB on a computer with a 32
bit processor is *very* silly.
Its just trickier to use.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Aug 12 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
10205
by: RR | last post by:
Hello I am trying to declare in my object something like double **ma; then do something like ma = new int; so I just want to declare a pointer to a double array and then initialize the double array but I keep getting compiler error if
34
4234
by: Christopher Benson-Manica | last post by:
If an array is sparse, say something like var foo=; foo=4; foo='baz'; foo='moo'; is there a way to iterate through the entire array? --
20
4721
by: Pavel Stehule | last post by:
Hello, Is possible merge two arrays like array + array => array select array_append(array, array); ERROR: function array_append(integer, integer) does not exist
10
9041
by: Ian Todd | last post by:
Hi, I am trying to read in a list of data from a file. Each line has a string in its first column. This is what i want to read. I could start by saying char to read in 1000 lines to the array( i think!!). But I want to use malloc. Each string is at most 50 characters long, and there may be zero to thousands of lines. How do I actually start the array? I have seen char **array etc. At first I tried char *array but I think that gives 50...
10
3171
by: Pete | last post by:
Can someone please help, I'm trying to pass an array to a function, do some operation on that array, then return it for further use. The errors I am getting for the following code are, differences in levels of indirection, so I feel it must have something to do with the way I am representing the array in the call and the return. Below I have commented the problem parts. Thanks in advance for any help offered. Pete
8
2252
by: masood.iqbal | last post by:
All this time I was under the illusion that I understand the concept of multi-dimensional arrays well ---- however the following code snippet belies my understanding. I had assumed all along that a declaration like: int intArray means that there is an array of pointers to int with a size of 5, each of whose elements is an array of int with a size of 3. This definition seemed intuitive to me since a declaration like
3
2848
by: Michel Rouzic | last post by:
It's the first time I try using structs, and I'm getting confused with it and can't make it work properly I firstly define the structure by this : typedef struct { char *l1; int *l2; int Nval; } *arrays; It's supposed to be a structure containing an array of chars, an array of ints and an int. I declare functions like this : arrays *parseline(char *line, int N)
39
19647
by: Martin Jørgensen | last post by:
Hi, I'm relatively new with C-programming and even though I've read about pointers and arrays many times, it's a topic that is a little confusing to me - at least at this moment: ---- 1) What's the difference between these 3 statements: (i) memcpy(&b, &KoefD, n); // this works somewhere in my code
14
1794
by: spreadbetting | last post by:
I'm trying to split a string into an separate arrays but the data is only delimited by a comma. The actual data is one long string but the info is in a regular format and repeats after every five ~'s . i.e the data may be returned as 1.01~11844.69~0.0~0.0~2.0~1.02~117.3~0.0~0.0~0.0~1.03~66.82~0.0~0.0~0.0~1.0­ 4~300.0~0.0~0.0~0.0~
127
4917
by: sanjay.vasudevan | last post by:
Why are the following declarations invalid in C? int f(); int f(); It would be great if anyone could also explain the design decision for such a language restricton. Regards, Sanjay
0
9579
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9422
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10208
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10038
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9987
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9857
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
6662
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5444
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3952
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.