Is there a better and fast way to initialize a dynamic array?

J

jerry

Consider the following codes:

static int POOL_SIZE 256
static int BUFF_SIZE 1024

static int *buff_pool[POOL_SIZE]={NULL};

void init_buff(int idx)
{
int i;
buff_pool[idx]=(int*)malloc(BUFF_SIZE * sizeof(int));
for (i=0; i<BUFF_SIZE;i+=)
buff_pool[idx] = 1;
}

There is an alternative way is to use memset instead of for loop, but
it is said that there is no guarantee that the machine representation
of zero is all-bits-zero. My codes need to work with different
compiler and machine.

I wonder if there is a better and fast way to initialize the dynamic
array without running the whole for loop?

Thanks

Jerry
 
I

Ian Collins

Consider the following codes:

static int POOL_SIZE 256
static int BUFF_SIZE 1024

static int *buff_pool[POOL_SIZE]={NULL};

void init_buff(int idx)
{
int i;
buff_pool[idx]=(int*)malloc(BUFF_SIZE * sizeof(int));
for (i=0; i<BUFF_SIZE;i+=)
buff_pool[idx] = 1;
}

There is an alternative way is to use memset instead of for loop, but
it is said that there is no guarantee that the machine representation
of zero is all-bits-zero. My codes need to work with different
compiler and machine.

I wonder if there is a better and fast way to initialize the dynamic
array without running the whole for loop?

How about:

enum { POOL_SIZE = 256, BUFF_SIZE = 1024 };

static int *buff_pool[POOL_SIZE]={NULL};

typedef struct X { int buf[BUFF_SIZE]; } X;

static X x;

void init_buff(int idx)
{
buff_pool[idx]=malloc(BUFF_SIZE * sizeof(buff_pool[idx]));

*(X*)buff_pool[idx] = x;
}

int main(void)
{
for( int i = 0; i < BUFF_SIZE; x.buf[i++] = 1);

// stuff.
}
 
B

BartC

There is an alternative way is to use memset instead of for loop, but
it is said that there is no guarantee that the machine representation
of zero is all-bits-zero. My codes need to work with different
compiler and machine.

If the memory represents pointers or floating point values, then perhaps
null or 0.0 isn't represented by zeros. But why should it matter for
integers?

(And if integer zero doesn't have a representation of all-bits-zero, I don't
think using assignment is going to help either.)
 
J

jerry

Consider the following codes:
static int POOL_SIZE 256
static int BUFF_SIZE 1024
static int *buff_pool[POOL_SIZE]={NULL};
void init_buff(int idx)
{
   int i;
   buff_pool[idx]=(int*)malloc(BUFF_SIZE * sizeof(int));
   for (i=0; i<BUFF_SIZE;i+=)
       buff_pool[idx] = 1;
}

There is an alternative way is to use memset instead of for loop, but
it is said that there is no guarantee that the machine representation
of zero is all-bits-zero.  My codes need to work with different
compiler and machine.
I wonder if there is a better and fast way to initialize the dynamic
array without running the whole for loop?

How about:

enum { POOL_SIZE = 256, BUFF_SIZE = 1024 };

static int *buff_pool[POOL_SIZE]={NULL};

typedef struct X { int buf[BUFF_SIZE]; } X;

static X x;

void init_buff(int idx)
{
   buff_pool[idx]=malloc(BUFF_SIZE * sizeof(buff_pool[idx]));

   *(X*)buff_pool[idx] = x;

}

