passing an array of string to a function - c

My program is
#define ARRLEN 10
#define SIZEALCO 128
#define MAX_STRING_LENGTH 12
in main function,
char TYPEDATA_XML_FN[ARRLEN][SIZEALCO];
char TYPEDATA_MD5_FN[ARRLEN][SIZEALCO];
char identifier[ARRLEN][MAX_STRING_LENGTH];
char Temppath[SIZEALCO];
int arraynum;
// ...
arraynum = 0;
for(arraynum = 0; arraynum <ARRLEN; arraynum++)
{
/* Create the file name with the path*/
strcpy(Temppath,"/fw/TYPEDATA/");
nameFil(Temppath,identifier[arraynum],TYPEDATA_XML_FN[arraynum],TYPEDATA_MD5_FN[arraynum]);
}
subfunction is :
void nameFil(char *SourPath,char *InPinName,char *FilePathNameXml,char *FilePathNameMd5)
{
sprintf(FilePathNameXml, "%s\\%s_TYPEDATA.XML",SourPath,InPinName);
sprintf(FilePathNameMd5, "%s\\%s_TYPEDATA.MD5",SourPath,InPinName);
}
I checked with your example. I used (trial)
char** a = calloc(ARRLEN, sizeof(char *));
for(i = 0; i < ARRLEN ; ++i)
a[i] = ucmalloc(MAX_STRING_LENGTH);
pase(a);
subfunction :
void pase(char b[ARRLEN][MAX_STRING_LENGTH])
{
// ...
}
Now I got the warning message as "warning: passing arg 1 of `pase' from incompatible pointer type".
Actually, I would like to pass the full string array identifier,TYPEDATA_XML_FN,TYPEDATA_MD5_FN. Now I am passing single string to the subfunction. Kindly guide me. Thank you

The prototype void pase(char b[ARRLEN][MAX_STRING_LENGTH]) is rather mis-leading,
void pase(char b[][MAX_STRING_LENGTH])
would be better, since otherwise there is the implication of bounds checking (the first array dimension is ignored).
The reason why you get "incompatible pointer type" is because a is an array of pointers. If a was incremented (as a pointer itself) then the address would increase by the size of a pointer. However, b is an array of arrays of size MAX_STRING_LENGTH, so if b was incremented then the value would increase by MAX_STRING_LENGTH.
The way you have allocated the array a will (probably) not give you contiguous memory, which is what is required here. You could achieve what you want using an array of pointers, but you really must decide what you want to do. If you want to use [][] notation then you need to
calloc(MAX_STRING_LENGTH,ARRLEN);

You are getting confused because although an one dimensional array char[] behaves like a pointer char *, in two dimensions a char[][N] is not convertible to a char **, being actually more like a (*char)[N] (pointer to arrays of length n of char).
So if you want to make a function that receives a two dimensional array, you have two choices:
Use pointers to pointers:
void f(char ** array, int nrows, int ncols);
To create a char**, do like you are already doing now: create an array for pointers and call malloc for each one of them.
Use two dimensional arrays:
void f(char array[][NCOLS], int nrows);
//note: NCOLS is a compile time constant now
//NROWS is the first dimension and can be omited from array[NROWS][NCOLS]
The tricky bit is malloc-ing a two dimensional array:
char (*my_array)[NCOLS];
//my_identifiers is a pointer to arrays of length NCOLS
// it can be passed to any function expecting a car[][NCOLS]
my_array = malloc(number_of_rows*(sizeof *my_array));
You can also make it easier to understand all of this with a good choice of typedefs:
typedef char MY_STRING[MAX_STR_LENGTH];
//define my strings as arrays of MAX_STRING_LENGTH
void f(MY_STRING array[]);
...
MY_STRING *arr = malloc(nstrings*sizeof(MY_STRING));
f(arr);

Related

I don't understand this code arrays and pointers

