I think the whole concept of array and array of chars in C is quite confusing. Can you please tell me if my reasoning is correct?
I have an array of array of char like this
char * array[2];
for(i=0;i<2;i++) {
array[i]=calloc(100,sizeof(char));
}
array[0] = strcpy(array[0], "blah");
array[1] = strcpy(array[1], "blahblah");
Now i want to put this array in the field of a struct (that field has type char**)
Can I go like this?
my_struct.array_field = &(array[0])
or is it a mistake?
Just assign array
my_struct.array_field = array
array is converted to char **.
And note that array is not an array of array of char, it is an array of (five) pointers to char.
No need of
array[0] = strcpy(array[0], "blah");
array[1] = strcpy(array[0], "blahblah");
although no harm except confusion. You can copy strings by just changing it to
strcpy(array[0], "blah");
strcpy(array[0], "blahblah");
Related
Can I consider *str[10] as two dimensional array ?
If I declare char *str[10]={"ONE","TWO","THREE"} how we can access single character ?
This record
char str[10];
is a declaration of an array with 10 elements of the type char, For example you can initialize the array like
char str[10] = "ONE";
This initialization is equivalent to
char str[10] = { 'O', 'N', 'E', '\0' };
all elements of the array that are not explicitly initialized are zero-initialized.
And you may change elements of the array like
str[0] = 'o';
or
strcpy( str, "TWO" );
This record
char *str;
declares a pointer to an object of the type char. You can initialize it for example like
char *str = "ONE";
In this case the pointer will be initialize by the address of the first character of the string literal.
This record
char * str[10];
is a declaration of an array of 10 elements that has the pointer type char *.
You can initialize it as for example
char * str[10] = { "ONE", "TWO", "THREE" };
In this case the first three elements of the array will be initialized by addresses of first characters of the string literals specified explicitly. All other elements will be initialized as null pointers.
You may not change the string literals pointed to by elements of the array. Any attempt to change a string literal results in undefined behavior.
To access elements of the string literals using the array you can use for example two subscript operator. For example
for ( sisze_t i = 0; str[0][i] != '\0'; ++i )
{
putchar( str[0][i] );
}
putchar( '\n' );
If you want to change strings then you need to declare for example a two dimensional array like
char str[][10] = { "ONE", "TWO", "THREE" };
In this case you can change elements of the array that are in turn one-dimensional arrays as for example
str[0][0] = 'o';
or
strcpy( str[0], "FOUR" );
Yes: char* str[10]; would create an array of 10 pointers to chars.
To access a single character, we can access it like a 2 dimensional array; i.e.:
char* str[10]={"ONE","TWO","THREE"};
char first = str[0][0];
Can I consider *str[10] as two dimensional array ?
It's unclear what you mean. *str[10] is not a valid type name, and the context is a bit lacking to determine how else to interpret it.
If you mean it as an expression referencing the subsequent definition then no, its type is char, but evaluating it produces undefined behavior.
If you are asking about the type of the object identified by str, referencing the subsequent definition, then again no. In this case it is a one-dimensional array of pointers to char.
If I declare char *str[10]={"ONE","TWO","THREE"} how we can access single character ?
You can access one of the pointers by indexing str, among other other ways. For example, str[1]. You can access one of the characters in the string into which that pointer points by using the indexing operator again, among other ways. For example, str[1][0]. That you are then using a double index does not make str a 2D array. The memory layout is quite different than if you declared, say, char str[3][10];.
I would like to create a dynamic two-dimensional array of pointers to strings, like in the diagram below:
The program below is an extracted part of a program, and allocating dynamically stack A seems to work fine, but I'm having trouble creating a dynamic two-dimensional array of pointers to the cells of A.
// Global
char **stack_A; // dynamic array of strings
char ***stack_B; // dynamic array of pointers to strings
int main(){
stack_A = malloc(sizeof(char *));
stack_B = malloc(sizeof(char **));
function();
return 0;
}
void function(){
// example for first entry
char *text = "some text";
stack_A = realloc(stack_A, sizeof(char *)*strlen(text));
stack_A[0] = strdup(text);
stack_B[0] = realloc(stack_B[0], sizeof(char **));
stack_B[0][0] = *stack_A[0];
printf("%s", **stack_B[0][0]); // I want to output "some text"
}
Update: both the comment and answer was helpful in resolving the issue.
The problem is that you are not copying the pointer to the string, but the first charachter of the string:
stack_B[0][0] = *stack_A[0]; -> *stack_A means the first array in the group of arrays.
it means the same as stack_A[0].
*stack_A[0] means the first char in stack_A[0]: 's'
You need to copy the pointer, not the first letter:
stack_B[0][0] = *stack_A[0] becomes stack_B[0][0] = stack_A[0].
I'm thinking how can I assign a string value to a row in a 2*2 character array in C?
this can be done in java like this:
char [][] array = new char[10][10];
array[1] = "foo".toCharArray();
In C, you can't "assign" to an array. You can, however, copy a string literal (or any string) into the array. You just need to make sure that you don't cause buffer overflows:
char arr[10][10];
const char *str = "foo";
if (strlen(str) < sizeof(arr[1])) {
strcpy(arr[1], str);
}
Alternatively, you can assign to a pointer (which is a member of an array of pointers):
const char *arr[10];
arr[1] = "foo";
One can't really tell which one you need to use unless you provide more context as to what you want to use the array for.
In some code that I read, there was an initializing statement like this
char *array[]= { "something1", "something2", "something3" };
What does this mean, and what does that pointer actually point to?
How is that allocated in memory, and how can I access every element and every character of an element in that array ?
--- Edited ---
and please what is the difference in this example between
char array[3];
and
char *array[3];
--- Edited ---
what that means ?
It's initializing an array of strings (char *) with three values (three pointers to null-terminating strings)
and what that pointer points to ?
It should point to the first element in the char* array
how is that allocated in memory ?
It will allocate enough memory to store the three strings followed by null-terminators, as well as the three pointers to those strings:
array --> pointer to three sequential memory addresses
array[0] --> something1{\0}
array[1] --> something2{\0}
array[2] --> something3{\0}
Note that the strings may not necessarily be in sequential memory
and how can I access every element
if by "element" you mean the string, you can loop though the pointers:
for(int i=0; i<3; i++)
{
char* element = array[i];
}
and every character of an element in that array
well, you could access the chars using array syntax (element[i]) but I would recommend using the C string functions for safety (so you don't have to worry about accessing memory outside the range of the string)
This is a way to initialize an array at the same time that you create it.
This code
char *array[]= { "a", "b", "c" };
will have the same result as this code.
char *array[3];
array[0] = "a";
array[1] = "b";
array[2] = "c";
Here is a good source for more information.
http://www.iu.hio.no/~mark/CTutorial/CTutorial.html#Strings
EDIT:
char array[3]; is an array of 3 char.
char *array[3]; is an array of 3 pointers to char.
char * in C is a string.
array is the name of the variable being declared.
[] indicates that it is an array.
{ "something1", "something2", "something3" } is initializing the contents of the array.
Accessing elements is done like so:
array[0] gives the 1st element - "something1".
array[1] gives the 2nd element - "something2".
etc.
Note:
As was pointed out in the comments, char * isn't technically a string.
It's a pointer to a char. You can visualize a string in memory like so:
<-------------------------->
..134|135|136|137|138|139|..
<-------------------------->
'H'|'e'|'l'|'l'|'o'|'\0'
<-------------------------->
This block of memory (locations 134-139) is holding the string of characters.
For example:
array[0] actually returns a pointer to the first character in "something1".
You use the fact that the characters are sequentially in memory to access the rest of the string in various ways:
/* ch points to the 's' */
char* ch = array[0];
/* ch2 points to the 'e' */
char* ch2 = ch + 3;
/* ch3 == 'e' */
char ch3 = *ch2;
/* ch4 == 'e' */
char ch4 = *(ch + 3);
/* ch5 == 'e' */
char ch5 = ch[3];
This defines a array of char pointers (aka. "c strings").
For accessing the content you could do:
for (int i=0; i<sizeof(array)/sizeof(char*); i++) {
printf("%s", array[i]);
}
It declares array as an array of 3 pointers to char, with its 3 elements initialized to pointers to the respective strings. The memory is allocated for the array itself (3 pointers) and for the strings. The strings memory is allocated statically. The array's memory is allocated either statically (if the declaration is outside of all functions) or dynamically (typically, on the execution stack of the CPU) if the declaration is inside a function.
I have a C code that creates an array of char pointers as the following:
char* arr[100];
I use each element in this array to point to some string that is being calculated by another function. So basically arr[0] would point to string1 and arr[1] to string2, etc.
This works just fine. However I'm now asked to be more flexible by having the user to specify the number of strings as a parameter.
How can I do this with minimal changes to my code? I understand that I need to use malloc. However I'm getting a lot of warnings in all of the assignment statements I had before. I changed the declaration of the array as the following:
char* arr = (char*)malloc(n * sizeof(char*)); //where n is provided by user
I thought that I only needed to change the declaration. Now all of the assignment statements are giving warnings ("assignment makes integer from pointer without a cast"). The following is an example of an assignment statement:
arr[i] = str; //where str is defined as char* and is calculated by another function
Am I missing something here?
If you're looking to create an array of char *, you need a char **arr. Think of it as an array of char * -- if you had an array of int, you would have int *. Since you have an array of char *s, you need char **.
char** arr = malloc(n * sizeof(char*));
You are declaring arr as a pointer to char: either a single string or, if you prefer, an array of chars.
To allocate an array of pointers, declare arr as
char **arr = malloc(n * sizeof(char *));
By the way, remove the cast: it is unnecessary in C. See also Question 7.7 in the comp.lang.c FAQ.
Don't forget that string is an array too (char *), so u will need array of pointers, which should look like this:
char** arr = (char**)malloc(n * sizeof(char*));
you want to declare arr as as char ** since you are pointing to an array of pointers. If you declare arr only as char * (not char ** or char *[]) you only have one "string".