0

I am writing a C function GetDeviceList() which must return a list of device names found as strings somehow. The number of devices found and of course the device names themselves will vary each time the function is called.

How the function gets the device names is not the scope of this question, but inside the GetDeviceList() function, a char* gets updated in a loop with each new device name found. This char* must then be copied to a list which can be read by the caller.

The function, nor the calling function cannot use dynamic memory.

What would be the best way to get a list of those strings returned from the function. I am thinking of a 2-dimensional char array passed as an output paramater, but not sure.

Engineer999
  • 3,683
  • 6
  • 33
  • 71
  • _The function, nor the calling function **cannot** use dynamic memory._ .. did you mean to say "can"? – yano Nov 15 '22 at 16:19
  • I'm stumped too .. if you have a dynamic amount of data you care about, but can't use dynamic memory, only idea I have is preallocating for a worst-case scenario... ? You can use another parameter/return value to capture length, or terminate it with a [sentinel value](https://en.wikipedia.org/wiki/Sentinel_value) – yano Nov 15 '22 at 16:23
  • It cannot. It must be static. – Engineer999 Nov 15 '22 at 16:24
  • Return value or output parameter are side issues. No dynamic memory means you will have to upper bound the memory needed and provide it as a local, local static, or global. Each choice has potential issues you will have to decide between and deal with. – Avi Berger Nov 15 '22 at 16:25
  • 1
    If the maximum string length is much larger than the average string length, then you can save memory by using an index array, and a string buffer, passed as output parameters. (I'm assuming that dynamic memory is not allowed because you are on a memory constrained device.) – user3386109 Nov 15 '22 at 16:29

2 Answers2

2

This is one possibility:

  • you need a static array of chars that is large enough so it can contain all device names
  • The function returns a buffer to this static array which will contain all device names separated by a null character and terminated by two null characters.

Example: for a 3 devices "AA", "BB" and "CC" GetDeviceList() returns a pointer to these bytes:

'A', 'A', 0, 'B', 'B', 0, 'C', 'C', 0, 0

Something like this:

const char *GetDeviceList()
{
  static char devicelist[1000];   // chooses this constant wisely:
                                  // big enough so it can contain the biggest
                                  // possible device list but not too big 
                                  // in order not to waste memory

  // construct your device list somehow ...
}

...
// Display all devices
const char *pdevice = GetDeviceList();

for (int i = 0; *pdevice != 0; i++)
{
  printf("Device #%d: %s\n", i, pdevice);
  pdevice += strlen(pdevice) + 1;
}

However there is one caveat here: you can obviously not get directly get the nth device name, but I'm sure you'll figure this out if you actually need it.

A 2-dimensional char array passed as an output paramater is another possibility, but you'll waste more memory and the code will most likely be more complicated, but on the other hand you'll be able to access the nth device name directly.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
0

Perhaps int GetDeviceList(size_t size, char **dest)?

  1. Pass into GetDeviceList() a pointer to a buffer of memory and its byte size.

  2. Walking from the front of memory, store a pointer to the copied string, which is at the end of available memory.

  3. Repeat for the N devices.

  4. At any time, if insufficient memory, return -1, else return N.

Memory layout in the end.  
[ptr0][ptr1][ptr2].....[string2][string1][string0]

// Usage
char ptrs[100];
int n = GetDeviceList(sizeof ptrs, &ptrs);
if (n >= 0) {
  for (int i = 0; i < n; i++) {
    printf("<%s>\n", ptrs[i]);
  }
} else {
  puts("Too big");
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256