When you are doing string_copy(my_array), you are passing a char (*)[100], i.e. pointer to char[100] array to your function. But your function is expecting a char *[], i.e. array of char pointers, because you have defined your function that way.
You can fix this by making changes so that your function (string_copy()) expects a char (*)[100], instead of a char *[].
For this, you can change your function definition as:
/* Your my_array gets converted to pointer to char[100]
so, you need to change your function parameter
from `char *pointer[]` to `char (*pointer)[100]`
*/
/* static void string_copy(char *pointer []) */
static void string_copy(char (*pointer) [100])
{
strcpy(pointer[0], "Hello ");
strcpy(pointer[1], "world");
}
* Alternative Solution *
A different design/solution would be to change in your main() function so that you are actually passing a char *[], which decays into a char ** - which is fine - to string_copy(). This way you would NOT have to change your string_copy() function.
int main(int argc, const char * argv[]) {
char my_array[10][100];
int tot_char_arrs, i;
char *char_arr_ptr[10];
/* Get total number of char arrays in my_array */
tot_char_arrs = sizeof(my_array) / sizeof(my_array[0]);
// Store all char *
for (i = 0; i < tot_char_arrs; i++)
char_arr_ptr[i] = my_array[i];
/* Actually passing a char *[].
it will decay into char **, which is fine
*/
string_copy(char_arr_ptr);
printf("%s%s\n", my_array[0], my_array[1]);
}
Answer from sps on Stack OverflowWhen you are doing string_copy(my_array), you are passing a char (*)[100], i.e. pointer to char[100] array to your function. But your function is expecting a char *[], i.e. array of char pointers, because you have defined your function that way.
You can fix this by making changes so that your function (string_copy()) expects a char (*)[100], instead of a char *[].
For this, you can change your function definition as:
/* Your my_array gets converted to pointer to char[100]
so, you need to change your function parameter
from `char *pointer[]` to `char (*pointer)[100]`
*/
/* static void string_copy(char *pointer []) */
static void string_copy(char (*pointer) [100])
{
strcpy(pointer[0], "Hello ");
strcpy(pointer[1], "world");
}
* Alternative Solution *
A different design/solution would be to change in your main() function so that you are actually passing a char *[], which decays into a char ** - which is fine - to string_copy(). This way you would NOT have to change your string_copy() function.
int main(int argc, const char * argv[]) {
char my_array[10][100];
int tot_char_arrs, i;
char *char_arr_ptr[10];
/* Get total number of char arrays in my_array */
tot_char_arrs = sizeof(my_array) / sizeof(my_array[0]);
// Store all char *
for (i = 0; i < tot_char_arrs; i++)
char_arr_ptr[i] = my_array[i];
/* Actually passing a char *[].
it will decay into char **, which is fine
*/
string_copy(char_arr_ptr);
printf("%s%s\n", my_array[0], my_array[1]);
}
you need to use a pointer to the array. here is an example with 1 dimension array:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
static void string_copy(char **pointer) {
strcpy(pointer[0], "Hello ");
}
int main(int argc, const char * argv[]) {
char my_array[10];
char * p_array = my_array;
string_copy(&p_array);
printf("%s\n", my_array);
}
You can do it like this:
void sort(char **, int);
int main()
{
char *string_database[5]={'\0'};
string_database[0]="Florida";
string_database[1]="Oregon";
string_database[2]="California";
string_database[3]="Georgia";
sort(string_database, 4);
return 0;
}
void sort(char **str, int n)
{
int i = 0;
for (i = 0; i < n; i++)
printf("The string is= %s\n",str[i]);
}
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void sort(char *strings[], int n);//Function prototype
int main()
{
char *string_database[4]={'\0'};
string_database[0]="Florida";
string_database[1]="Oregon";
string_database[2]="California";
string_database[3]="Georgia";
sort(string_database, 4);
return 0;
}
void sort(char *strings[], int n)
{
int i;
for (i=0; i<n; i++) {
printf("String %d: %s\n", i, strings[i]);
}
}
You usually pass the length of the array along with the array itself. The char *strings[] is really just sintactic sugar though, so if you want to keep the function prototype without parameter names you can use char **strings as well, so that the code could be like this:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void sort(char **, int);//Function prototype
int main()
{
char *string_database[4]={'\0'};
string_database[0]="Florida";
string_database[1]="Oregon";
string_database[2]="California";
string_database[3]="Georgia";
sort(string_database, 4);
return 0;
}
void sort(char **strings, int n)
{
int i;
for (i=0; i<n; i++) {
printf("String %d: %s\n", i, strings[i]);
}
}
Also, as Jite below points out, using a syntax such as char *strings[] might mislead you or another reader of the code into thinking they're dealing with a static matrix, while this is not true; you should therefore opt for the more straightforward char **strings syntax.
Passing an array of strings as parameter to a function in C - Stack Overflow
[C] How to pass an array of strings to a function
How to pass array of strings as function parameter?
How to pass array of strings to a function in C - Stack Overflow
You've already got it.
#include <stdio.h>
static void func(char *p[])
{
p[0] = "Hello";
p[1] = "World";
}
int main(int argc, char *argv[])
{
char *strings[2];
func(strings);
printf("%s %s\n", strings[0], strings[1]);
return 0;
}
In C, when you pass an array to a function, the compiler turns the array into a pointer. (The array "decays" into a pointer.) The "func" above is exactly equivalent to:
static void func(char **p)
{
p[0] = "Hello";
p[1] = "World";
}
Since a pointer to the array is passed, when you modify the array, you are modifying the original array and not a copy.
You may want to read up on how pointers and arrays work in C. Unlike most languages, in C, pointers (references) and arrays are treated similarly in many ways. An array sometimes decays into a pointer, but only under very specific circumstances. For example, this does not work:
void func(char **p);
void other_func(void)
{
char arr[5][3];
func(arr); // does not work!
}
char* parameters[513]; is an array of 513 pointers to char. It's equivalent to char *(parameters[513]).
A pointer to that thing is of type char *(*parameters)[513] (which is equivalent to char *((*parameters)[513])), so your function could look like:
void f( char *(*parameters)[513] );
Or, if you want a C++ reference:
void f( char *(¶meters)[513] );
The warning is exactly right. Your function wants an array of pointers. You're giving it an array of arrays.
Expected:
sep_foo:
+------+ +-----+
|char**|--> 0: |char*|-->"string1"
+------+ +-----+
1: |char*|-->"string2"
+-----+
*sep_foo_qty-1: |... |
+-----+
What you provided:
sep_foo:
+--------------------------------+
0: | char[MAX_STRING_LENGTH] |
+--------------------------------+
1: | char[MAX_STRING_LENGTH] |
+--------------------------------+
MAX_QTY-1: | ... |
+--------------------------------+
An array with elements of type X can "decay" into a pointer-to-X, or X*. But the value of X isn't allowed to change in that conversion. Only one decay operation is allowed. You'd need it to happen twice. In your case, X is array-of-MAX_STRING_LENGTH-chars. The function wants X to be pointer-to-char. Since those aren't the same, the compiler warns you. I'm a bit surprised it was just a warning since nothing good can come from what the compiler allowed to happen.
In your function, you could write this code:
char* y = NULL;
*sep_foo = y;
That's legal code since sep_foo is a char**, so *sep_foo is a char*, and so is y; you can assign them. But with what you tried to do, *sep_foo wouldn't really be a char*; it would be pointing to an array of char. Your code, in effect, would be attempting to do this:
char destination[MAX_STRING_LENGTH];
char* y = NULL;
destination = y;
You can't assign a pointer into an array, and so the compiler warns that the call is no good.
There are two ways to solve this:
Change the way you declare and allocate
sep_fooon the calling side so it matches what the function expects to receive:char** sep_foo = calloc(MAX_QTY, sizeof(char*)); for (int i = 0; i < MAX_QTY; ++i) sep_foo[i] = malloc(MAX_STRING_LENGTH);or, equivalently
char* sep_foo[MAX_QTY]; for (int i = 0; i < MAX_QTY; ++i) sep_foo[i] = malloc(MAX_STRING_LENGTH);Change the prototype of the function to accept what you're really giving it:
int parse(const char *foo, char sep_foo[MAX_QTY][MAX_STRING_LENGTH], int *sep_foo_qty);
Parameter 2 should be
char sep_foo[][MAX_STRING_LENGTH]
To clarify, you are passing a pointer to parse() and treating it as a pointer to a pointer. A multidimensional array in C is NOT an array of pointers. It is a single block of memory that is pointed to by the array variable. You cannot dereference it twice.
I have an array of strings saved as a 2d array i found it easier to parse from a .txt file. char strings[4][255]. I want to put it as a function parameter to be able to print its contents. I've tried the following but none have worked :( Segfault 11
func(char strings[][255]) func(char strings[][]) func(char ** strings) func(char * strings[])
As coded, printer takes a string and prints every final substring. You pass *words, which is the same as words[0], ie: the first string in the 2D array.
To pass a pointer to the array, the type of the argument should be char array[][10](*).:
#include <stdio.h>
char words[][10] = { "madam", "Russia", "India", "Japan",
"China", "Brazil", "Mexico" };
int size = sizeof(words) / sizeof(words[0]);
void printer(char words[][10], int len);
int main() {
printer(words, size);
return 0;
}
void printer(char words[][10], int len) {
for (int i = 0; i < len; i++) {
printf("%s\n", array[i]));
}
}
Note however that you could also define array as an array of pointers to character strings char *array[]. This would allow for strings of any length, not limited to 9 characters plus a null terminator.
The code would be changed to this:
#include <stdio.h>
char *words[] = { "madam", "Russia", "India", "Japan",
"China", "Brazil", "Mexico" };
int size = sizeof(words) / sizeof(words[0]);
void printer(char *words[], int len);
int main() {
printer(words, size);
return 0;
}
void printer(char *words[], int len) {
for (int i = 0; i < len; i++) {
printf("%s\n", array[i]));
}
}
The array words is initialized from string literals, which must not be changed, so it would be better to define it as const char *array[] and modify printer accordingly. Note also that printf("%s\n", array[i])) is equivalent to puts(array[i]) (good compilers detect this equivalence and generate the call to puts in both cases):
#include <stdio.h>
const char *words[] = { "madam", "Russia", "India", "Japan",
"China", "Brazil", "Mexico" };
int size = sizeof(words) / sizeof(words[0]);
void printer(const char *words[], int len);
int main() {
printer(words, size);
return 0;
}
void printer(const char *words[], int len) {
for (int i = 0; i < len; i++) {
puts(array[i]);
}
}
(*) The function does not receive an actual 2D array as argument, but a pointer to the array of arrays, which technically has type char (*)[10] but the compiler will accept both syntaxes equivalently and char array[][10] is simpler and more readable
You are just printing the 1st element of words[0], because you have passed words[0] which is equivalent to *words.
Also, to print the whole array of pointers, you need char [][10] as your parameter in function printer().
Note: You can put printer() function above main() function, then there will be no need for forward declaration.
Final Code
#include <stdio.h>
char words[][10] = {"madam", "Russia", "India", "Japan", "China", "Brazil", "Mexico"};
int size = sizeof(words) / sizeof(*words);
void printer(const char array[][10], int len){
for(int i = 0; i < len; i++){
puts(array[i]);
}
}
int main(void) {
printer(words, size);
return 0;
}
Does this work?
#include <string.h>
#include <assert.h>
#include <stdio.h>
int format_parameters(char *str, char *param[], size_t nparam)
{
char **next = param;
char **end = param + nparam;
char *data = str;
assert(str != 0 && param != 0 && nparam != 0);
while (next < end && *data != '\0')
{
*next++ = data;
data = strchr(data, ' '); // Choose your own splitting criterion
if (data == 0)
break;
*data++ = '\0';
}
return(next - param);
}
int main(void)
{
char str[] = "a b c d";
char *param[5];
int nvals = format_parameters(str, param, 5);
int i;
for (i = 0; i < nvals; i++)
printf("Param %d: <<%s>>\n", i+1, param[i]);
return 0;
}
The return value is the number of parameters found. If you pass an empty string, that would be 0. Beware leading, trailing and repeated blanks; the code works - but maybe not as you want it to.
This is entirely about memory allocation.
If you allocate static memory for param before the function is called, the memory will exist in that scope.
Otherwise take a look at dynamic allocation, it will exist until you tell it to go away.
If your string array will remain with those sizes then the best way is to use
void function (char (* cppStringArray)[512], size_t num_strings);
pass as
function(cStringArray, sizeof(*cStringArray)/sizeof(cStringArray));
Problem is that char** is not equivalent to char (*)[512]. The former is a pointer to pointer to char. The latter is a pointer to a block of 512 characters.
Define the function like below.
void function (char cppStringArray[5][512]);
char array_slave_1[128][128]
This is 2-dimensional array of char as paramter:
int array_length(char *a[])
This is array of pointers to char (which might be C strings, but could be other char/byte buffers, or single chars too). Except because it is a function parameter, it really is pointer to pointer, so if you are a novice you'd be better off writing what it really is, to avoid getting confused:
int array_length(char **a)
Types of array_slave_1 and a are fundamentally different, and incompatible.
If you want to make your function take the array as parameter, you could do:
int array_length(char a[][128])
which is same as this (note the extra () compared to code in question, they matter!), because array parameters really are pointers, so you have a pointer to one or more char[128] buffers:
int array_length(char (*a)[128])
Then you need a different way to determine the array length, though. Perhaps empty string means end of strings? That's up to you, really.
Alternative is to change your array to be array of pointers:
char *array_slave_1[128]; // 128 pointers to char buffer or C string
// remember that you must allocate the space of each string!
Perhaps you are just "over complicating" things.
Here is a "best guess" at what you might be trying to achieve (based on allocating room for 128x strings, each up to 127 bytes (plus a null terminator.)
#include <stdio.h>
#include <string.h>
int main() {
char array_slave_1[ 128 ][ 127 + 1 ]; // notation helps signify this is a string
strcpy( array_slave_1[ 0 ], "Hello World!" );
strcpy( array_slave_1[ 1 ], "Foobar" );
for( int i = 0; i < 2; i++ )
printf( "'%s' length %d\n", array_slave_1[ i ], strlen( array_slave_1[ i ] ) );
return 0;
}
Output
'Hello World!' length 12
'Foobar' length 6
strlen() has already been done in the standard C library.
Inside the function parameter list, char arr[] is absolutely equivalent to char *arr, so the pair of definitions and the pair of declarations are equivalent.
void function(char arr[]) { ... }
void function(char *arr) { ... }
void function(char arr[]);
void function(char *arr);
The issue is the calling context. You provided a string literal to the function; string literals may not be modified; your function attempted to modify the string literal it was given; your program invoked undefined behaviour and crashed. All completely kosher.
Treat string literals as if they were static const char literal[] = "string literal"; and do not attempt to modify them.
function("MyString");
is similar to
char *s = "MyString";
function(s);
"MyString" is in both cases a string literal and in both cases the string is unmodifiable.
function("MyString");
passes the address of a string literal to function as an argument.