Alternative to memset - c

I want to initialize an array of struct, however the second parameter of memset() takes an int. Is there another the function that does the same but with a (void *) has 2nd parameter?
I thought of memcpy() but it doesn't set the value in the entire array. Any idea?
the struct:
typedef struct {
int x;
int y;
char *data;
} my_stuff;
The code:
my_stuff my_array[];
my_array = malloc(MAX * sizeof(my_stuff));
my_stuff *tmp;
tmp->x = -1;
tmp->y = 1;
strcpy(tmp->data = "Initial state");
memset(my_array, tmp, sizeof(my_array));

memset() sets the value of each byte. There's no problem typecasting a pointer to an integer (the second parameter). The main problem is that it will be bigger than a byte.
I'm not aware of any version of memset() that copies more than byte values. I would create a simple loop for this.
Also note that there would be some additional problems with your code, had it worked. For one thing, sizeof(my_array) returns the total number of bytes in the data structure and not the number of elements. Also, your code would've just copied the pointer. You need to actually copy the data it points to since the target is not pointers--it's actual structures.

There isn't a standard function for this - you will just need to call memcpy() in a loop:
my_stuff *my_array = malloc(MAX * sizeof(my_stuff));
my_stuff tmp;
size_t i;
tmp.x = -1;
tmp.y = 1;
tmp.data = "Initial state";
for (i = 0; i < MAX; i++)
memcpy(&my_array[i], &tmp, sizeof tmp);
Note that you can't strcpy() into tmp.data, because that's just a dangling pointer with no memory allocated.

You cannot use memset() in this case. You should use memcpy(). Just try this out:
1. malloc your array
2. initialize the first element of the array
3. copy the first element to all the elements
/* step 1 */
my_stuff *my_array = malloc(MAX * sizeof(my_stuff));
int i;
/* step 2 */
my_array[0].x = -1;
my_array[0].y = 1;
my_array[0].data = "Initial state";
/* step 3 */
for (i = 1; i < MAX; i++)
memcpy(&my_array[i], &my_array[0], sizeof(my_array[0]));

Related

Garbage value even after initializing members of dynamically allocated struct array

