user48730: I'm trying to pass a list of files (located in sketch) to be read using a library I write. List can have different filenames and vary in number of files.
How to pass a this array to my library?
for example:
char *parameterFiles[3] = {"/myIOT_param.json", "/myIOT2_topics.json", "/sketch_param.json"};
EDIT_1
To explain more clearly what are my needs:
Let's say that my library has a class name myIOT2. That class holds an array that contains a list of all filenames (what shown here is not all class). Those names are different from one use of the library to the other, and it might not have all 4 files ( can be also 0 files stored ).
I wish to have the flexibilty not to hard code exact filename in advance, but to pass that array as part of my sketch, as show prior to EDIT_1.
class myIOT2
{
public:    
const char *parameter_filenames[4] = {nullptr, nullptr, nullptr, nullptr}; 


};


user7508: You have to pass both a pointer to the list, and the length of the list
as an extra argument. The signature of the function may be something
like:
void processFiles(const char *fileList[], int fileCount);

Note that const char *fileList[] is just a fancy way of writing
const char **fileList. I find the former more readable, but that is
completely subjective.
Here is a small test code showing this in action:
void processFiles(const char *fileList[], int fileCount)
{
    for (int i = 0; i < fileCount; ++i) {
        Serial.print("Processing file ");
        Serial.println(fileList[i]);
    }
}

const char *parameterFiles[3] = {
    "/myIOT_param.json",
    "/myIOT2_topics.json",
    "/sketch_param.json"
};

void setup() {
    Serial.begin(9600);
    processFiles(parameterFiles, 3);
}

void loop() {}

Alternatively, you may put a “sentinel” at the end of the list: a null
pointer that signifies that the list ends there:
void processFiles(const char *fileList[])
{
    for (const char **p = fileList; *p; ++p) {
        Serial.print("Processing file ");
        Serial.println(*p);
    }
}

const char *parameterFiles[] = {
    "/myIOT_param.json",
    "/myIOT2_topics.json",
    "/sketch_param.json",
    nullptr
};

void setup() {
    Serial.begin(9600);
    processFiles(parameterFiles);
}

void loop() {}


Edit: Answering to EDIT_1.