int main(void)
{
   for( int i = 0; i < BUFF_SIZE; x.buf[i++] = 1);

   // stuff.}


Thanks for your reply.

It will need an extra memory block to hold the initial value. It also
need individual initial block for different type, such as long long,
double, etc. It will increase the memory usage. Considering the
memory usage, is there a another way?

Thanks
 
J

jerry

If the memory represents pointers or floating point values, then perhaps
null or 0.0 isn't represented by zeros. But why should it matter for
integers?

(And if integer zero doesn't have a representation of all-bits-zero, I don't
think using assignment is going to help either.)

Thanks for your reply.

Is it the only way that using assignment for floating array?
 
I

Ian Collins

I wonder if there is a better and fast way to initialize the dynamic
array without running the whole for loop?

How about:

enum { POOL_SIZE = 256, BUFF_SIZE = 1024 };

static int *buff_pool[POOL_SIZE]={NULL};

typedef struct X { int buf[BUFF_SIZE]; } X;

static X x;

void init_buff(int idx)
{
buff_pool[idx]=malloc(BUFF_SIZE * sizeof(buff_pool[idx]));

*(X*)buff_pool[idx] = x;

}

int main(void)
{
for( int i = 0; i< BUFF_SIZE; x.buf[i++] = 1);

// stuff.}

Please don't quote signatures and google nonsense.
Thanks for your reply.

It will need an extra memory block to hold the initial value. It also
need individual initial block for different type, such as long long,
double, etc. It will increase the memory usage. Considering the
memory usage, is there a another way?

Life, and programming, is full of compromises. Here the compromise is
speed/space.

Is the cost of an initialisation loop a measurable problem to you?
 
B

Barry Schwarz

Consider the following codes:

static int POOL_SIZE 256
static int BUFF_SIZE 1024

static int *buff_pool[POOL_SIZE]={NULL};

This is a VLA supported only by C99 compilers.
void init_buff(int idx)
{
int i;
buff_pool[idx]=(int*)malloc(BUFF_SIZE * sizeof(int));

Lose the cast. All it does is camouflage an error if you fail to
include stdlib.h.
for (i=0; i<BUFF_SIZE;i+=)

I assume you meant i++ (or perhaps i+=1).
buff_pool[idx] = 1;
}

There is an alternative way is to use memset instead of for loop, but
it is said that there is no guarantee that the machine representation
of zero is all-bits-zero. My codes need to work with different
compiler and machine.


Since you don't attempt to assign 0 to any element of the array, what
difference does it make how zero is represented?

memset stores values in bytes. If you are attempting to initialize an
array of char (any flavor) or any other type whose size is 1, it
should work. If the type has a size greater than one, memset is only
useful if each byte of an element should have the same value (which
for practical purposes limits you to integer types with value 0 but
then you could just as easily use calloc).
I wonder if there is a better and fast way to initialize the dynamic
array without running the whole for loop?

I don't know if it is any better but you could reduce the number of
loop iterations by using memcpy and memmove code along the lines of:

buff_pool[idx][0] = your value;
for (i = 1; i < BUFF_SIZE/2; i,, *= 1)
memcpy(buff_pool[idx],
buff_pool[idx] + i,
i * sizeof *buff_pool[idx]);
memmove(buff_pool[idx],
buff_pool[idx] + BUFF_SIZE/2,
(BUFF_SIZE+1)/2 * sizeof *buff_pool[idx]);

This will work for both non-zero values and non-integer types.
 
B

BartC

Is it the only way that using assignment for floating array?

To initialise a block of floating point numbers to 0.0 where the
representation is unknown?

Assignment is the sure way to do it, but that doesn't mean you have to
assign 0.0 to every element.

For example, assignment can be used to initialise one row, then memcpy() can
be used to copy those 0.0s to the other rows.

And that row can be part of the data, or a special row - or part row - set
aside for that purpose. There are probably other ways of avoiding too many
assignments (perhaps using memset() for platforms that you know for sure use
all-bits-zero, and assignment where that is not the case, using conditional
compilation)
 
E

Eric Sosman

[...]
(And if integer zero doesn't have a representation of all-bits-zero, I
don't think using assignment is going to help either.)

First, assigning zero -- or forty-two, or negative ninety-nine --
to an `int' will work just fine, regardless of the representation of
any of those quantities. You can even safely assign a `signed char'
with value eighty-six to a `long double' variable and be confident that
the latter will then have the value eighty-six, even though the two
representations are almost certainly different.

Second, any integer type with all-bits-zero has the numerical value
zero. It may happen that the type has more than one way to represent
the value zero, but all-bits-zero will be one of them. It may or may
not be the "normal" way to represent a zero, but a zero it will be.

(Note that this is only for *integer* types; there is no similar
guarantee for floating-point, complex, or pointer types.)
 
E

Eric Sosman

[... filling an array with a constant ...]
Is it the only way that using assignment for floating array?

It's certainly not the "only" way. For example, you could
fill element [0] (of an array of any kind at all) manually, then
use memcpy() to copy [0] to [1], then memcpy() again to copy
[0] and [1] to [2] and [3], then again to copy [0] through [3]
to [4] through [7], ... Filling an N-element array this way
uses approximately lg(N) memcpy() calls, each filling twice as
many elements as the one before. (Watch out for the boundary
conditions on the final call, though.)

However, I urge you to consider Ian Collin's question: "Is
the cost of an initialisation loop a measurable problem to you?"
The word "measurable" is of great importance: What have you done
to obtain evidence that array-filling is a performance problem?
What have your measurements shown?
 
K

Keith Thompson

jerry said:
Consider the following codes:

static int POOL_SIZE 256
static int BUFF_SIZE 1024

Missing semicolons.
static int *buff_pool[POOL_SIZE]={NULL};

That initializes each element of buf_pool to a null pointer.
The first is explicit, the others are implicit (elements not
specified in an initializer are initialized to zero converted to
the appropriate type).
void init_buff(int idx)
{
int i;
buff_pool[idx]=(int*)malloc(BUFF_SIZE * sizeof(int));

Drop the cast.
for (i=0; i<BUFF_SIZE;i+=)

i+= what?

It would be *really* helpful if you'd post the actual code you compiled,
copy-and-pasted, not re-typed. Otherwise it can be hard to tell the
difference between transcription errors and the actual problem you're
asking about.
buff_pool[idx] = 1;
}

There is an alternative way is to use memset instead of for loop, but
it is said that there is no guarantee that the machine representation
of zero is all-bits-zero. My codes need to work with different
compiler and machine.


You're setting the elements to 1, not 0. Or was that a typo?

For integer types, there is a guarantee that all-bits-zero is a
representation of 0 (though not necessarily the only such
representation). N1256 6.2.6.2p5:

For any integer type, the object representation where all the
bits are zero shall be a representation of the value zero in
that type.

(This wasn't in the original C99 standard; it was added in one of the
Technical Corrigenda, presumably because all existing implementations
already behaved this way.)
 
I

Ian Collins

Consider the following codes:

static int POOL_SIZE 256
static int BUFF_SIZE 1024

static int *buff_pool[POOL_SIZE]={NULL};

This is a VLA supported only by C99 compilers.

No, it's an error. You can't declare a VLA at file scope.
 
M

Malcolm McLean

void init_buff(int idx)
{
  int i;
  buff_pool[idx]=(int*)malloc(BUFF_SIZE * sizeof(int));
  for (i=0; i<BUFF_SIZE;i+=)
      buff_pool[idx] = 1;

}

I wonder if there is a better and fast way to initialize the dynamic
array without running the whole for loop?

Not really. On some machines you could set a long or long long to
0x0000000100000001, then treat buff_pool as a long *, and you might
initialise the ints faster. But it's very machine specific, and it
makes the code hard to read. It's very much a last resort.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top