I have a dynamically allocated array of structures, 'buff'. Each element is a structure that has a few integer variables and a pointer 'buffer_ptr' which points to another dynamically allocated array of structures. The size of both arrays is given as command line input.
int buffer_size;
int user_num;
struct tuple
{
char userID[5];
char topic[16];
int weight;
};
struct buff_ctrl
{
struct tuple* buffer_ptr;
int in;
int out;
int numItems;
int done;
};
The arrays are created and initialized in main() as follows:
int main(int argc, char* argv[])
{
void *status;
pthread_t mapThd;
if(argc != 4)
{
printf("Input format: ./combiner <buffer_size> <number_of_users> <input_file>\n");
return -1;
}
buffer_size = atoi(argv[1]);
user_num = atoi(argv[2]);
struct buff_ctrl *buff = (struct buff_ctrl*)malloc(user_num * sizeof(struct buff_ctrl));
for(int i=0; i<user_num; i++)
{
struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
struct tuple *ptr = (struct tuple*)malloc(buffer_size * sizeof(struct tuple));
curr_buff->buffer_ptr = ptr;//points to another array
curr_buff->in = 8;
curr_buff->out = 4;
curr_buff->numItems = 7;
curr_buff->done = 0;
printf("%p\n",curr_buff);
}
Then, I need to pass the 'buff' pointer as an argument when creating thread using pthread_create:
pthread_create(&mapThd, NULL, mapper, (void*)buff);
pthread_join(mapThd, &status);
free(buff);
/*end of main*/
My function pointer is as follows:
void* mapper(void *buff)
{
struct buff_ctrl* arr = (struct buff_ctrl *)buff;
struct buff_ctrl* temp_ptr;
printf("######################################################\n");
for(int k=0; k<user_num; k++)
{
/*Printing just to check values */
temp_ptr = arr + (k*sizeof(struct buff_ctrl));
printf("buffer ptr = %p\n", temp_ptr->buffer_ptr);
printf("in = %d\n", temp_ptr->in);
printf("out = %d\n", temp_ptr->out);
printf("numItems = %d\n", temp_ptr->numItems);
}
printf("######################################################\n");
pthread_exit((void*)buff);
}
But, when I print the values of 'buffer_ptr' from the created thread (only one), for ODD number of user_num, there is always ONE element of the array 'buff' which gives garbage value after pthread_create statement! When the values are checked in main itself after removing calls to pthread, it runs fine.
This line
struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
should be
struct buff_ctrl* curr_buff = buff + i;
buff + i is pointer arithmetic and the compiler already takes the size of the
object pointed to by buff into consideration. By doing i*sizeof(struct buff_ctrl) you are assigning
a pointer that may be after the allocated memory.
As general suggestion:
Don't cast malloc. And instead of using sizeof(<type>), use sizeof *variable, this is more safe, because
it's easier to make mistakes when writing sizeof(<type>).
So:
struct buff_ctrl *buff = malloc(user_num * sizeof *buff);
...
struct tuple *ptr = malloc(buffer_size * sizeof *ptr);
And you don't need to declare a separate pointer, you can do:
for(int i=0; i<user_num; i++)
{
buff[i].buffer_ptr = malloc(buffer_size * sizeof *buff[i].buffer_ptr);
buff[i].in = 8;
buff[i].out = 4;
buff[i].numItems = 7;
buff[i].done = 0;
}
Also you should always check for the return value of malloc. If it returns
NULL, you cannot access that memory.
This is wrong:
struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
When you do pointer arithmetic, it operates in units of the size of what the pointer points to, so you don't need to multiply by sizeof. As a result, you're effectively multiplying twice and accessing outside the array bounds.
Just treat buff as an array, rather than dealing with pointers.
for(int i=0; i<user_num; i++)
{
struct tuple *ptr = malloc(buffer_size * sizeof(struct tuple));
buff[i].buffer_ptr = ptr;//points to another array
buff[i].in = 8;
buff[i].out = 4;
buff[i].numItems = 7;
buff[i].done = 0;
}
Also, see Do I cast the result of malloc?
You have a fundamental error.
Pointer arithmetics works by adding the offset in multiples of the pointer type, so adding the offset yourself will not work as you apparently expect it to.
If it was a char * pointer then you would need to add the offset manually, increments would be multiplied by one. But in your case increments by n are multiplied by the size of the pointer base type.
There are times when doing pointer arithmetics with the addition notation makes sense, but most of the time it's much clearer to write index notation instead.

how to find the new size of array of pointer to string

In the main method , i am creating an array of pointers to string
in the add method i am reallocating the array size and adding x elements which i dont know
while coming back to main how can i know the new size of the array , i mean the number of elements int the array ?
Here is my code .. (it has some bugs)
#include <stdio.h>
void add(char ***x);
int main()
{
char **s;
s = (char **) malloc(sizeof(char *));
int i;
add(&s);
for( i=1;i<=?????(**find the new size of the array** );i++)
puts(*s[i]);
return 0;
}
void add(char ***x)
{
- ** // alter arry add x random datas to the array of string pointer**
/*
s[1]="Hello";
s[2]="Need";
s[3]="a help";
s[4]="and help";
s[5]="for the help";
*/
char **data;
int i = 0;
for (i = 1; i <= 5; i++)
{
data = (char **) realloc(*x, 1 * sizeof(char *));
data[i] = (char *) malloc(i * sizeof(char *));
strcpy(data[i], "first");
}
}
can some one please point and fix the bug in the code..
(Sidenote:
can some one please point and fix the bug in the code..
hey, isn't that what debuggers are for?)
Long story short, keep track of it manually:
char **func_that_reallocs(char **ptr, size_t *sz)
{
char **tmp = realloc(ptr, new_size * sizeof(*ptr));
*sz = new_size;
return tmp;
}
And please do not cast the return value of malloc()!
Always add one entry more to the array as needed and set this additional last entry to NULL.
Then write a function which scans the array until it find this NULL-pointer and return the number of entries counted up until then and you are done.
It's the same concept as for a C-"string", with the only difference of using a NULL instead of '\0' as (array-)terminator.
Some people call this last element also the "stopper"-element.
The positive thing about this approach is, one does not have to keep the array's size in a different variable, which might get out of sync with the real size of the array: The size is implicitly given by the array itself.

how to pass pointer to array of pointers in C

I have the following C code which works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
int pw = sizeof(char*); // width of pointer (to char)
int num;
int first = 1;
int size = 0;
int incr = 10;
char *(*arr)[]; // pointer to array of pointers to char */
test(char* s, int i)
{
int j;
char *(*newarr)[]; // pointer to array of pointers to char
if (first) { // first time
arr = malloc(pw*incr); // malloc array
first = 0; // skip from now on
size = incr; // save the size
}
if (i >= size) { // out of space
newarr = malloc(pw*(size+incr)); // get incr bigger space
for (j=0; j<size; j++) // copy the elements from the old
(*newarr)[j] = (*arr)[j]; // array to new array
free(arr); // free the old array space
arr = newarr; // point old array to new array
size = size+incr;
};
int len = strlen(s); // length of s
(*arr)[i] = malloc(len+1); // assign pointer to pointer array element
strcpy((*arr)[i], s); // copy s to array
// both arguments must be pointers
printf("%d\t%s\n", i, (*arr)[i]);
};
main()
{
char* s = "this is a string";
for (num=0; num<30; num++) // add 30 pointers to s to *arr
test(s, num);
for (num=0; num<30; num++)
printf("%d\t%s\n", num, (*arr)[num]); // print out what they point to
};
It prints out 'i\tthis is a string' for 'i' from 0 to 29 twice. What I want to do is pass 'arr' from the top of the file as an argument of 'test'. The reason I want to do that is because I want to pass several different arrays all of which are declared the same way. If I make the minimal changes to do that I get:
0 this is a string
Segmentation fault (core dumped)
Here is the output of the diff command which shows the minimal changes:
13c13
< char *(*arr)[]; // pointer to array of pointers to char */
---
> char *(*jarr)[]; // pointer to array of pointers to char */
15c15
< test(char* s, int i)
---
> test(char* s, int i, char *(*arr)[])
52c52
< test(s, num);
---
> test(s, num, jarr);
54,55d53
< for (num=0; num<30; num++)
< printf("%d\t%s\n", num, (*arr)[num]); // print out what they point to
In other words everything is the same except for renaming 'arr' as 'jarr' and passing it to 'test'.
Thanks in advance,
Mike
The trouble occurs when you call:
test(s, num, jarr);
You are passing jarr by value. Inside the function, you are reallocating (the hard way — why not use realloc() which does the copying for you?) the array, but that change does not affect the value of jarr 'in main()' because it was passed by value. The second time through the loop, you are still passing a null pointer to the function, but you are then dereferencing that null pointer, which is bad news.
How to fix?
Fair question...I'm not sure if the old "well, if I want to get to there, I wouldn't start from here" gag passes muster.
The 'simplest' change is to revise the call:
jarr = test(s, num, jarr);
and then 'just' revise the function so that it returns a pointer to an array of character pointers. That is a very esoteric function. My brain's not awake (insufficient caffeine), so I used an intermediate typedef to get around the problem of how to write the function declaration and definition:
typedef char *(ArrayString[]);
ArrayString *test3(char *s, int i, char *(*arr)[]);
ArrayString *test3(char *s, int i, char *(*arr)[]) { (*arr)[i] = s; return arr; }
It compiles without warnings; that isn't a guarantee that it's correct.
The primary alternative is to pass a pointer to a pointer to an array of char pointers to the function, which is even more esoteric.
However, both of these are 'starting from here' solutions. You'd do better, on the whole, to devise a different way of handling things. Pointers to arrays are certainly a part of C, but they are at the outer edges of C and you should generally assume that if your design calls for their use, then your design is probably not the best. You should use a simpler char ** (or, perish the thought, char ***; triple indirection is best avoided too, but that isn't always possible).
You seem to have misunderstood how arrays and pointers works. Lets say you want a dynamic array of strings, that is basically a pointer to a pointer of char:
char **arr = NULL;
To allocate memory for that you do e.g.
arr = malloc(sizeof(char *) * current_size);
Now you have an "array" of character pointers. Lets say you want each of these to be a specific string str:
for (int i = 0; i < current_size; i++)
{
arr[i] = strdup(str);
}
Oh, now you need to increase the number of strings, all initialized to the same string as before:
size_t new_size = current_size + 10;
arr = realloc(arr, sizeof(char *) * new_size);
for (int i = current_size; i < new_size)
{
arr[i] = strdup(str);
}
The problem now is that you want to do all of the above in a separate function. It's first now that you have to add another indirection.
I think you can do a double check on the first malloc value assigned to jarr both in the test(s, 0, jarr) and out of the test(s, 0, jarr); the jarr assignement is not successful since you change the pointer value in the passing by value.

how to initialize the array of pointers to a structure to zero

I am allocating memory for array of pointers to structure through malloc and want to initialize it with zero like mentioned below . Assuming the structure contains member of type int and char [] (strings) ? so how can i zero out this struct.
Code : suppose i want to allocate for 100
struct A **a = NULL;
a = (struct **)malloc(sizeof( (*a) * 100);
for(i=1; i < 100; i++)
a[i] = (struct A*)malloc(sizeof(a));
Also please explain me why is it necessary to initialize with zero .
Platform : Linux , Programing language : C
I know we can use memset or bzero . I tried it bt it was crashing , may be i was noy using it properly so pls tell me the correct way .
Use of calloc would be most in line with the example above.
First, C arrays are zero-based, not one-based. Next, you are allocating only enough space to hold one pointer, but you are storing 100 pointers into it. Are you trying to allocate 100 As, or are you trying to allocate 100 sets of 100 As each? Finally, the malloc inside your loop allocates space for the sizeof a, not sizeof (struct A).
I'll assume that you are trying to allocate an array of 100 pointers to A, each pointer pointing to a single A.
Solutions: You could use calloc:
struct A **a;
/* In C, never cast malloc(). In C++, always cast malloc() */
a = malloc(100 * sizeof( (*a)));
for(i=0; i < 100; i++)
a[i] = calloc(1, sizeof(struct A));
Or, you could use memset:
struct A **a;
a = malloc(100 * sizeof(*a));
for(i = 0; i < 100; i++) {
a[i] = malloc(sizeof(struct A));
memset(a[i], 0, sizeof(struct A));
}
You ask "why is it necessary to initialize with zero?" It isn't. The relevant requirement is this: you must assign a value to your variables or initialize your variable before you use them for the first time. That assignment or initialization might be zero, or it might be 47 or it might be "John Smith, Esq". It just has to be some valid assignment.
As a matter of convenience, you might choose to initialize all of your members of struct A to zero, which you can do in one single operation (memset or calloc). If zero is not a useful initial value for you, you could initialize the structure members by hand, for example:
struct A **a;
a = malloc(100 * sizeof(*a));
for(i = 0; i < 100; i++) {
a[i] = malloc(sizeof(struct A));
a[i]->index = i;
a[i]->small_prime = 7;
strcpy(a[i]->name, name_database[i]);
}
As long as you never refer to the value of an uninitialized and unassigned variable, you are good.
You can use memset() to set the whole array to 0
OTOH,
a = (struct **)malloc(sizeof( (a*)));
for(i=1; i < 100; i++)
a[i] = (struct*)malloc(sizeof(a) * 100);
is wrong, because you have just created one element of a * but in the next line when the loop goes to 2nd iteration, it will access illegal memory. So to allocate 100 elements of a *, your first malloc() should be as follows
a = (struct **)malloc(sizeof(a *) * 100);
The correct code (including error handling) would more or less will look as follows:
if ((a = (struct **)malloc(sizeof(a*) * 100)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
for(i=0; i<100; i++) {
if ((a[i] = (struct*)malloc(sizeof(a) * 100)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
memset(a[i], 0, 100);
}
or as an alternative to malloc() and memset(), you can use calloc()
You dont need many malloc's, one calloc is enough:
int i;
struct A **a = calloc(100,sizeof**a+sizeof*a),*mem=a+100;
for(i=0;i<100;++i)
{
a[i]=&mem[i];
}
...
free(a); /* and you only need ONE free */

How to allocate and deallocate heap memory for 2D array?

I'm used to PHP, but I'm starting to learn C. I'm trying to create a program that reads a file line by line and stores each line to an array.
So far I have a program that reads the file line by line, and even prints each line as it goes, but now I just need to add each line to an array.
My buddy last night was telling me a bit about it. He said I'd have to use a multidimensional array in C, so basically array[x][y]. The [y] part itself is easy, because I know the maximum amount of bytes that each line will be. However, I don't know how many lines the file will be.
I figure I can make it loop through the file and just increment an integer each time and use that, but I feel that there might be a more simple way of doing it.
Any ideas or even a hint in the right direction? I appreciate any help.
To dynamically allocate a 2D array:
char **p;
int i, dim1, dim2;
/* Allocate the first dimension, which is actually a pointer to pointer to char */
p = malloc (sizeof (char *) * dim1);
/* Then allocate each of the pointers allocated in previous step arrays of pointer to chars
* within each of these arrays are chars
*/
for (i = 0; i < dim1; i++)
{
*(p + i) = malloc (sizeof (char) * dim2);
/* or p[i] = malloc (sizeof (char) * dim2); */
}
/* Do work */
/* Deallocate the allocated array. Start deallocation from the lowest level.
* that is in the reverse order of which we did the allocation
*/
for (i = 0; i < dim1; i++)
{
free (p[i]);
}
free (p);
Modify the above method. When you need another line to be added do *(p + i) = malloc (sizeof (char) * dim2); and update i. In this case you need to predict the max numbers of lines in the file which is indicated by the dim1 variable, for which we allocate the p array first time. This will only allocate the (sizeof (int *) * dim1) bytes, thus much better option than char p[dim1][dim2] (in c99).
There is another way i think. Allocate arrays in blocks and chain them when there is an overflow.
struct _lines {
char **line;
int n;
struct _lines *next;
} *file;
file = malloc (sizeof (struct _lines));
file->line = malloc (sizeof (char *) * LINE_MAX);
file->n = 0;
head = file;
After this the first block is ready to use. When you need to insert a line just do:
/* get line into buffer */
file.line[n] = malloc (sizeof (char) * (strlen (buffer) + 1));
n++;
When n is LINE_MAX allocate another block and link it to this one.
struct _lines *temp;
temp = malloc (sizeof (struct _lines));
temp->line = malloc (sizeof (char *) * LINE_MAX);
temp->n = 0;
file->next = temp;
file = file->next;
Something like this.
When one block's n becomes 0, deallocate it, and update the current block pointer file to the previous one. You can either traverse from beginning single linked list and traverse from the start or use double links.
There's no standard resizable array type in C. You have to implement it yourself, or use a third-party library. Here's a simple bare-bones example:
typedef struct int_array
{
int *array;
size_t length;
size_t capacity;
} int_array;
void int_array_init(int_array *array)
{
array->array = NULL;
array->length = 0;
array->capacity = 0;
}
void int_array_free(int_array *array)
{
free(array->array);
array->array = NULL;
array->length = 0;
array->capacity = 0;
}
void int_array_push_back(int_array *array, int value)
{
if(array->length == array->capacity)
{
// Not enough space, reallocate. Also, watch out for overflow.
int new_capacity = array->capacity * 2;
if(new_capacity > array->capacity && new_capacity < SIZE_T_MAX / sizeof(int))
{
int *new_array = realloc(array->array, new_capacity * sizeof(int));
if(new_array != NULL)
{
array->array = new_array;
array->capacity = new_capacity;
}
else
; // Handle out-of-memory
}
else
; // Handle overflow error
}
// Now that we have space, add the value to the array
array->array[array->length] = value;
array->length++;
}
Use it like this:
int_array a;
int_array_init(&a);
int i;
for(i = 0; i < 10; i++)
int_array_push_back(&a, i);
for(i = 0; i < a.length; i++)
printf("a[%d] = %d\n", i, a.array[i]);
int_array_free(&a);
Of course, this is only for an array of ints. Since C doesn't have templates, you'd have to either put all of this code in a macro for each different type of array (or use a different preprocessor such as GNU m4). Or, you could use a generic array container that either used void* pointers (requiring all array elements to be malloc'ed) or opaque memory blobs, which would require a cast with every element access and a memcpy for every element get/set.
In any case, it's not pretty. Two-dimensional arrays are even uglier.
Instead of an array here, you could also use a linked list, The code is simpler, but the allocation is more frequent and may suffer from fragmentation.
As long as you don't plan to do much random access (Which is O(n) here), iteration is about as simple as a regular array.
typedef struct Line Line;
struct Line{
char text[LINE_MAX];
Line *next;
};
Line *mkline()
{
Line *l = malloc(sizeof(Line));
if(!l)
error();
return l;
}
main()
{
Line *lines = mkline();
Line *lp = lines;
while(fgets(lp->text, sizeof lp->text, stdin)!=NULL){
lp->next = mkline();
lp = lp->next;
}
lp->next = NULL;
}
If you are using C you will need to implement the resizing of the array yourself. C++ and the SDL has this done for you. It is called a vector. http://www.cplusplus.com/reference/stl/vector/
While a multidimensional array can solve this problem, a rectangular 2D array would not really be the natural C solution.
Here is a program that initially reads the file into a linked list, and then allocates a vector of pointers of the right size. Each individual character does then appear as array[line][col] but in fact each row is only as long as it needs to be. It's C99 except for <err.h>.
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct strnode {
char *s;
struct strnode *next;
} strnode;
strnode *list_head;
strnode *list_last;
strnode *read1line(void) {
char space[1024];
if(fgets(space, sizeof space, stdin) == NULL)
return NULL;
strnode *node = malloc(sizeof(strnode));
if(node && (node->s = malloc(strlen(space) + 1))) {
strcpy(node->s, space);
node->next = NULL;
if (list_head == NULL)
list_head = node;
else
list_last->next = node;
list_last = node;
return node;
}
err(1, NULL);
}
int main(int ac, char **av) {
int n;
strnode *s;
for(n = 0; (s = read1line()) != NULL; ++n)
continue;
if(n > 0) {
int i;
strnode *b;
char **a = malloc(n * sizeof(char *));
printf("There were %d lines\n", n);
for(b = list_head, i = 0; b; b = b->next, ++i)
a[i] = b->s;
printf("Near the middle is: %s", a[n / 2]);
}
return 0;
}
You can use the malloc and realloc functions to dynamically allocate and resize an array of pointers to char, and each element of the array will point to a string read from the file (where that string's storage is also allocated dynamically). For simplicity's sake we'll assume that the maximum length of each line is less than M characters (counting the newline), so we don't have to do any dynamic resizing of individual lines.
You'll need to keep track of the array size manually each time you extend it. A common technique is to double the array size each time you extend, rather than extending by a fixed size; this minimizes the number of calls to realloc, which is potentially expensive. Of course that means you'll have to keep track of two quantities; the total size of the array and the number of elements currently read.
Example:
#define INITIAL_SIZE ... // some size large enough to cover most cases
char **loadFile(FILE *stream, size_t *linesRead)
{
size_t arraySize = 0;
char **lines = NULL;
char *nextLine = NULL;
*linesRead = 0;
lines = malloc(INITIAL_SIZE * sizeof *lines);
if (!lines)
{
fprintf(stderr, "Could not allocate array\n");
return NULL;
}
arraySize = INITIAL_SIZE;
/**
* Read the next input line from the stream. We're abstracting this
* out to keep the code simple.
*/
while ((nextLine = getNextLine(stream)))
{
if (arraySize <= *linesRead)
{
char **tmp = realloc(lines, arraysSize * 2 * sizeof *tmp);
if (tmp)
{
lines = tmp;
arraySize *= 2;
}
}
lines[(*linesRead)++] = nextLine;
)
return lines;
}

Resources