[My library's] class holds an array that contains a list of all
filenames

First of all, you have to decide who is responsible for storing those
file names: the library or its client. When you write:
const char *parameterFiles[3] = {
    "/myIOT_param.json", "/myIOT2_topics.json", "/sketch_param.json"
};

you are creating 4 arrays: an array of 3 pointers named
parameterFiles, and three arrays of characters holding the file names.
Note that those 3 arrays are anonymous: they are not array
variables. If the client code tries to pass this parameterFiles to
your library, the array identifier will decay to a pointer, and your
library will receive that pointer. What should it do with it?

The library could just keep a copy of the pointer. The client is then
responsible for ensuring that it remains valid for as long as the
library may need it. This practically implies that parameterFiles
should be a global variable, and should not be modified once given to
the library.

The library could make a copy of the array. Then the client is freed
from this responsibility. However, it is still responsible for
ensuring that the pointers that were copied from the array remain
valid, i.e. that the file names stay in the same place in memory.

The library could copy the file names themselves. Then the client
doesn't have any responsibility about keeping pointers valid.


If you choose option 2 or 3, the library will have to hold one or more
arrays. You will then have to choose whether you allocate them
statically, or dynamically with new. Dynamic allocation is more
efficient when the arrays can vary greatly in length, but it can raise
issues of memory fragmentation in RAM-constrained devices.
I cannot tell you which option is best: it depends on your use case. In
any case, whatever you choose, you should document it: the user of the
library should know whether they are responsible for keeping any
pointers valid.
In the following, I will assume option 2 with static allocation. This is
consistent with the code snippets in your question. Also, if the client
provides the file names as string literals, then pointers to these
strings remain always valid.
Here is a toy implementation of the myIOT2 class, where the list of
file names is copied by the constructor into the class:
class myIOT2 : public Printable
{
public:
    static const int maxFileCount = 4;

    myIOT2(const char *fileList[], int count) {
        if (count > maxFileCount)
            count = maxFileCount;  // discard extra files
        fileCount = count;
        for (int i = 0; i < fileCount; i++)
            filenames[i] = fileList[i];
    }

    size_t printTo(Print& p) const {
        size_t count = p.print(F("myIOT2["));
        for (int i = 0; i < fileCount; i++) {
            count += p.print('"');
            count += p.print(filenames[i]);
            count += p.print('"');
            if (i < fileCount - 1)
                count += p.print(", ");
        }
        count += p.print(']');
        return count;
    }

private:
    const char *filenames[maxFileCount];
    int fileCount;
};

Note that, the array of file names being statically allocated, there is
a hard maximum on the number of files that can be stored. I made the
class Printable only for debugging convenience.
And here is an example of this class in use:
const int fileCount = 3;

const char *parameterFiles[fileCount] = {
    "/myIOT_param.json", "/myIOT2_topics.json", "/sketch_param.json"
};

myIOT2 iot(parameterFiles, fileCount);

void setup() {
    Serial.begin(9600);
    Serial.println(iot);
}

void loop() {}

This test sketch prints:
myIOT2["/myIOT_param.json", "/myIOT2_topics.json", "/sketch_param.json"]


48730: <p>I'm trying to pass a list of files (located in sketch) to be read using a library I write. List can have different filenames and vary in number of files.</p>
<p>How to pass a this array to my library?</p>
<p>for example:</p>
<p><code>char *parameterFiles[3] = {&quot;/myIOT_param.json&quot;, &quot;/myIOT2_topics.json&quot;, &quot;/sketch_param.json&quot;};</code></p>
<p><strong>EDIT_1</strong></p>
<p>To explain more clearly what are my needs:
Let's say that my library has a class name <code>myIOT2</code>. That class holds an array that contains a list of all filenames (what shown here is not all class). Those names are different from one use of the library to the other, and it might not have all 4 files ( can be also 0 files stored ).</p>
<p>I wish to have the flexibilty not to hard code exact filename in advance, but to pass that array as part of my sketch, as show prior to EDIT_1.</p>
<pre><code>class myIOT2
{
public:    
const char *parameter_filenames[4] = {nullptr, nullptr, nullptr, nullptr}; 


};
</code></pre>
 7508: <p>You have to pass both a pointer to the list, and the length of the list
as an extra argument. The signature of the function may be something
like:</p>
<pre class="lang-cpp prettyprint-override"><code>void processFiles(const char *fileList[], int fileCount);
</code></pre>
<p>Note that <code>const char *fileList[]</code> is just a fancy way of writing
<code>const char **fileList</code>. I find the former more readable, but that is
completely subjective.</p>
<p>Here is a small test code showing this in action:</p>
<pre class="lang-cpp prettyprint-override"><code>void processFiles(const char *fileList[], int fileCount)
{
    for (int i = 0; i &lt; fileCount; ++i) {
        Serial.print(&quot;Processing file &quot;);
        Serial.println(fileList[i]);
    }
}

const char *parameterFiles[3] = {
    &quot;/myIOT_param.json&quot;,
    &quot;/myIOT2_topics.json&quot;,
    &quot;/sketch_param.json&quot;
};

void setup() {
    Serial.begin(9600);
    processFiles(parameterFiles, 3);
}

void loop() {}
</code></pre>
<p>Alternatively, you may put a “sentinel” at the end of the list: a null
pointer that signifies that the list ends there:</p>
<pre class="lang-cpp prettyprint-override"><code>void processFiles(const char *fileList[])
{
    for (const char **p = fileList; *p; ++p) {
        Serial.print(&quot;Processing file &quot;);
        Serial.println(*p);
    }
}

const char *parameterFiles[] = {
    &quot;/myIOT_param.json&quot;,
    &quot;/myIOT2_topics.json&quot;,
    &quot;/sketch_param.json&quot;,
    nullptr
};

void setup() {
    Serial.begin(9600);
    processFiles(parameterFiles);
}

void loop() {}
</code></pre>
<hr />
<p><strong>Edit</strong>: Answering to EDIT_1.</p>
<blockquote>
<p>[My library's] class holds an array that contains a list of all
filenames</p>
</blockquote>
<p>First of all, you have to decide who is responsible for storing those
file names: the library or its client. When you write:</p>
<pre class="lang-cpp prettyprint-override"><code>const char *parameterFiles[3] = {
    &quot;/myIOT_param.json&quot;, &quot;/myIOT2_topics.json&quot;, &quot;/sketch_param.json&quot;
};
</code></pre>
<p>you are creating 4 arrays: an array of 3 pointers named
<code>parameterFiles</code>, and three arrays of characters holding the file names.
Note that those 3 arrays are <em>anonymous</em>: they are not array
variables. If the client code tries to pass this <code>parameterFiles</code> to
your library, the array identifier will decay to a pointer, and your
library will receive that pointer. What should it do with it?</p>
<ol>
<li><p>The library could just keep a copy of the pointer. The client is then
responsible for ensuring that it remains valid for as long as the
library may need it. This practically implies that <code>parameterFiles</code>
should be a global variable, and should not be modified once given to
the library.</p>
</li>
<li><p>The library could make a copy of the array. Then the client is freed
from this responsibility. However, it is still responsible for
ensuring that the pointers that were copied from the array remain
valid, i.e. that the file names stay in the same place in memory.</p>
</li>
<li><p>The library could copy the file names themselves. Then the client
doesn't have any responsibility about keeping pointers valid.</p>
</li>
</ol>
<p>If you choose option 2 or 3, the library will have to hold one or more
arrays. You will then have to choose whether you allocate them
statically, or dynamically with <code>new</code>. Dynamic allocation is more
efficient when the arrays can vary greatly in length, but it can raise
issues of memory fragmentation in RAM-constrained devices.</p>
<p>I cannot tell you which option is best: it depends on your use case. In
any case, whatever you choose, you should document it: the user of the
library should know whether they are responsible for keeping any
pointers valid.</p>
<p>In the following, I will assume option 2 with static allocation. This is
consistent with the code snippets in your question. Also, if the client
provides the file names as string literals, then pointers to these
strings remain always valid.</p>
<p>Here is a toy implementation of the <code>myIOT2</code> class, where the list of
file names is copied by the constructor into the class:</p>
<pre class="lang-cpp prettyprint-override"><code>class myIOT2 : public Printable
{
public:
    static const int maxFileCount = 4;

    myIOT2(const char *fileList[], int count) {
        if (count &gt; maxFileCount)
            count = maxFileCount;  // discard extra files
        fileCount = count;
        for (int i = 0; i &lt; fileCount; i++)
            filenames[i] = fileList[i];
    }

    size_t printTo(Print&amp; p) const {
        size_t count = p.print(F(&quot;myIOT2[&quot;));
        for (int i = 0; i &lt; fileCount; i++) {
            count += p.print('&quot;');
            count += p.print(filenames[i]);
            count += p.print('&quot;');
            if (i &lt; fileCount - 1)
                count += p.print(&quot;, &quot;);
        }
        count += p.print(']');
        return count;
    }

private:
    const char *filenames[maxFileCount];
    int fileCount;
};
</code></pre>
<p>Note that, the array of file names being statically allocated, there is
a hard maximum on the number of files that can be stored. I made the
class <code>Printable</code> only for debugging convenience.</p>
<p>And here is an example of this class in use:</p>
<pre class="lang-cpp prettyprint-override"><code>const int fileCount = 3;

const char *parameterFiles[fileCount] = {
    &quot;/myIOT_param.json&quot;, &quot;/myIOT2_topics.json&quot;, &quot;/sketch_param.json&quot;
};

myIOT2 iot(parameterFiles, fileCount);

void setup() {
    Serial.begin(9600);
    Serial.println(iot);
}

void loop() {}
</code></pre>
<p>This test sketch prints:</p>
<pre><code>myIOT2[&quot;/myIOT_param.json&quot;, &quot;/myIOT2_topics.json&quot;, &quot;/sketch_param.json&quot;]
</code></pre>
