copying values from a integer array to integer struct - c

I have an integer array:
int num[20] = {1,1,5,5,1,1,5,9,2,2,6,1,1,2,5,5,1,3,6,2};
I want to copy the elements num into the following struct:
struct tuple
{
int p1;
int p2;
int p3;
int p4;
};
I am doing the following:
struct tuple *arr;
memcpy(&arr,&num,sizeof(num));
This does not seem to work, since I am encountering a segmentation fault later on in the code.
When I try to print the size:
printf("size of arr: %lu, size of arr[0]: %lu \n", sizeof(arr), sizeof(arr[0]));
I get the following:
size of arr: 8, size of arr[0]: 16
which is wrong, since the values should read:
size of arr: 80, size of arr[0]: 16
Therefore when I try to print, it seg faults:
for (i=0;i<sizeof(arr)/sizeof(arr[0]);++i)
printf("%d,%d,%d,%d\n", arr[i].p1,arr[i].p2, arr[i].p3, arr[i].p4);
Can someone assist me as to where I might be going wrong?

Several points to make here. Firstly:
struct tuple *arr;
memcpy(&arr,&num,sizeof(num));
arr is a pointer to a struct tuple; it is not a struct tuple, and it's size is the pointer size on your system (which is probably 8 bytes), not the same size as a struct tuple. When you do the memcpy, it's copying over the pointer to struct tuple, not a struct tuple instance.
Secondly, if you meant to copy to a struct tuple like this:
struct tuple aTuple;
memcpy(&aTuple,&num,sizeof(num));
Then you would have an actual instance of a struct tuple rather than just a pointer, and the memcpy would copy to that memory. But this would still be wrong because:
1) The size of the array is much larger than the size of struct tuple, and
2) Structures are not guaranteed to have all their fields adjacent in memory. There can be padding between p1 and p2, etc., so the structure and the array would be arranged in memory differently and not directly copyable.
Incidentally, this would work for memcpy to a struct tuple:
struct tuple aTuple;
aTuple.p1 = aTuple.p2 = aTuple.p3 = aTuple.p4 = 42;
struct tuple anotherTuple;
memcpy(&anotherTuple,&aTuple,sizeof(struct tuple));
I post that only as an example of correct usage.
EDIT:
Another thing, regarding this:
printf("size of arr: %lu, size of arr[0]: %lu \n", sizeof(arr), sizeof(arr[0]));
Did you pass num to another function, as parameter arr? In that case the arr is also a pointer, whose size is 8 rather than 80. When you pass an array to a function, it is passed as a pointer.

Try replacing struct tuple *arr; with struct tuple arr[5]; or perhaps struct tuple arr[sizeof(num)/sizeof(struct tuple)];. When you declare arr as a pointer, it doesn't allocate any space for the array it's pointing to. When you declare it as an array, it will decay to a pointer in the memcpy call and blit the int array over top of the stack-(or static-)allocated struct array.
Alternatively, you could initialize arr with a call to malloc(sizeof(num)), but be sure to match such a call with a call to free().
Also, as pointed out by comments, you need to pass arr and num rather than &arr and &num. You want to copy the data, not the pointers (although it may be that &num is equivalent to num as a pointer, in this case).

Related

access to a member of a struct (pointer) with the use of double pointer

