I'm trying to get the number of elements in an array of structs so I can pass it into another function. Struct:
struct info{
char string1[30];
float float1;
int int1;
char string2[30];
};
Section I'm trying to run:
void function1(){
struct info* temp = build();
printf("flag: %lu %lu %lu\n", sizeof(temp), sizeof(temp[0]), sizeof(temp)/sizeof(temp[0]));
sortFloat(temp, sizeof(temp)/sizeof(temp[0]), 1);
free(temp);
}
build() returns an array of structs after reading in data from a file where each line will be a struct in the array. I'm having trouble passing the size of the array into sortFloat(). The print line returns
flag: 8 72 0
when there are only two lines in the data file. Hard coding that argument as 2 makes the whole program work correctly. Why is this method of counting the elements of the array of structs not?
sizeof(temp)
will not evaluate to the number of elements in the array. It will evaluate to just the size of the pointer.
If you need the size of the array, you can do this:
Change the signature of build to:
struct info* build(int* sizePtr);
Make sure that sizePtr is appropriately set in the implementation.
Then, call it using:
int size;
struct info* temp = build(&size);
What you are thinking of as an array is more precisely just a pointer to the first element. How many elements follow the first element cannot be known to function1(). Only the function build() knows how many elements were read and how much memory was dynamically allocated to store those elements.
The only solution is to get the build() function to also pass back the number of elements read from the file. One way to do this is to send the address of an int variable to build(int *countp) and have build(int *countp) store the count into this int using either ++*countp; as it reads each element or *countp = n; where n is a different variable in which build(...) maintains the count.
Because temp is not an array. It is a pointer. So calling sizeof on it will return the size of the pointer.
It might be hard to understand, but in C, arrays (real arrays, not pointers) are best regarded as value types that are quite tricky to pass around by value. Arrays are not pointers and pointers are not arrays.
sizeof is an operator for determining the size of memory occupied by a value. That is why, when applied to an array, it returns the size of the array, and when applied to a pointer - just the size of the pointer.
What you're creating and returning from build() is most likely a dynamically-allocated (via malloc or friends) buffer of memory. In this case, it was never a real array to begin with! It is just a pointer to a chunk of memory on the heap. This chunk of memory is not one value, and its size cannot be determined using sizeof like that. So you've got no choice but to count the number of allocated structs and get that information to the caller.
Related
I'm doing a homework assignment for Computing II. It's to create a to-do list of tasks in a dynamically created array of strings that can manipulated in a number of ways. One of the ways it needs to be manipulated is through the addition of a task, or an element of the array through the use of realloc. My code is as follows, and will run until I call the freshly realloc'd array in a different function.
void add_task(char **List, int line_num){
char task[1000];
List = (char**)realloc(List, (line_num+1)*sizeof(char));
List[line_num] = malloc((1000) * sizeof(char));
printf("Please enter the string you would like to use as your new task.\n");
scanf("%s",task);
strcat(task,"\n");
strcpy(List[line_num],task);
return;
}
Your realloc() call is wrong, you're providing the wrong size. Since List is char**, the elements are char*, not char.
List = realloc(List, (line_num+1)*sizeof(char*));
Since sizeof(char*) is likely to be 4, you're allocating only 1/4 as much space as you need. And then you're writing outside the bounds of this array, resulting in undefined behavior.
In general, whenever you're assigning to <something>* with malloc or realloc, the argument to sizeof should be <something>, i.e. just remove the last * from the type.
I have an char array of fixed size in C application. I am passing that array to some function and from there I am passing it to multiple functions. So that the array gets filled in some of the functions based on some condition. Since I am sending a fixed size array I am facing problem when I copy data to it if the size is more than the array size. I know that I have to make that char array dynamic but as I said that array gets filled in multiple functions and size will be different. So do I need to dynamically allocate the array wherever it gets filled? Consider the array gets filled in 30+ different functions. Or is there a way to do a minimal modification?
As your question title says C, IMO the best approach will be to decalre a pointer of that particular variable type in your main() function, pass the address of that pointer [essencially a double-pointer] to other functions and allocate memory dynamically.
You can keep on passing the pointer to all other functions. Inside every called functions, measure the amount of memory required to put the data [from that particular function] and use realloc() to increase the available memory.
As mentioned by UncleO, the required pointer should be the pointer to array [i.e, a double pointer]
EDIT
For the very first time allocating memory to that pointer, you can use malloc() or calloc().
From next time onwards, to extend [resize] the amount of memory, you need to use realloc()
You don't pass an array to a function in C, although it appears that way. What gets passed is a pointer to the first element of the array. The pointer is passed by value. That is, the value of the pointer (the memory location) is copied into a local variable. The contents of the array can be changed using this local variable.
If you use malloc() or realloc() with this local variable, then the pointer that was "passed in" won't be affected. realloc() may resize the memory, but it can also free that memory and allocate some new memory to the local variable.
If you want to change the array pointer, then you should pass in a pointer to the pointer. The thing the pointer points to is what is changed. This is a bit more cumbersome. But this way you can allocate more memory is needed.
#include <stdlib.h>
char* arr;
void changeit(char** arrptr)
{
*arrptr = realloc(*arrptr, 20*sizeof(char));
}
void main (void)
{
arr = malloc(10*sizeof(char));
changeit(&arr);
}
To function that do not alter the array, pass the array address and size.
int foo1(const char *array, size_t size, ...)
To each function that does not change the array size, pass array address and array size
int foo2(char *array, size_t size, ...)
To functions that may alter the array size, pass the address of the address of the array and the address of the size.
int foo3(char **array, size_t *size, ...)
Code could put these two variables together
typedef struct {
size_t size;
char array;
} YetAnotherArrayType;
Chux,
There's a little typo at then end of your post. I think you mean:
typedef struct {
size_t size;
char* array;
} YetAnotherArrayType;
You didn't make array a pointer type.
If the poster is handcrafting a container, the classic solution is to track both a size and a capacity.
In that model you allocate the array to some initial a capacity and set size to 0. You then track its population causing it grow by some chunk size or factor each time it fills up.
Frequent reallocation can be a massive performance drain and by the sounds of the program in question such behaviour seems likely.
I am currently trying to get the length of a dynamically generated array. It is an array of structs:
typedef struct _my_data_
{
unsigned int id;
double latitude;
double longitude;
unsigned int content_len;
char* name_dyn;
char* descr_dyn;
} mydata;
I intialize my array like that:
mydata* arr = (mydata*) malloc(sizeof(mydata));
And then resized it using realloc and started to fill it with data.
I then attempted to get its size using the code described here.
sizeof(arr) / sizeof(arr[0])
This operation returns 0 even though my array contains two elements.
Could someone please tell me what I'm doing wrong?
If you need to know the size of a dynamically-allocated array, you have to keep track of it yourself.
The sizeof(arr) / sizeof(arr[0]) technique only works for arrays whose size is known at compile time, and for C99's variable-length arrays.
sizeof cannot be used to find the amount of memory that you allocated dynamically using malloc. You should store this number separately, along with the pointer to the allocated chunk of memory. Moreover, you must update this number every time you use realloc or free.
mydata* arr = (mydata*) malloc(sizeof(mydata));
is a pointer and not an array. To create an array of two items of mydata, you need to do the following
mydata arr[2];
Secondly, to allocate two elements of mydata using malloc(), you need to do the following:
mydata* arr = (mydata*) malloc(sizeof(mydata) * 2);
OTOH, length for dynamically allocated memory (using malloc()) should be maintained by the programmer (in the variables) - sizeof() won't be able to track it!
You're trying to use a pretty well known trick to find the number of elements in an array. Unfortunately arr in your example is not an array, it's a pointer. So what you're getting in your sizeof division is:
sizeof(pointer) / sizeof(structure)
Which is probably always going to be 0.
I am trying to print a dynamic array, but I am having trouble with the bounds for the array.
For a simple example, lets say I'm trying to loop through an array of ints. How can I get the size of the array? I was trying to divide the size of the array by the size of the type like this sizeof(list)/sizeof(int) but that was not working correctly. I understand that I was trying to divide the size of the pointer by the type.
int *list
// Populate list
int i;
for(i = 0; i < ????; i++)
printf("%d", list[i]);
With dynamic arrays you need to maintain a pointer to the beginning address of the array and a value that holds the number of elements in that array. There may be other ways, but this is the easiest way I can think of.
sizeof(list) will also return 4 because the compiler is calculating the size of an integer pointer, not the size of your array, and this will always be four bytes (depending on your compiler).
YOU should know the size of the array, as you are who allocated it.
sizeof is an operator, which means it does its job at compile time. It will give you the size of an object, but not the length of an array.
So, sizeof(int*) is 32/62-bit depending on architecture.
Take a look at std::vector.
There is no standardized method to get the size of allocated memory block. You should keep size of list in unsigned listSize like this:
int *list;
unsigned listSize;
list = malloc(x * sizeof(int));
listSize = x;
If you are coding in C++, then it is better to use STL container like std::vector<>
As you wrote, you really did tried to divide the size of a pointer since list is declared as a pointer, and not an array. In those cases, you should keep the size of the list during the build of it, or finish the list with a special cell, say NULL, or anything else that will not be used in the array.
Seeing some of the inapropriate links to C++ tools for a C question, here is an answer for modern C.
Your ideas of what went wrong are quite correct, as you did it you only have a pointer, no size information about the allocation.
Modern C has variable length arrays (VLA) that you can either use directly or via malloc. Direcly:
int list[n];
and then your idea with the sizeof works out of the box, even if you changed your n in the mean time. This use is to be taken with a bit of care, since this is allocated on the stack. You shouldn't reserve too much, here. For a use with malloc:
int (list*)[n] = malloc(*list);
Then you'd have to adapt your code a bit basically putting a (*list) everywhere you had just list.
If by size you mean the number of elements then you could keep it in a counter that gets a ++ each time you push an element or if you dont mind the lost cycles you could make a function that gets a copy of the pointer to the first location, runs thru the list keeping a counter until it finds a k.next==null. or you could keep a list that as a next and a prev that way you wouldnt care if you lost the beginning.
The question is how to get the length of dynamically allocated 2D Arrays in C? I thought the code below should get the number of rows, but it doesn't.
char** lines;
/* memory allocation and data manipulation */
int length; //the number of rows
length = sizeof(lines)/sizeof(char*);
Any thoughts on this?
You can't get the length of dynamically allocated arrays in C (2D or otherwise). If you need that information save it to a variable (or at least a way to calculate it) when the memory is initially allocated and pass the pointer to the memory and the size of the memory around together.
In your test case above sizeof is returning the size of the type of lines, and thus your length calculation is equivalent to sizeof(char**)/sizeof(char*) and is likely to have the trivial result of 1, always.
The underlying implementation of malloc or new must inevitably keep track of the size of the memory allocated for your variable. Unfortunately, there is no standard way to get the size of allocated block. The reason is due to the fact that not all memory block are dynamically allocated, so having the function that only works for only dynamic allocation is not so useful.
void fillwithzero(int* array) {
unsigned int size = getsize(array); // return 0 for statically allocated array ??
for(int i = 0; i < size; i++) {
array[i] = 0;
}
}
Let us say we have getsize function that is capable of magically get the size of the dynamically allocated array. However, if you send pointer of a static array, or some array allocated by other means (e.g. external function) to fillwithzero, this function will not be working. That is why most C function that accept array required caller to send the size or the maximum size of the array along with the array itself.
You cannot find the size of an array dynamically allocated.
If you need pass this array to a function, create a structure containing the array and its size.
struct Line {
char** text;
uint32_t size;
};
You cannot get the length of a dynamically allocated array in C.
When you allocate it, you need to store that length somewhere, so you know how long it is.
For instance:
int length = ...;
lines = malloc(length*sizeof(char*));
If you need to pass this around to other functions, you will need to either pass them as separate parameters, or define a struct type that includes the length and the lines pointer.
You pass it along with your value. There's no way to find that out.
You can get the length of dynamically allocated memory, IF you use the NONPORTABLE MSVC/MinGW extension:
#include <malloc.h>
char *m = malloc(1234);
#ifdef __int64
printf("m size = %lu bytes", _msize(m) );
#endif