I learned pointers and arrays already but I don't know what ** or && is used for and when trying to understand this line im not sure what this is.
int main() {
srand(time(NULL));
int n, m, option, row, col, flagCount = 0;
char **flags, **board;
im not sure what's being declared in the 4th row also those pointers at list I think they are are later in the program being sent to this function .
char **creatArray(int n)
what is this (**) used for in the function type?
* is a pointer type, ** is a pointer type to a pointer, for example: int* p;, meaning that p is a pointer type that points to int, and if you need a pointer type to this p pointer, you can do the following definition: int** test = &p; At this point test is a pointer to p, its type is int**.
char *flag;
it means that flag is a pointer which will hold the address of character data type
char **flag;
it means that flag is a pointer which will hold the address of a "POINTER" which is pointer to a character data type
enter image description here
When you use a pointer '*' you can create for example an array when you allocate memory for multiple chars. Example char *word = malloc(10*sizeof(char)). Your word has now space for 10 chars. When you want to create a sentence you need multiple words so you can create a two dimensional array. You can say char *sentence = malloc(10*sizeof(word)).
In c double pointer are often used to create a two dimensional array.
When your function create a new game board of size n*n then it will return the array.
So for example you call char **board = **newArray(n);
In c you can create an array like char array[] or you can create an like char *array. This is the same because an array in C is a pointer to the first element of the array. But the problem is you can't return an array like this from a function you need to return the pointer. So char[] function() is not working you need to say char *function(). And this is the case in your example you create a new two dimensaional array for your board and return the pointer to the first element (pointer) of the array that is why you call your function char** and not char[][].

array of pointers to ints? or pointer to an array of ints?

I have noticed that pointers are 4 bytes while ints are 2 bytes. When I make a declaration such as:
int * myGreatArray[50];
am I declaring an array of 50 pointers to ints? I thought I was declaring a pointer to an array of integers, which is functionally the same as
int ** myGreatArray = malloc(50 * sizeof(int *));
However, I was informed by this tutorial that such a declaration is actually creating an array of pointers to ints, which seems more inefficient than just simply storing the ints themselves.
https://www.tutorialspoint.com/cprogramming/c_array_of_pointers.htm
Can anyone clarify this for me?
It is a question of precedence of operators.
int * myGreatArray[50]; // array of 50 pointers to int
int (*ptArray)[50]; // pointer to array of 50 ints
int * myGreatArray[50];
is indeed creating an array of pointers to int. If you wanted a pointer to an array of int, it would be written as
int (*myGreatArray)[50];
However, I was informed by this tutorial that such a declaration is actually creating an array of pointers to ints, which seems more inefficient than just simply storing the ints themselves.
Depends on what you are trying to do. It's useful for creating "jagged" 2D arrays, where each "row" can be a different length:
for ( size_t i = 0; i < 50; i++ )
myGreatArray[i] = malloc( sizeof *myGreatArray[i] * some_length(i) );
where some_length(i) represents the number of elements for a particular "row". It can also be used to point to existing arrays:
int foo[] = {1, 2, 3};
int bar[] = {4, 5, 6, 7, 8};
...
int *myGreatArray[] = {foo, bar, ...};
When you are writing this declaration:
int * myGreatArray[50];
its the same as writing -
int ** myGreatArray = malloc(50 * sizeof(int *));
and you will get an array of 50 pointers to int, while if you will use this line:
int myGreatArray[50];
or:
int* myGreatArray = (int*)malloc(sizeof(int)*50)
you will get an array of 50 int variables.
I hope that my comment was helpful for you :D
and if you still have questions ask and i will answer you ASAP.
Have a great day ;)
Declaring an array:
int * myGreatArray[50];
This is an array that stores 50 pointers to int. Be aware that it does not allocate the storage for those integers, just for the storage of the pointers.
int arr[50]; //array of 50 integers
int * parr = arr; /*pointer to an int, which may be
the beginning of an array*/
Passing to a function:
This is exactly what I was hoping I'd discover, so when passing an array into a function, is it more efficient to pass a pointer to an array as opposed to an array of pointers? I'd think yes. – Michael Hackman
The two function definitions:
void doStuffToArray(int ** array, size_t len)
{
//dostuff
}
and
void doStuffToArray(int * array[], size_t len)
{
//dostuff
}
are functionally identical. When you pass an array, the function actually receives a pointer to the array.
To call the functions, you can pass the array (devolves to pointer to the beginning of the array, (recommended) or a pointer to the beginning of the array (not recommended for full arrays, but is useful to pass pointers to sections of arrays):
int arr[10] = {};
doStuffToArray(arr, sizeof(arr)/sizeof(arr[0])); //functionally identical
doStuffToArray(&arr[0], sizeof(arr)/sizeof(arr[0])); //functionally identical
When passing an array of pointers, there are two function definitions that can be used, e.g. argv is an array of pointers to char arrays:
int main(int argc, char * argv[]){return 0;} //functionally identical
int main(int argc, char ** argv ){return 0;} //functionally identical
My advice is to use the array notation (with the []) as this is a declaration of intent, instead of the equivalent but more ambiguous pointer notation.
If you know how big the array is, then argv could have been defined as an 'array of arrays' char argv[][] which would be great, but can't be done. When defining a function, only the first array dimension can be undefined, any further dimensions have to be defined. If you know how big it is though, there is nothing to stop you from creating a function:
void doStuffToMyArray( int array[][10]){
/*...*/
}
In fact in this call
malloc(50 * sizeof(int));
there is allocated neither array.:) There is allocated an extent of memory. You can interpret it in various ways.
For example you can write
int *myGreatArray = malloc(50 * sizeof(int));
char *myGreatArray = malloc(50 * sizeof(int));
or even like
long *myGreatArray = malloc(50 * sizeof(int));
provided that sizeof( long ) is equal to 2 * sizeof( int ).
or like
int ( *myGreatArray )[50] = malloc(50 * sizeof(int));
The only requirement is that there was allocated enough memory for the object(s) you are going to store there.
If you want to allocate dynamically an extent of memory for an array similar to this declaration
int * myGreatArray[50];
then you should write
int ** myGreatArray = malloc(50 * sizeof(int *));
^^^^^^ ^^^^^
If you want to allocate dynamically an extent of memory for an array similar to this declaration
int myGreatArray[50];
that is an array of 50 objects of type int then you should write
int * myGreatArray = malloc(50 * sizeof(int));
^^^^^ ^^^^^

