Global Array defined within a function

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

Is it possible to create a global array from within a function?

 

I need a 2D array to be created in an "Init" function.

 

It's for a library so each user of the library may need to create smaller or larger arrays.

 

These arrays need to remain unchanged through the life of the program once they are created.

 

Or should I just malloc and use pointers?

 

Thanks.

 

 

 

Whaa ?,.

Last Edited: Sun. Apr 5, 2015 - 03:45 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, if you think about it your situation is a near-degenerate case:  one-time "allocation.  The max size needs to be known.  So just make a global single-dimension array and "use up" that much.

 

Then your "allocation" invocation checks that global "elements" hasn't been set yet (enforcing the one-time) and that x dimension and y dimension multiplied together don't exceed MAX_ELEMENTS.

 

Then elements_x and elements_y are used in an accessor function to pick out the correct element.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Thanks for responding theusch ...

 

.. I probably did not explain well enough.

 

(and keep in mind I am seasoned programmer but ... a beginner to C programming).

 

The project I am working on (my first substantial C project other than Hello World stuff) ...

... I want to be a library that can be used in several devices with different MCU's and memory.

 

These devices will have stack-able modules.

Each module needs an element in a buffer of 2 bytes.

 

So in a sense one could have 20 of these gizmo's and each gizmo could have up to 255 stack-able add ons.

 

It shall be possible to power down the device and add an additional stack item so the buffer size depends on what the end user adds to each device.

I have this INIT function in the library and it's job is to be called by main code which supplies the number of stacks it detected on the current power up.

 

Based on this number I want the INIT function in the library to create the correct size buffer and have this buffer be visible in scope to all other function in the library (module).

 

I think (not sure) that there is no way to re-dim and array in C?

 

So what are my options ... malloc?

 

I want this library to be portable across many devices with the least amount of re-coding.

 

malloc would work here ... no?

 

I would get a piece of memory and a pointer to it by specifying the needed bytes?

... and I think this would be available to the whole module once I return from INIT?

 

Unless there is a way to create an array in the INIT function that is usable outside (globally) and in any other function in the module.

 

Thanks!

 

 

 

Whaa ?,.

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

I'm probably the least qualified person here, but I believe that theusch still has the answer. You ALWAYS need to allow room for the max number of array elements because the user can create that condition at will. So, you can make array max[max_num]. Then you can assign portions of it as required. First module gets elements 0 to x1, 2nd x2 to x3 etc. So module 0 uses max[x+0] , module 1  uses max[x+ offset 1]...  You can use your init to assign the offsets and to let the world know how many modules will be in play.

 

In thinking about malloc, you could probably do it, but I believe that the concept is to make memory available as needed and then get rid of it so that the program doesn't continually grow as it runs.  IMHO, you don't have that issue. You always have to allow for the max array size, so there's no real advantage to not allocating it all.

 

Real programmers may feel free to correct me on any of this.

 

Good Luck,

 

hj

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

ford2go wrote:

I'm probably the least qualified person here, but I believe that theusch still has the answer. You ALWAYS need to allow room for the max number of array elements because the user can create that condition at will. So, you can make array max[max_num]. Then you can assign portions of it as required. First module gets elements 0 to x1, 2nd x2 to x3 etc. So module 0 uses max[x+0] , module 1  uses max[x+ offset 1]...  You can use your init to assign the offsets and to let the world know how many modules will be in play.

 

In thinking about malloc, you could probably do it, but I believe that the concept is to make memory available as needed and then get rid of it so that the program doesn't continually grow as it runs.  IMHO, you don't have that issue. You always have to allow for the max array size, so there's no real advantage to not allocating it all.

 

Real programmers may feel free to correct me on any of this.

 

Good Luck,

 

hj

X2 (or X3)

 

I was initially thinking in malloc, but if you're no going to need to release the used space, then what for?

If you have 5 add-ons instead of 200, are you going to need the unused memory on something?

If not, then just do as it's been told here: use a max_size array.

 

If yes, then just go ahead, use malloc on one variable and ¿treat it like an array later?

I don't see any difference once the array has been created, is there?

 

 

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

In thinking about malloc, you could probably do it, but I believe that the concept is to make memory available as needed and then get rid of it so that the program doesn't continually grow as it runs.

The purpose of malloc is to create space for a variable at run time. There is no mandate that that memory needs to be freed at anytime. What would make the program "continually grow" would be continually using malloc (which is not the case here). There is nothing wrong with using malloc at the start of a program, then never releasing that memory.

