Is this a good way to do this?

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I found this technique for initializing/clearing  arrays -- possibly on stack overflow.

 

int sample[10][zx1];

memset(sample,0,sizeof(sample));

 

I tested it on a sample program and it seems to work, but it bothers me.  It's declared in string.h (says captain obvious) and doesn't seem to be intended for this use.

There were comments that for larger arrays it's faster than using a loop /assign.

 

Opinions?

 

Thanks,

 

hj

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not a LL (language lawyer) but I'm not aware of a case where this would bite you.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

memset is highly optimized so it will be faster than any loop you can write.

Works for ints or any type where the underlying representation of zero is

all-zero bits.

 

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ford2go wrote:
I tested it on a sample program and it seems to work, ...
likewise by a linter.

#include <string.h>
int main()
{
const unsigned int zx1=7;
int sample[10][zx1];
memset(sample,0,sizeof(sample));
return 0;
}

PC-lint Plus Online Demo - Gimpel Software - The Leader in Static Analysis for C and C++ with PC-lint Plus (C11, Visual Studio 2015)

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is the matter with

int sample[10][zx1]={ 0 };

?

It seems simpler to code.

It probably costs the minimum (2 cycles/byte).

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:

What is the matter with

int sample[10][zx1]={ 0 };

?

It seems simpler to code.

It probably costs the minimum (2 cycles/byte).

 

Initialized data like this takes space in in both ROM (flash memory) for the initial values and RAM for the variable itself.  Before entering main() the compiler generated startup code copies the ROM initial values over to the RAM area where the variable itself resides.  All this automagically happens before your first instruction is executed.  So the cost is usable program space in flash memory.

 

Not a problem for small arrays.  But if your array was say 64KB you could run out of program space on your chip.

 

The memset() example takes no additional "hidden" flash space other than the code used inside the function itself.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
What is the matter with int sample[10][zx1]={ 0 };

error: variable-sized object may not be initialized

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So it  boils down to a few things.

Mainly what is zx1 for a thing? Is it a variable and for example used in a function argument?

Or is an at compile time defined constant?

 

The combination of memset() and sizeof is a very common and accepted method to clear data structures.

 

Why is it bothering you?

In C a string is exactly the same as an array of characters. (And it ends with a 0x00 byte).

 

AVR's have a very limited amount of ram. So you should be carefull when declaring variable sized data structures on the stack.

All data declared within functions ( data not declared static that is) is allocated on the stack.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ScottMN wrote:
skeeve wrote: What is the matter with int sample[10][zx1]={ 0 }; ? It seems simpler to code. It probably costs the minimum (2 cycles/byte). Initialized data like this takes space in in both ROM (flash memory) for the initial values and RAM for the variable itself.
Global arrays initialized to zero do not take up data space in ROM.

In this case, we are dealing with an automatic array, alas not of fixed size.

For a fixed size array initialized to zeros, I'd expect the compiler to do the right thing.

That would be essentially OP's memset method.

 

BTW I think the recent C standards guarantee that memset will work.

They require that integers be represented in one (or more?) ways,

all of which represent zero the same way.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the answers. It bothered me because I don't automatically think of an int array as an array of characters.  I understand the concept, but I don't have a lot of experience using it in practice.

 

As for the array I'm using, it's on a PC (sorry), so size isn't a real issue. As for the zx1 parameter, it's there because of something that I try to when I can. The zx1 value will eventually be found in a config file.  I'm trying to put parameters in files so that I can do a little editing without recompiling. I do the same type of thing with an Arduino SD card  data logger.

 

Thanks again,

 

hj

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also:

Remember that sizeof returns the size in bytes.

sizeof an array of 50 bytes is not the same as sizeof an array of 50 integers.

#include <stdio.h>

int main( void) {
	int array[23854];
	
	printf("Size: %d\n", sizeof array);
	printf("Num:  %d\n", sizeof array /  sizeof( int));
}

When I compile & run this on my PC I get:

paul@dualcore:~$ gcc asdf.c -o asdf
paul@dualcore:~$ ./asdf
Size: 95416
Num:  23854

Bit surprized that sizeof( int) is 4 on my 64 bit Linux box.

 

The parameter after sizeof does not always have to be between parentheses, but because it can always be put between parenthesis (just as about anything else) and knowbody cares to bother with the rules  most people get into a habit of always using parentheses here.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Paulvdh wrote:

Bit surprized that sizeof( int) is 4 on my 64 bit Linux box.

 

LP64 is the current Best Practice - see UNIX.org

 

Integer Sizes

 

On 64-bit platforms, you have access to all four integer sizes using the

'natural' types: char, short, int, long, and pointers are of course 64 bits.

 

--Mike