how to get the value from the array in C?

I have a two dimensional array like this:
void getC(int **p)
{
*p = &c[0][0];
}
int c[10][10];
int *a;
getC(a);
a[0][0];
it says error: no match for 'operator[]' in `a[0][0];` what is the problem and how to fix it?
You're compiling a C program with a C++ compiler. Watch out!
You need to put the definition of c above the getC function (or provide a forward declaration).
You have statements outside of a function, which isn't allowed in C. Wrap the int *a and subsequent lines with int main(void) { ... }
You need a & to make your getC() call legal - you're passing an int *, but it expects int **:
getC(&a);
The statement a[0][0] has no effect, and is anyway wrong since a is just an int *; you can't dereference it twice.
You should probably get a beginner C book and start working through it.
Essentially you are sort of downgrading the array/pointer from an int (*)[10] (pointer to array of 10 int) to a simple int pointer, by just returning the address of the first element of the 2dim array. While this is techically correct (the address of one element of the 2dim array is of course an int*), the information about the structure/layout of the ints in the array is lost, so the resulting a-ptr doesn't now anything about the fact that the int was part of a [10][10] structure.
In your case, the only way to get to the array elements would be to multiply your way through the int arrays, based on your own knowledge that at address a there are 100 ints organized 10x10:
int *a;
getC(&a);
...= a[10*x + y]; // equivalent of c[x][y];
.
However, essentially, the correct way (completely preserving types) would be
int c[10][10];
void getC(int (**p)[10]) // pointer to pointer to array of 10 ints
{
*p = c; // c itself can seamlessly change into a pointer to one sub-element
// (i.e. pointer to array of 10)
}
int main()
{
int (*a)[10]; // pointer to array(s) of 10 ints
int q;
getC(&a);
q= a[9][9];
...
}
The same again with one more dimension level (probably the most intutive solution):
However, essentially, the correct way (completely preserving types) would be
int c[10][10];
void getC(int (**p)[10][10]) // pointer to pointer to array of 10x10 ints
{
*p = &c; // &c can seamlessly change into a pointer to 10x10 ints
}
int main()
{
int (*a)[10][10]; // pointer to array(s) of 10x10 ints
int q;
getC(&a); // pass adress of pointer to 10x10 ints
q= (*a)[9][9]; // need *a in brackets to derference the pointer (operator precedence)
...
}