hey I am trying to create a program in which I am trying store elements from one array to another with the use of a pointer to pointer but the problem is that is caused undefined behavior I believe that the problem is that I do not pass the elements in members with a proper way
I know it is a vague way of doing this but It is in only for practising reasons
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct student{
char *name;
int *number;
}T;
int main(void) {
char array[10][100]={"araaaa","bbgt","gffkghgh"};
T arr[10][100];
T *p;
T **p1;
p=&arr[0][0];
p1=&p;
int i=0;
for(i = 0 ; i < 3 ; i++)
{ p=arr[i];
strcpy((*p1)->name,array[i]);
}
/*******print_elements*************/
for(i = 0 ; i < 3 ; i++)
{ p=arr[i];
printf("\n the elements are %s",(*p1)-> name);
}
return 0;
}
When you do this:
strcpy ((*p1)->name, array[i]);
(*p1)->name is an uninitialised pointer. What happens, therefore, is in the lap of the gods.
The easiest fix is to modify your student structure such that name is a buffer, rather than a pointer. At the same time, change number to an int, rather than a pointer to an int::
typedef struct student{
char name [100];
int number;
} T;
If you want to keep name as a pointer then you have to allocate some memory before you store your string in it. This should work:
(*p1)->name = strdup (array[i]);
Don't forget to free the memory when done.
T is made of of two pointers, this first one points to a string of characters in memory.
arr is a 2D array that is allocated to store a total of 1000 T structures.
arr[i] would reference a 1D array of T structures within arr
*p1 would essentially be arr[i], since dereferencing p1 gives you p, which was just set to arr[i]. So, that is not a pointer to a T structure, but to an array of T structures. Forcing the cast will likely give you a reference to the first T structure in that row, however.
->name This value is never set. You allocated an array, but "name" is a pointer to memory, not an array of characters, so '->name' is undefined.
I think you need to change arr to be a single dimension array. You aren't using 90% of it.
And, you need to initialize every T struct in that array. You can use malloc or strdup, and then remember to free them all. Or, set the struct to use an array instead.

How to send 2D array to a function?

I've created a 2D array using this:
struct Cars (*ParkingLot)[FloorCount] = malloc(sizeof(struct Cars[FloorCount][10]));
I don't know if it matters but the FloorCount is set to 1 for now, and struct Cars is defined this way:
struct Cars
{
int ID;
char color[20];
char type[20];
};
Anyway, I'm trying to use this array in a function, and I can't access the values inside the array.
For example, the next thing:
void CarIn (struct Cars *Lot[])
{
printf("%d", Lot[0][0].ID);
}
ParkingLot[0][0].ID=15;
CarIn(ParkingLot);
That's not what I wanna do, but it's the most basic function I can think of using the array, it will help me with the rest.
Edit:
Well, I've managed to print using the function, all I needed is to add & before the Lot[0][0].ID...
The other problem I have now is that this function doesn't seem to work at all, it always crash:
void CarIn (struct Cars *Lot[],struct Cars New)
{
Lot[0][0]=New;
return;
}
First, your sizing is wrong in your allocation declaration for ParkingLot. I assume you want 10 cars per floor and an arbitrary number of floors, and if that is the case, then this should be done as:
struct Cars (*ParkingLot)[10] = malloc(FloorCount * sizeof *ParkingLot);
ParkingLot is a pointer to an array of 10 Cars (not 10 pointers to Cars; rather 10 Cars in sequence). sizeof *ParkingLot will calculate the memory requirement for holding that many sequential Cars structures, and finally, multiplying by FloorCount will give you that many floors, of that many cars. For sanity sake you could (and probably should) use the array allocator in the standard library, calloc, though it isn't strictly needed. It would look something like this:
struct Cars (*ParkingLot)[10] = calloc(FloorCount, sizeof *ParkingLot);
Some find it clearer, and relish in the fact it zero-initializes the allocated memory.
On to your question, to pass a true array of arrays (as opposed to an array of pointers) your function parameter declaration is incorrect.
This:
void CarIn (struct Cars *Lot[])
declares an arbitrary-length array of struct Cars *, and indeed the above is equivalent to this:
void CarIn (struct Cars **Lot)
You want neither of those if your intent is to pass a true array of arrays (which is what your allocation is indeed acquiring). Instead, you want something like this:
void CarIn (struct Cars Lot[][10])
or equivalently, this:
void CarIn (struct Cars (*Lot)[10])
To pass a true array of arrays to a function, all dimensions but the most-superior must be provided in the declaration. The above declare an arbitrary length array of element-count-10 arrays of Cars.
Note: This can be done with variable-length syntax as well, if the sizing for the array of arrays inferior dimension is runtime-generated, but that doesn't seem to be your question (yet). For now, the above should get you where you want to go.
Best of luck.
struct does not create a 2D array, struct creates a structure - a 'template' that unifies different data types and stores them as an 'unity' in memory
A 2D array is created by i.e. int 2Darray[3][4] = {{0,1,2},{8,9,10,11}};
A 2D array of a structure is created by i.e. struct Cars cars2Darray[10][10];
See this http://www.tutorialspoint.com/cprogramming/c_multi_dimensional_arrays.htm
To pass a 2D array to a function as argument one possible method is to use a pointer to the 0-element of the array i.e. 2D_array[0] (if the array is named 2D_array).
In the following the pointer 'ptr' points to the 0-element of the int-array '1D_array'
int 1D_array[8]= { 1, 2, 4, 8, 16, 32, 64, 128 };
int *ptr;
ptr = 1D_array;
The ptr = 1D_array stores the address of the 0th element of 1D_array in ptr, so ptr now points to the 0-th element of 1D_array
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int 1D_array[8]= { 1, 2, 4, 8, 16, 32, 64, 128 };
int *ptr;
int i;
ptr = 1D_array;
printf("The value, *ptr points to, is %d\n", *ptr);
printf("When applying *ptr+1 it points to %d\n", *(ptr+1));
printf("*(ptr+3) = %d\n", *(ptr+3));
printf("\n all elements of 1D_array : \n");
for(i=0; i<8; i++)
printf("element[%d]=%d \n", i, *(ptr+i));
return EXIT_SUCCESS;
}
As ptr now points to the 0th element of 1D_array you can use it to pass the array to a function.
For how to pass a 2D array to a function there are 3 methods (2 using pointers) see this Correct way of passing 2 dimensional array into a function

