I'm trying to instantiate a new string every iteration of a loop. What I tried was this:
int main(void) {
char *strs[10];
for (int i = 0; i < 10; i ) {
char str[10] = "";
char c = '0' i;
strncat(str, &c, 1);
strs[i] = str;
}
for (int i = 0; i < 10; i ) {
printf("%s\n", strs[i]);
}
}
However, this prints all 9's, since C has conveniently decided that each iteration it would use the same address. I know that the following works, but just wanted to ask if it is possible to avoid malloc.
int main(void) {
char *strs[10];
for (int i = 0; i < 10; i ) {
char *str = malloc(sizeof(char) * 10);
char c = '0' i;
strncat(str, &c, 1);
strs[i] = str;
}
for (int i = 0; i < 10; i ) {
printf("%s\n", strs[i]);
}
}
I am also interested in instantiating structs the same way without malloc. Is this possible?
CodePudding user response:
A straightforward approach is to declare a two dimensional array like for example
char strs[10][2] = { "" };
for (int i = 0; i < 10; i ) {
strs[i][0] = '0' i;
}
Here is a demonstration program
#include <stdio.h>
int main( void )
{
enum { N = 10 };
char strs[N][2] = { "" };
for ( int i = 0; i < N; i )
{
strs[i][0] = '0' i;
}
for ( int i = 0; i < N; i )
{
printf( "%s ", strs[i] );
}
putchar( '\n' );
}
The program output is
0 1 2 3 4 5 6 7 8 9
Pay attention to that your second program has undefined behavior
char *str = malloc(sizeof(char) * 10);
char c = '0' i;
strncat(str, &c, 1);
strs[i] = str;
The dynamically allocated array is not initialized. So the call of strncat
invokes undefined behavior.
And in the both your programs this call strncat(str, &c, 1);
does not build a string. So this call printf("%s\n", strs[i]);
again invokes undefined behavior.
CodePudding user response:
Regardless of data type, an object declared at block scope without storage class specifier static
* has automatic storage duration. Its lifetime ends when execution of the innermost block containing its declaration terminates. Attempting to access such an object outside its lifetime produces undefined behavior.
If you want an object whose lifetime starts after the beginning of program execution and extends beyond the termination of the innermost block containing the start point, then dynamic allocation is your only choice.
* with static
, the object has static storage duration -- the whole run of the program. You can access these via pointer from outside the scope of their identifiers, but for each such declaration there is only object serving the whole execution of the program.
CodePudding user response:
"just wanted to ask if it is possible to avoid malloc."
Yes. The following makes use of Variable Length Arrays, and a function to do this without using calloc
or malloc
.
Running from the command prompt for example, enter:
your_program_name 10 5<return>
to create an array of 10 elements each having room for 4 char
plus a terminating null.
void populate_strs(int num, int longest, char sArr[num][longest])
{
for(int i=0;i<num; i )
{
char c[2] = {0};
c[0] = '0' (char)i;
c[1] = 0;//null terminate string
strncat(sArr[i], c, 1);//do not need & for string
}
}
int main(int argc, char *argv[])
{
if(argc != 3) printf("Usage error...");
int num_str = atoi(argv[1]);
int max_len = atoi(argv[2]);
char strs[num_str][max_len];
memset(strs, 0, sizeof strs);
populate_strs(num_str, max_len, strs);
for (int i = 0; i < 10; i ) {
printf("%s\n", strs[i]);
}
return 0;
}
And the same is true for an array of struct
;
Given this for example:
typdef struct {
int val;
char str;
bool state;
} data_s;
...
int size = 0;
printf("Enter how many array elements of data_s to create.\n");
fscanf(stdin, "%d", &size);
data_s data[size];
memset(data, 0, sizeof data);
//use array of data;