passing a pointer to 2D array of pointers in C

I have seen some of the other answers on this topic but dont really understand them enough to fit them to my problem. I have a 2D array of pointers to char that I want to pass to a function.
If the array is declared: char *params[50][50]; (50 is just picked arbitrarily)
and the function prototype is: void test (char ***results);
How would I call the function? everything I try ends up with an incompatible pointer warning
Also what is the most correct way to then refer to the members of the array while inside the function? is it simply: results[x][y]; ?
Thanks
you can't, pointers to pointers and pointers to arrays are different things.
void test (char *results[50][50]);
void test (char *results[][50]);
void test (char *(*results)[50]);
are all equivalent prototypes for the function that you are looking for.
Suplement: If you want to use the same function for arrays with varying lenght for the dimension you'd have to use VLA (variable length array) as function arguments:
void test (size_t n, char *results[n][n]);
void test (size_t n, char *results[][n]);
void test (size_t n, char *(*results)[n]);
This only works if you have a compiler that is conforming to C99.
Observe that the parameter for the size comes before the array, such that it is known there.
Also you don't have to declare the arrays themselves with variable length to use this feature for the function parameters. But if you do be careful that you don't allocate large matrices on the stack, otherwise you may easily have a stackoverflow.
If you declare an array as
char *array[N][M];
and pass it to a function as
test(array)
then the prototype to the function will need to be either
void test(char *(*arr)[M])
or
void test(char *arr[][M])
In either case, arr has type "pointer to M-element array of pointer to char". This is not the same type as char ***, and there's no really good or clean way to convert between the two.
Had you allocated dynamcally allocated array in the following manner, then the prototype would be correct:
char ***array = malloc(sizeof *array * N);
if (array)
{
size_t i;
for (i = 0; i < N; i++)
{
array[i] = malloc(sizeof *array[i] * M);
if (array[i])
{
size_t j;
for (j = 0; j < M; j++)
{
array[i][j] = some_initial_pointer_value();
}
}
}
}
Note that in this case, the type of array is char ***.
If you're working with arrays declared as T a[M][N], and you want to write a function that will accept arrays of different sizes, then you can either use the VLA syntax as suggested by Jens, or you could do something like this:
void test(char **a, size_t rows, size_t cols)
{
size_t i, j;
...
some_pointer_value = a[i * rows + j];
...
a[i * rows + j] = some_pointer_value;
}
...
test(&array[0][0], 50, 50);
In this case, we explicitly pass the address of the first element of the array and the array dimensions as separate parameters. Within the body of test we treat the array as having 1 dimension (char *a[rows * cols]) and compute the offset manually. Note that this only works for arrays that are contiguously allocated; this won't work with the version that does piecemeal allocation for each row in the array above.
My C is a little rusty but:
char *params[][];
is a 2D array of char * pointer, not char. If you wanted a 2D char array it is defined as:
char params[valuex][valuey];
Iit will be static memory allocation, only available in definition scope, i mean you leave the scope you loose the array if it is not the behaviour you are looking for try dynamic allocation).
You can then pass this array to a function by defining the function prototype as:
void foo(char param[valuex][valuey] );
Regards