Passing an Array of Structures

How can I pass an array of structures?
So far I have this which is global:
typedef struct _line
{
float val1;
int val2;
} line;
Then I read data from a file into this structure
struct _line* read_file()
{
typedef struct _line *Lines
Lines *array = malloc(num_lines * sizeof(Lines));
//read values into structures here
Then I fill up the structures in the array with values. If I do printf("%d", (*array[1]).val1); I get the right value here in this particular method
Then I return the array like so
return *array
But when I do so, only the 0th structure reads correctly in the method I returned to. Reading the 1st element just prints random values. What am I doing incorrectly?
You should not dereference the array when you return it1, it's actually of incompatible type with the function return type, just
return array;
also, check that array != NULL after malloc() before reading the values, and you don't really need the typedef it makes your code a bit confusing.
If your code compiled which I doubt, then you don't have warnings enabled in your compiler command, enable them so you can prevent this kind of issue.
(1) *array is equivalent to array[0].
Expanding on my comments, your code (as you describe and show it) you have undefined behavior:
This is because you allocate an array of pointers, but you apparently do not allocate the pointers in that array. So when you dereference a pointer (which you haven't allocated and whose value is indeterminate and so will point to a seemingly random location) you have this undefined behavior.
Instead of using a type-alias like Line use the structure name, like
struct _line *array = malloc(num_lines * sizeof(*array));
That will allocate num_lines structures (instead of pointers), then you use it like a normal array, without the pointer dereferencing
array[x].val1 = something;
And you of course return that pointer array as-is:
return array;

qsort dynamically created array in c

Hey guys (be forewarned that this question makes me feel n00b so I probably am),
I'm able to dynamically create an array and I'm able to use qsort effectively for a statically created array but am having trouble using qsort on a dynamically created one. I think I'm stumbling on my use of pointers.
struct my_struct {
FILE *fp;
int i;
};
So the array contains the above struct and I'd like to sort it by the int value.
Statically, I can do something like this:
struct my_struct array[4];
And sort:
qsort((void *) &array, sizeof(array) / sizeof(struct my_struct), sizeof(struct my_struct), *compare);
--
If I create the array thus:
struct my_struct* = malloc(sizeof(struct process) * 4);
Everything compiles and runs, however execution never goes into the compare function.
Any help would be greatly appreciated
sizeof(array) is (sizeof(struct my_struct) * array_size) for constant-size array, but it's only pointer size for dynamic one. You have to calculate actual size (one you passed to malloc) yourself and put it into qsort call.
Your invocation of qsort only works by accident:
qsort((void *) &array, sizeof(array) / sizeof(struct my_struct), sizeof(struct my_struct), *compare);
The address of an array has the same value but a different type from the address of the zeroth element of the array. The cast to void * is also superfluous; and the dereference of the comparator function is also aconventional. Normally, that'd be written:
qsort(array, sizeof(array) / sizeof(array[0]), sizeof(struct my_struct), compare);
Or:
qsort(array, sizeof(array) / sizeof(array[0]), sizeof(array[0]), compare);
If you have a dynamically allocated structure:
size_t num_items = 4;
struct my_struct *dynarr = malloc(sizeof(struct my_struct) * num_items);
or:
struct my_struct *dynarr = malloc(sizeof(*dynarr) * num_items);
then you will be specifying the number of elements differently in the call to qsort, but the rest is essentially unchanged:
qsort(dynarr, num_items, sizeof(*dynarr), compare);
Note in particular that there is no & in front of dynarr, which is a simple pointer variable, for all it has a possibly misleading name.
Why your code went wrong
A guess, but a plausible guess. If you wrote:
qsort(&dynarr, sizeof(dynarr) / sizeof(dynarr[0]), sizeof(dynarr[0]), compare);
then sizeof(dynarr) is the size of a pointer (say 8 bytes in a 64-bit program), and sizeof(dynarr[0]) is 16 bytes, so the size (number of elements) that you tell qsort() to sort is 0 (because 8 / 16 == 0), so the comparator would never be called. If your program is compiled as a 32-bit program, the sizes are 4 bytes for the pointer and 8 for the structure, so the result is still 0.
Note that if instead you passed 4 or num_items as the size of the array, then you'd get a crash. The address of dynarr is the wrong address to pass to the function; you want to pass the address value that is held in dynarr, not the address at which dynarr itself is stored.
NB: You should show the qsort() that doesn't work so we don't have to guess what you've written.

multidimensional array: incompatible type assignment

I have declared array of known size,
typedef struct{
......
char * buffer[height+1]; //height is a constant int
......} args;
int main{
args * info;
info = malloc (sizeof(args));
char* output_buffer[width][height+1]; //width is also a constant int >= 4
output_buffer[2] = malloc (sizeof(char)*char_per_line*(height+1)); // error same as below
info->buffer = output_buffer[2]; // I know it's wrong. incompatible types in assignment
....}
Numbers are arbitrary and used just for illustration.
What i am doing is to assign the address of output_buffer[width] to info->buffer, and then pass info as an argument to a thread, which generates data an array of size height+1; in each slot is a cstring of length char_per_line. Those cstrings are stored in output_buffer[2].
I am confused here that isn't the output_buffer[2] a pointer of type char*[height+1]? Then why can't I assign address of memory from malloc to it?
Also, I know that I cannot assign an array to an array, but how can I get the code work in desired way? If the solution is to use a char** as char*[height+1], then how can I access info->buffer[height], say?
Thanks in advance!
According to the requirement you are specifying, this is what you need to do
/* This is a 2D array of pointers. */
char* output_buffer[width][height+1];
for ( int i =0; i< width; i++ )
for ( int j=0; j <height+1; j++ )
output_buffer[i][j] = malloc (sizeof(char)*char_per_line*(height+1));
And then,
info->buffer[SOME_VALUE] = output_buffer[SOME_WIDTH][SOME_HEIGHT];
I am confused here that isn't the output_buffer[2] a pointer of type
char*[height+1]? Then why can't I assign address of memory from malloc
to it?
malloc returns a single dimensional pointer void* but as you have noted, output_buffer[2] is not a single dimensional pointer. It is of type char*[height+1]. [] adds one more dimension apart from the *.
isn't the output_buffer[2] a pointer of type char*[height+1]?
No. output_buffer[2] is an array of size height+1. Its element type is char*.
Then why can't I assign address of memory from malloc to it?
As you know, you cannot assign to an array.
array of size height+1; in each slot is a cstring of length char_per_line.
how can I get the code work in desired way?
If you need an array of (height+1) C strings, each of size char_per_line, you need to allocate (height+1) C strings of size char_per_line. That is, call malloc (height+1) times and pass char_per_line to each. (There's a way to do it in one call to malloc but you probably don't want to do that right now).
typedef struct{
......
char * buffer[height+1]; //height is a constant int
......} args
this has to be
typedef struct{
......
char ** buffer; //height is a constant int
......} args
output_buffer[2] = malloc (sizeof(char)*char_per_line*(height+1));
you have to this in a for loop, and for all output_buffer[i][j], (now it is char ** = char *).

Resources