I tried creating function that dynamically allocates memory for 2 dimensional array and put some integer values into the array. Overall, the function worked as expected but there were some error. So I did the same thing within main() and got the right result. My code is like below:
#include <stdlib.h>
#include <stdio.h>
void test(int d1, int d2, int ***p){
int value;
*p = (int **)(malloc(sizeof(int)*d1));
for (int i = 0; i < d1; i++){
(*p)[i] = (int *)(malloc(sizeof(int)*d2));
for (int j = 0; j < d2; j++){
(*p)[i][j] = i * 10 + j;
}
}
printf("\n");
}
int main(void){
int d1, d2;
int ** ptr;
printf("length of 1st dimension?\n");
scanf("%d", &d1);
printf("length of 2nd dimension?\n");
scanf("%d", &d2);
test(d1, d2, &ptr);
for (int i=0; i<d1; i++){
for (int j=0; j<d2; j++){
printf("%d ", ptr[i][j]);
}
printf("\n");
}
free(ptr);
ptr = (int **)(malloc(sizeof(int)*d1));
for (int i=0; i< d1; i++){
ptr[i] = (int *)(malloc(sizeof(int)*d2));
for (int j=0; j<d2; j++){
ptr[i][j] = i *10 +j;
}
}
printf("\n######################\n\n");
for (int i=0;i<d1;i++){
for (int j=0; j<d2;j++){
printf("%d ", ptr[i][j]);
}
printf("\n");
}
free(ptr);
return 0;
}`
When I passed 5 as a length of 1st and 2nd dimension, I got the result like below:
length of 1st dimension?
5
length of 2nd dimension?
5
532699424 32725 2 3 4
10 11 12 13 14
20 21 22 23 24
30 31 32 33 34
40 41 42 43 44
######################
0 1 2 3 4
10 11 12 13 14
20 21 22 23 24
30 31 32 33 34
40 41 42 43 44
I think, except that I passed pointer to pointer to pointer as an argument to the function, I did the same thing. However some values in the first row are different. And I got different value for the first row whenever I executed the function.
Could someone please let me know what I did wrong?
Thank you in advance.
The lines
*p = (int **)(malloc(sizeof(int)*d1));
ptr = (int **)(malloc(sizeof(int)*d1));
are wrong. The elements is int*, but only room for int is allocated per element.
This may cause trouble if int* is larger than int (for example, when int* is 8 bytes and int is 4 bytes).
The lines should be
*p = malloc(sizeof(int*)*d1);
ptr = malloc(sizeof(int*)*d1);
or (with risk of making mistake reduced by avoiding writing type manually)
*p = malloc(sizeof(*p)*d1);
ptr = malloc(sizeof(*ptr)*d1);
See also: c - Do I cast the result of malloc? - Stack Overflow
Related
Why is the data preserved for the second call when I haven't used static?
Here is the code, the output and what I've expected the output should be.
#include <stdio.h>
void fun(int len)
{
int arr[10];
int i;
for (i = 0; i < len; i++)
arr[i] = (i+1) * 10;
for (i = 0; i < 10; i++)
printf("%d ", arr[i]);
printf("\n");
}
int main(void) {
fun(10);
fun(4);
return 0;
}
output:
10 20 30 40 50 60 70 80 90 100
10 20 30 40 50 60 70 80 90 100
expected output:
10 20 30 40 50 60 70 80 90 100
10 20 30 40 0 0 0 0 0 0
int arr[10]; declares an array of 10 int elements on the stack. Its elements are uninitialized. If you attempt to access them without initialization, as is the case with fun(4), you may see garbage values, you may happen to see old memory contents (as you did here), or you may crash the program with a segmentation fault if the memory page belongs to another program. You may even get your expected output! In fact, anything can happen because behavior is undefined by the specification.
To meet your expectations, initialize the array in any way you choose, such as one of the following:
int arr[10] = {};
int arr[10] = {0};
int arr[10];
memset(arr, 0, sizeof(int) * 10);
int arr[10];
for (int i = 0; i < 10; i++) {
arr[i] = 0;
}
etc.
Please initialize array.
Like this
void fun(int len)
{
int arr[10] = {0}; //changed
int i;
for (i = 0; i < len; i++)
arr[i] = (i+1) * 10;
for (i = 0; i < 10; i++)
printf("%d ", arr[i]);
printf("\n");
}
You are invoking undefined behavior by accessing uninitialized memory. The result could be literally anything, including your computer growing legs and running away.
In practice, what is probably happening is that your function calls occupy the same place on the stack since there are no other calls between or within them. The arr variable ends up on the same spot on the stack both times. The first initialization is more comprehensive than the second, so you don't see total garbage. This is to be expected, but certainly never relied upon.
array arr[] is allocated in stack which is uninitialized by default, the values are the ones used last time this area was allocated, in this it happens to allocate the same stack area between the 2 fun calls, and the stack area was initialized by the first call.
I'm working in C
I have a struct called Entity and I create a dynamic array of that struct. Then I try to remove one element from the array but I don't get the behaviour I want.
Here is the code I'm using:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Entity
{
int x, y;
int velX, velY;
}Entity;
int remove_element(Entity** array, int sizeOfArray, int indexToRemove)
{
int i;
printf("Beginning processing. Array is currently: ");
for (i = 0; i < sizeOfArray; ++i)
printf("%d ", (*array)[i].x);
printf("\n");
Entity* temp = malloc((sizeOfArray - 1) * sizeof(Entity)); // allocate an array with a size 1 less than the current one
memmove(
temp,
*array,
(indexToRemove+1)*sizeof(Entity)); // copy everything BEFORE the index
memmove(
temp+indexToRemove,
(*array)+(indexToRemove+1),
(sizeOfArray - indexToRemove)*sizeof(Entity)); // copy everything AFTER the index
printf("Processing done. Array is currently: ");
for (i = 0; i < sizeOfArray - 1; ++i)
printf("%d ", (temp)[i].x);
printf("\n");
free (*array);
*array = temp;
return 0;
}
int main()
{
int i;
int howMany = 20;
Entity* test = malloc(howMany * sizeof(Entity*));
for (i = 0; i < howMany; ++i)
(test[i].x) = i;
remove_element(&test, howMany, 14);
--howMany;
return 0;
}
And the output I get :
Beginning processing. Array is currently: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Processing done. Array is currently: 0 1 2 3 4 1866386284 6 7 8 9 10 11 12 13 15 16 17 18 19
Then the program crashes at the free (*array); line.
I want my second line to be 0 1 2 3 4 5 6 7 8 9 10 11 12 13 15 16 17 18 19.
How could I solve my problem ?
First thing you have allocated memory space for holding 20 Enity*. Then you have dereferenced it (and the value it contained is indeterminate). This is undefined behavior. And all story ends here.
But let's analyze what you mostly wanted.
Entity* test = malloc(howMany * sizeof(Entity));
^^^^^^^
is what you wanted. Because only if you do this you will get the member elements x and so on.
Also if you are considering 0 indexing then the memmove calls should be
memmove(temp, *array, (indexToRemove)*sizeof(Entity));
memmove(temp+indexToRemove, (*array)+(indexToRemove+1),
(sizeOfArray - indexToRemove - 1)*sizeof(Entity));
These two changes will be enough to solve the problems you are facing and realizing the correct behavior. (If this is all there is in your code).
Also as per standard the main() should be declared like this in case it doesn't take any parameter int main(void). Free the dynamically allocated memory when you are done working with it. Also you should check the return value of malloc - in case it fails it returns NULL and you should handle that case.
Your offset calculations are off by one in both memmove instances. Use this instead:
// copy everything BEFORE the index
memmove(temp,
*array,
indexToRemove * sizeof(Entity));
// copy everything AFTER the index
memmove(temp + indexToRemove,
*array + indexToRemove + 1,
(sizeOfArray - indexToRemove - 1) * sizeof(Entity));
In main itself your memeory allocation is not done properly.if you are using double pointer you should allocate memory first for double pointer and than single pointer in loop one by one.
a little touch
remove element in any type of struct array
regards
int remove_element(void **input_ptr, int input_size, int index_remove, int struct_size)
{
void *temp_ptr;
temp_ptr = malloc((input_size - 1) * struct_size);
if (temp_ptr == 0)
return -1;
memmove(temp_ptr, *input_ptr, index_remove * struct_size);
memmove(temp_ptr + (index_remove * struct_size), (*input_ptr) + (index_remove + 1) * struct_size, (input_size - index_remove - 1) * struct_size);
free(*input_ptr);
*input_ptr = temp_ptr;
return 1;
}
usage example for question struct
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Entity
{
int x, y;
int velX, velY;
}Entity;
int remove_element(void **input_ptr, int input_size, int index_remove, int struct_size)
{
void *temp_ptr;
temp_ptr = malloc((input_size - 1) * struct_size);
if (temp_ptr == 0)
return -1;
memmove(temp_ptr, *input_ptr, index_remove * struct_size);
memmove(temp_ptr + (index_remove * struct_size), (*input_ptr) + (index_remove + 1) * struct_size, (input_size - index_remove - 1) * struct_size);
free(*input_ptr);
*input_ptr = temp_ptr;
return 1;
}
int main()
{
int i;
int howMany = 20;
Entity* test = malloc(howMany * sizeof(Entity));
for (i = 0; i < howMany; ++i)
{
(test[i].x) = i;
printf("test[%d].x = '%d'\n", i, test[i].x);
}
remove_element((void**)&test, howMany, 14, sizeof(Entity));
--howMany;
printf("Deleted index --- new array\n");
for (i = 0; i < howMany; ++i)
printf("test[%d].x = '%d'\n", i, test[i].x);
return 0;
}
I'm coding a program in C that should rank countries by its gold medals in the olympic games.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _Table {
char *country;
int amnt, gold, silver, bronze;
} Table;
char *arrayAlloc(int size) {
char *array;
array = (char *) malloc(sizeof(char) * size);
return array;
}
void readTable(Table *ptr) {
char buffer[100], *cpyPtr, *savePtr;
for (int i = 0; i < ptr->amnt; ++i) {
fgets(buffer, sizeof(buffer), stdin);
buffer[strlen(buffer) - 1] = '\0';
ptr[i].country = strtok_r(buffer, " ", &savePtr);
ptr[i].country = strdup(ptr[i].country);
cpyPtr = strtok_r(NULL, " ", &savePtr);
ptr[i].gold = strtol(cpyPtr, &cpyPtr, 10);
cpyPtr = strtok_r(NULL, " ", &savePtr);
ptr[i].silver = strtol(cpyPtr, &cpyPtr, 10);
cpyPtr = strtok_r(NULL, " ", &savePtr);
ptr[i].bronze = strtol(cpyPtr, &cpyPtr, 10);
}
}
void printTable(Table *ptr) {
for (int i = 0; i < ptr->amnt; ++i) {
printf("%s %d %d %d\n", ptr[i].country, ptr[i].gold,ptr[i].silver, ptr[i].bronze);
}
}
int compare(const void *p, const void *q) {
int l = ((Table *)p)->gold;
int r = ((Table *)q)->gold;
return (r - l);
}
int main(int argc, char const *argv[]) {
int N; // Amount of lines
scanf("%d", &N);
getchar();
Table tab[N];
tab->amnt = N;
tab->country = arrayAlloc(100);
readTable(tab);
qsort(&tab->gold, tab->amnt, sizeof(Table), compare);
printTable(tab);
free(tab->country);
return 0;
}
Input example:
4
BRA 3 4 5
USA 23 76 34
CHN 23 54 12
GER 10 20 23
Expected output:
USA 23 76 34
CHN 23 54 12
GER 10 20 23
BRA 3 4 5
What I'm getting:
BRA 23 54 12
GER 23 76 34
CHN 3 4 5
USA 10 20 23
As you can see it seems to "sort" it somehow. However it is far from what I need to accomplish.
I've already tried to modify the compare() function, but without success.
What am I possibly missing here?
qsort(&tab->gold, tab->amnt, sizeof(Table), compare);
The first two arguments should be a pointer to your array (Table tab[N];) and the number of elements in the array (N), i.e.:
qsort(tab, N, sizeof(Table), compare);
You did have the correct number of elements in tab->amnt, but the start pointer &tab->gold doesn't point to the beginning of the table, but in the middle of the first element, so qsort can't work correctly.
Also, you have functions with loops like this:
void printTable(Table *ptr) {
for (int i = 0; i < ptr->amnt; ++i) {
Which means that you're carrying the size of the array in its first member. That seems odd, and means the array member 'amnt' is redundant in all but the first member of the array.
But if the array gets sorted, the first array member is no longer the first, and ptr->amnt doesn't contain the correct size any longer.
Better change printTable to
void printTable(Table *ptr, unsigned size) {
for (int i = 0; i < size; ++i) {
and call it with
printTable(tab, N);
Same for readTable.
I'm also not sure what the purpose of this is:
tab->country = arrayAlloc(100);
You're preallocating space pointed to by the country pointer in the first array member, but in any case readTable allocates space for country with strdup to all array members.
You might also want to consider checking the value or N entered by the user, or allocating the memory for tab via malloc. Now tab is allocated on the stack, which may cause the program to crash if the user enters some number large to cause a stack overrun.
Also, since you don't check the return values of the strtok_r calls in readTable, the program will crash if the user gives malformed input.
There are several issues; yet the main two are the following:
In qsort(&tab->gold, tab->amnt, sizeof(Table), compare), you do not pass the begin of the array (as neccessary), but a pointer to a data member of the first element in the array. This means that the pointer passed has a particular offset to the begin of the array and will point almost in the "middle" of the first element. As qsort will exchange elements (i.e. memory chunks of the size provided) relative to the pointer you provide to qsort, each object may get "split" with unexpected and weird results then (very likely yielding undefined behaviour as well).
Second, you use tab->amnt = N, which is equivalent to tab[0].amnt = N, i.e. it sets amnt only for the first entry. If you then sort the array, the first entry may be replaced by another one, which does not have set amnt to a specific value. So your print-function, which again relies on amnt being in the first element, will count wrong.
So write qsort(tab, N, sizeof(Table), compare) and manage the size of the array outside the elements, i.e. introduce a separate parameter size, that is then passed to the print-function.
Maybe there are other issues as well, but these two are the most suspicious ones to me.
There is more than one issue in your code.
First if all you your tab would be better if allocated dynamically.
Table* tab = malloc(sizeof(Table)*N);
Variable-length array are only supported by c99 and later versions and some C11 implementation might not support them too if __STDC_NO_VLA_ is defined (Check C11 standard 6.10.8.3)
Secondly, everything which iterates on tab has to know tab's size which's N that you have to pass around as for instance in
void readTable(Table *ptr, const int N) {
char buffer[100], *cpyPtr, *savePtr;
for (int i = 0; i < N; ++i) {...
Finaly qsort need to be called as follows:
qsort(tab, N,sizeof(Table), compare);
The following will produces the expected output (note that I have not checked for any other issues):
typedef struct _Table {
char *country;
int amnt, gold, silver, bronze;
} Table;
char *arrayAlloc(int size) {
char *array;
array = (char *) malloc(sizeof(char) * size);
return array;
}
void readTable(Table *ptr, const int N) {
char buffer[100], *cpyPtr, *savePtr;
for (int i = 0; i < N; ++i) {
fgets(buffer, sizeof(buffer), stdin);
buffer[strlen(buffer) - 1] = '\0';
ptr[i].country = strtok_r(buffer, " ", &savePtr);
ptr[i].country = strdup(ptr[i].country);
cpyPtr = strtok_r(NULL, " ", &savePtr);
ptr[i].gold = strtol(cpyPtr, &cpyPtr, 10);
cpyPtr = strtok_r(NULL, " ", &savePtr);
ptr[i].silver = strtol(cpyPtr, &cpyPtr, 10);
cpyPtr = strtok_r(NULL, " ", &savePtr);
ptr[i].bronze = strtol(cpyPtr, &cpyPtr, 10);
}
}
void printTable(Table *ptr, const int size) {
for (int i = 0; i < size; ++i) {
printf("%s %d %d %d\n", ptr[i].country, ptr[i].gold,ptr[i].silver, ptr[i].bronze);
}
}
int compare(const void *p, const void *q) {
return ((Table *)p)->gold<((Table *)q)->gold;
}
int main(int argc, char const *argv[]) {
int N; // Amount of lines
scanf("%d", &N);
getchar();
Table* tab = malloc(sizeof(Table)*N);
readTable(tab,N);
printTable(tab,N);
qsort(tab, N,sizeof(Table), compare);
printTable(tab,N);
free(tab);
return 0;
}
outputs:
BRA 3 4 5
USA 23 76 34
CHN 23 54 12
GER 10 20 23
USA 23 76 34
CHN 23 54 12
GER 10 20 23
BRA 3 4 5
This is my simple program that generate a array of N integers, print it, and it will call the getevennumber function, and the function will return the pointer addresses of the even numbers in array. and the main program will print the even numbers in the array:
#include <stdio.h>
int* getEvenNumber(int a[]);
int main (){
int N;
printf("Enter N: ");
scanf("%d", &N);
int array[N], i;
int *test[N];
srand(time(NULL));
for(i = 0; i < N; i++)
{
array[i] = (rand() % 100)+1;
printf("%d \n", array[i]);
}
printf("------- \n");
*test = getEvenNumber(array);
for(i = 0; i <= sizeof(test); i++){
printf("%d \n", *test[i] );
}
return 0;
}
int* getEvenNumber(int a[]){
int i,j = 0;
int* ptr[j];
for(i = 0; i <= sizeof(a); i++)
{
if (a[i] % 2 == 0)
{
ptr[j] = &a[i];
printf("%d\n",*ptr[j]);
j++;
}
}
return *ptr;
}
currently the problem is: when I run the program, it will print the desired even numbers, then the program will also print 2 random data address then crushes, here is an example output:
N: 10
66
19
70
54
84
12
35
56
53
19
66
70
54
84
19
1981890690
-1090571325
(program crushed)
Can someone help me identify the problem please, thank you!
In the function getEvenNumber, you're creating a local variable ptr which adress you are returning. You should not do that, because local variables only exist within a function, and never outside of it. Also, you are actually returning the value of the first element of ptr (because you are dereferencing it). This is why *test[i] fails, because you never return the actual array and thus cannot iterate over it with [i].
The best solution would be to declare the array in the main function and pass it like this getEvenNumber(int a[], int *ptr[])
And don't declare your array with size zero... (as you are currently doing with ptr).
for(i = 0; i <= sizeof(test); i++){
printf("%d \n", *test[i] );
}
sizeof(test) isn't the number of elements in the array test, it's sizeof(int*) which is 8 (bytes), assuming you're on a 64-bit system. It's returning the size of a pointer to a memory address, not the actual length of the array. So your loop goes outside the bounds of the array which probably causes your problem.
Also you're returning a local variable, which can cause additional problems.
I was asked to write a program that produces a 2d array of random numbers. My code produces strange results. Regardless of the size of the matrix it produces a "reverse diagonal matrix" (not sure what else to call it). I was to understand that rand() produces a pseudorandom number between 0 and RAND_MAX but somehow the results are dependent on the size of my matrix, I am unsure how this behavior could happen.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAT_SIZE 5
void main (void)
{
srand(time(0));
unsigned char * ptr = malloc(MAT_SIZE*MAT_SIZE);
unsigned char i, j;
for(i = 0; i < MAT_SIZE; i++)
{
for(j = 0; j < MAT_SIZE ; j ++)
{
*(ptr + i + j ) = rand();
}
}
for(i = 0; i < MAT_SIZE ; i++)
{
for(j = 0; j < MAT_SIZE ; j ++)
{
printf("%5d", *(ptr + i + j));
}
printf("\n");
}
free(ptr);
}
Output for 3*3
142 141 11
141 11 230
11 230 28
Output for 5*5
232 157 62 131 245
157 62 131 245 54
62 131 245 54 138
131 245 54 138 246
245 54 138 246 108
Even a pseudorandom number shouldn't behave differently based on how it is used. Is there something I'm not understanding about the program that forces these results?
The problem is not with the random numbers that are generated but with how you are saving them in your matrix. To access element (j, i) you do not want
*(ptr + i + j )
but
*(ptr + MAT_SIZE * i + j )
You are only accessing the first i+j members of the array, and looping over the same indices repeatedly. Instead of:
*(ptr + i + j )
Try
*(ptr + i * MAT_SIZE + j )
Note that you can dynamically allocate a 2D array as follows:
unsigned char (*ptr)[MAT_SIZE] = malloc( MAT_SIZE * sizeof *ptr );
...
ptr[i][j] = rand();
...
free( ptr );
Makes life a little simpler. This way you can use normal 2D array indexing instead of having to map i and j to a single dimension.
Nits:
Unless your compiler documentation explicitly lists void main() as a valid signature for main, use int main( void ) instead. I know you've seen thousands of examples of void main() in books and on line, but just because the compiler doesn't complain about it doesn't mean it isn't wrong.
rand() returns int, which will not fit into an unsigned char. Overflow on unsigned types is well-defined, but even so, you may want to explicitly map your rand result onto the range [0..255].