How to qsort an array of pointers to char in C?

Suppose I have an array of pointers to char in C:
char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };
And I wish to sort this array using qsort:
qsort(data, 5, sizeof(char *), compare_function);
I am unable to come up with the compare function. For some reason this doesn't work:
int compare_function(const void *name1, const void *name2)
{
const char *name1_ = (const char *)name1;
const char *name2_ = (const char *)name2;
return strcmp(name1_, name2_);
}
I did a lot of searching and found that I had to use ** inside of qsort:
int compare_function(const void *name1, const void *name2)
{
const char *name1_ = *(const char **)name1;
const char *name2_ = *(const char **)name2;
return strcmp(name1_, name2_);
}
And this works.
Can anyone explain the use of *(const char **)name1 in this function? I don't understand it at all. Why the double pointer? Why didn't my original function work?
Thanks, Boda Cydo.
If it helps keep things straight in your head, the type that you should cast the pointers to in your comparator is the same as the original type of the data pointer you pass into qsort (that the qsort docs call base). But for qsort to be generic, it just handles everything as void*, regardless of what it "really" is.
So, if you're sorting an array of ints, then you will pass in an int* (converted to void*). qsort will give you back two void* pointers to the comparator, which you convert to int*, and dereference to get the int values that you actually compare.
Now replace int with char*:
if you're sorting an array of char*, then you will pass in a char** (converted to void*). qsort will give you back two void* pointers to the comparator, which you convert to char**, and dereference to get the char* values you actually compare.
In your example, because you're using an array, the char** that you pass in is the result of the array of char* "decaying" to a pointer to its first element. Since the first element is a char*, a pointer to it is a char**.
Imagine your data was double data[5] .
Your compare method would receive pointers (double*, passed as void*) to the elements (double).
Now replace double with char* again.
qsort is general enough to sort arrays consisting of other things than pointers. That's why the size parameter is there. It cannot pass the array elements to the comparison function directly, as it does not know at compile time how large they are. Therefore it passes pointers. In your case you get pointers to char *, char **.
The comparison function takes pointers to the type of object that's in the array you want to sort. Since the array contains char *, your comparison function takes pointers to char *, aka char **.
Maybe it is easier to give you an code example from me. I am trying to sort an array of TreeNodes and the first few lines of my comparator looks like:
int compareTreeNode(const void* tt1, const void* tt2) {
const TreeNode *t1, *t2;
t1=*(const TreeNode**)tt1;
t2=*(const TreeNode**)tt2;
After that you do your comparison using t1 and t2.
from man qsort:
The contents of the array are sorted in ascending
order according to a comparison function pointed to by
compar, which is called with two arguments that **point**
to the objects being compared.
So it sounds like the comparison function gets pointers to the array elements. Now a pointer to a char * is a char **
(i.e. a pointer to a pointer to a character).
char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };
is a statement asking the compiler for an array of size 5 of character pointers. You have initialized those pointers to string literals, but to the compiler, it's still an array of five pointers.
When you pass that array into qsort, the array of pointers decays into a pointer pointing to the first element, in accordance with C array parameter passing rules.
Therefore you must process one level of indirection before you can get to the actual character arrays containing the constants.
#bodacydo here is a program that may explain what other programmers are trying to convey but this would be in context of "integers"
#include <stdio.h>
int main()
{
int i , j;
int *x[2] = {&i, &j};
i = 10; j = 20;
printf("in main() address of i = %p, address of j = %p \r\n", &i, &j);
fun(x);
fun(x + 1);
return 0;
}
void fun(int **ptr)
{
printf("value(it would be an address) of decayed element received = %p, double dereferenced value is %d \r\n",*ptr, **ptr);
printf("the decayed value can also be printed as *(int **)ptr = %p \r\n", *(int **)ptr );
}
qsort() passes a pointer to the user-defined comparison function and as you have a char * (pointer to char array) hence your comparison function should dereference from pointer to pointer hence char **.

Resources