Regards,
Steve A.

The Board helps those that help themselves.

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

Thanks to all of you for your feedback.

 

This project is for an automation I/O stack.

There could be dozens of devices that would use this library ... each one using a different sized Micro with different RAM available.

 

I am using a 328p at the moment.

So since there are four possibilities ... Digital Inputs, Digital Outputs, Analog Inputs, Analog Outputs ...

 

... for each unit the address space allows 255 of each point type.

1020 MAX per device ... if they stack that many.

 

I need a buffer for each type with 2 bytes for each DI, DO, AO point and 3 bytes for an AI point (20 bits of resolution).

The highest 4 bits are used as flags.

 

So I am not sure I understand what you are all suggesting.

 

Are you saying you can create an array that would be the MAX possible and not require the RAM to back it up?

 

I am not following ... sorry.

 

(remember ... I'm brand new to C).

Thanks for your patients !!

 

 

 

 

 

 

 

 

Whaa ?,.

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

Are you saying you can create an array that would be the MAX possible and not require the RAM to back it up?

No, if you create it you will certainly need the RAM for it. I think that for the circumstance malloc would be the best choice. But you will have to ensure that the device that it is used on has enough ram to meet the needs of the array. The first line of defense would be to check the returned pointer. If it is NULL then there is certainly not enough room on the device for the table. But you still need to ensure that any RAM allocated afterwards (local variables, stack usage, etc.) has enough room.

Regards,
Steve A.

The Board helps those that help themselves.

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

Thanks Koshchi !!

 

 

That's what I will do then.

 

Those who will use the library will be responsible to make sure they don't define more points in the call to INIT then they have RAM for.

 

 

Whaa ?,.

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

In avr-gcc, the desired array is named _end:

extern uint8_t _end[];

It ends at (uint8_t*)(SP) or sooner.

That should give the init function all the information it needs.

I'd expect similar information to be available on other platforms.

 

All that said, malloc will likely do what you want and might be easier to wrap one's brain around.

Scrutability is an important aspect of reliable code.

 

Another possibility is to give the array one object file for each RAM size.

The one fetched would depend on a symbol defined by the user.

One could use the same source file with multiple set of compiler options:

// HANDLE and ARRAY_SIZE should be "#define-d" with -D options on the compile line
char HANDLE;
unsigned char array[ARRAY_SIZE];

 

Of course, it might be easier to just give the user the source and let said user customize with the appropriate #defines.

Moderation in all things. -- ancient proverb

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

In avr-gcc, the desired array is named _end:

extern uint8_t _end[];

It ends at (uint8_t*)(SP) or sooner.

That should give the init function all the information it needs.

I'd expect similar information to be available on other platforms.

 

All that said, malloc will likely do what you want and might be easier to wrap one's brain around.

Scrutability is an important aspect of reliable code.

 

Another possibility is to give the array one object file for each RAM size.

The one fetched would depend on a symbol defined by the user.

One could use the same source file with multiple set of compiler options:

// HANDLE and ARRAY_SIZE should be "#define-d" with -D options on the compile line
char HANDLE;
unsigned char array[ARRAY_SIZE];

 

Of course, it might be easier to just give the user the source and let said user customize with the appropriate #defines.

 

I tried to delete this second post, but was denied access.

Moderation in all things. -- ancient proverb

Last Edited: Wed. Apr 8, 2015 - 01:48 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried to delete this second post, but was denied access.

You have been found by the Forum Gods to be untrustworthy. All of your future posts will be limited to quips about people from Montana and their relationship with sheep cheeky

Regards,
Steve A.

The Board helps those that help themselves.

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

If you need to determine memory allocation at run time you HAVE to malloc.

Otherwise you make an array of structs that can hold any type and off you go.

 

The struct would most likely contain a union of structs that define each sensor...

typedef struct anytype_T
{
 int Commonthing;

 char another thing;

 union
  {
   mystruct1_t   t1;
   mystruct2_t   t2;
   ...
  }
}

each element will be the largest of mystruct1_t or mystruct2_t ( plus the common data )

anytype_t myBigArray[BIG_THING];

 

 

The static array is only a problem if you are short on RAM

Keith Vasilakes

Firmware engineer

Minnesota

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

keith v wrote:
The static array is only a problem if you are short on RAM
You haven't noticed OP's use case.

OP wants to use the same code on processors with differing amounts of SRAM.

Big enough on one processor might be too big on another.

Moderation in all things. -- ancient proverb