dynamic define and allocate pointers - c

I want to dynamically define and allocate pointers:
#include<stdio.h>
#define def_var(type,name,i) type name##i
#define var(name,i) name##i
void main(){
int i;
for (i=0;i<10;i++){
def_var(float,*ww,i)=NULL;
}
for (i=0;i<10;i++){
var(ww,i)=(float *)malloc(100);
}
}
But when I compile it, lots of error come up. Can anybody help fix it?

You can't do what you're trying to do. Preprocessor macros are expanded at compile time, they can't depend on run-time variable values. So
def_var(float,*ww,i)=NULL;
is expanded into
float *wwi = NULL;
It doesn't, and can't, replace i with the value of the variable, it just performs text substitution.
Also, variable declarations have block scope, so any variables declared inside the for loop go away when the loop finishes.
Just declare an array of pointers.
float *ww[10];
for (int i = 0; i < 10; i++) {
ww[i] = malloc(100 * sizeof(float *));
}

If ww is supposed to represent 10 arrays of 100 floats each (known numbers at compile time), then just use a multi-dimensional array:
float ww[10][100];
and index accordingly when used (eg: ww[7][93] = 6;).
If 'ww' must contain dynamically allocated pointers as you say, then use (where each element is a pointer to an array of 100 floats)
float (*ww[10]) [100];
for (i=0;i<10;i++){
ww[i]=malloc(sizeof(float)*100);
}
and index accordingly when used (eg: (*(ww[7]))[93] = 6; or ww[7]->[93] = 6;).
Remember to free each when done.
for (i=0;i<10;i++){
free(ww[i]);
}
Caution: Remember malloc will not intialize the newly allocated memory - that is up to you! Strongly recommended to use calloc instead to zero-out the memory instead, so it is in a known state.

Related

Declare dynamically sized array in global scope

Not using C that often, I came across a possibly simple problem. I have several functions, that need access to a global array-variable g. But the actual size of this variable has to be defined in an init()-function. The size depends on some other stuff, so g has to be declared somehow with a dynamic size. I read about malloc and other functions, but I am not sure how to use them properly.
Example:
double g[dynamic]; // size is not known yet
int n;
void init()
{
// calculate "n" for array size
n = ...
// declare and initialze g with a size "n"
}
void dostuff()
{
for (int i = 0; i < n; i++)
work(g[i]);
}
How should I solve this?
You cannot use an array. You must use a pointer.
double *global_array; // size is not known yet
size_t nglobal_array; // may be helpful to have the size
void init(void)
{
// calculate "nglobal_array" for array size
nglobal_array = 42;
// declare and initialze global_array with a size "nglobal_array"
global_array = malloc(nglobal_array * sizeof *global_array);
if (global_array == NULL) {
fprintf(stderr, "Error allocating resources.\nProgram aborted.\n");
exit(EXIT_FAILURE);
}
}
void dostuff()
{
for (int i = 0; i < nglobal_array; i++)
work(global_array[i]);
}
Don't forget to free(global_array) when you no longer need it.
Complete usage would then be something like this
#include <stdlib.h>
// includes
// declarations & definitions as above
int main(void) {
init();
dostuff();
free(global_array);
}
What you want to achieve is not possible in C.
A global array must have a fixed size at compile, or at least at link time.
You can declare the array without a specified size:
extern double g[];
But it must be defined somewhere with an actual size, computed from a constant expression at the definition place, and the size cannot be determined from the above declaration, so it must be passed some other way to the functions that will use the array: either implicitly, with a special value signifying the end of the array (like '\0' for char strings) or explicitly via a separate variable as you posted. Note however that n and g are very poor name choices for global variables as they are likely to clash with local variable names and convey no meaning to the reader.
If the size is not known until run time, you should define a pointer instead of an array and also define a separate variable with the length of the array that will be allocated by the initialization function.
double *g;
size_t g_length;
No. C doesn't do that. Arrays declared in global scope have fixed space allocated for them in your binary(.EXE files on Windows and ELF executables on Linux). If you want an array of dynamic size, you need to dynamically allocate it.
Example is here:
#include <stdlib.h>
#define ARRAY_SIZE 100
typedef char T; //your type here
T* array;
void init() {
array = malloc(sizeof(T) * ARRAY_SIZE); //array filled with garbage values
//array = calloc(ARRAY_SIZE, sizeof(T)); //array filled with 0x00
}
void finish() {
free(array); // DO NOT ACCESS ARRAY AFTER THIS CALL!
}
int main() {
init();
array[6] = 63; //access array as normal
finish();
//array[41] = 23; //will most likely crash due to a segmentation fault, also called an access violation on Windoez
}

How to dynamically allocate an array of integers in C

A portion of my C code is shown below.
int data[10]={1,3,6,8,1,7,9,1,1,1};
b=10;
int out[b];
process(data, &b, out);
alpha (out, b);
data and out are int arrays. The function process takes the array data whose length is pointed by b (=10) and performs mathematical operation and then returns an array out whose length is then again returned by b (unknown and hence required to be dynamically allocated). Then the array out is sent with function alpha. Right now the function alpha always sends out[10] since b has been declared as 10 in second line of code. How can I allocate array out dynamically so that it contains only valid data returned after function process.
You need to know the difference between dynamic and static allocations.
There are 3 alternatives:
Static allocation:
You need to know in advance the array length. It must be a number and not a variable:
int out[10];
Array is static and is only locally scoped. So if you do:
function do_something()
{
int out[10];
}
you can't use the out array outside the function. But you can define out
outside and send it like this:
function do_something(int* out)
{
// do things
}
...
{
int out[10];
do_something(out);
}
Automatic allocation
When you do
int b = 100;
int out[b];
(which won't compile on gcc without the -std=c99 or -std=c11 flag), you get an automatic variable, which is very convenient if you don't use out out of scope, but can be a bit dangerous. The resulting array is generated in the Stack, and is destroyed when it goes out of scope (which is why it can get you into trouble if you use it freely). See
https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Variable-Length.html
We suggest you use:
Dynamic allocation
Where the array is generated on the Heap and you are responsible to clean it up when you're done with it. The down side is you need to clean it up yourself. The up side is you can use pass it around and use it anywhere.
int b=100;
int* out = (int*) malloc(b * sizeof(int));
// do things with out
free(out);
VERY IMPORTANT:
Do not change the value of the pointer out. If you do, then you won't free the right amount of memory. A nice thing to do is to copy the pointer, and use the copied address for free:
int b=100;
int* out = (int*) malloc(b * sizeof(int));
int* out_copy = out;
// do things with out. don't touch out_copy
free(out_copy);
int *out;
out=(int *) malloc(sizeof(int) * 10);
This will produce array out of integer type with size 10.
You need out to be a pointer - not an array - and you need to pass a pointer to out to the function, just like you do with b.
Example:
void f(int **a, int *size)
{
*a = malloc(23 * sizeof(**a));
*size = 23;
}
/* ... */
int *p = NULL;
int b = 0;
f(&p, &b);
/* 'p' has been allocated and 'b' has its size. */

How to return a char** in C

I've been trying for a while now and I can not seem to get this working:
char** fetch (char *lat, char*lon){
char emps[10][50];
//char** array = emps;
int cnt = -1;
while (row = mysql_fetch_row(result))
{
char emp_det[3][20];
char temp_emp[50] = "";
for (int i = 0; i < 4; i++){
strcpy(emp_det[i], row[i]);
}
if ( (strncmp(emp_det[1], lat, 7) == 0) && (strncmp(emp_det[2], lon, 8) == 0) ) {
cnt++;
for (int i = 0; i < 4; i++){
strcat(temp_emp, emp_det[i]);
if(i < 3) {
strcat(temp_emp, " ");
}
}
strcpy(emps[cnt], temp_emp);
}
}
}
mysql_free_result(result);
mysql_close(connection);
return array;
Yes, I know array = emps is commented out, but without it commented, it tells me that the pointer types are incompatible. This, in case I forgot to mention, is in a char** type function and I want it to return emps[10][50] or the next best thing. How can I go about doing that? Thank you!
An array expression of type T [N][M] does not decay to T ** - it decays to type T (*)[M] (pointer to M-element array).
Secondly, you're trying to return the address of an array that's local to the function; once the function exits, the emps array no longer exists, and any pointer to it becomes invalid.
You'd probably be better off passing the target array as a parameter to the function and have the function write to it, rather than creating a new array within the function and returning it. You could dynamically allocate the array, but then you're doing a memory management dance, and the best way to avoid problems with memory management is to avoid doing memory management.
So your function definition would look like
void fetch( char *lat, char *lon, char emps[][50], size_t rows ) { ... }
and your function call would look like
char my_emps[10][50];
...
fetch( &lat, &lon, my_emps, 10 );
What you're attempting won't work, even if you attempt to cast, because you'll be returning the address of a local variable. When the function returns, that variable goes out of scope and the memory it was using is no longer valid. Attempting to dereference that address will result in undefined behavior.
What you need is to use dynamic memory allocation to create the data structure you want to return:
char **emps;
emps = malloc(10 * sizeof(char *));
for (int i=0; i<10; i++) {
emps[i] = malloc(50);
}
....
return emps;
The calling function will need to free the memory created by this function. It also needs to know how many allocations were done so it knows how many times to call free.
If you found a way to cast char emps[10][50]; into a char * or char **
you wouldn't be able to properly map the data (dimensions, etc). multi-dimensional char arrays are not char **. They're just contiguous memory with index calculation. Better fit to a char * BTW
but the biggest problem would be that emps would go out of scope, and the auto memory would be reallocated to some other variable, destroying the data.
There's a way to do it, though, if your dimensions are really fixed:
You can create a function that takes a char[10][50] as an in/out parameter (you cannot return an array, not allowed by the compiler, you could return a struct containing an array, but that wouldn't be efficient)
Example:
void myfunc(char emp[10][50])
{
emp[4][5] = 'a'; // update emp in the function
}
int main()
{
char x[10][50];
myfunc(x);
// ...
}
The main program is responsible of the memory of x which is passed as modifiable to myfunc routine: it is safe and fast (no memory copy)
Good practice: define a type like this typedef char matrix10_50[10][50]; it makes declarations more logical.
The main drawback here is that dimensions are fixed. If you want to use myfunc for another dimension set, you have to copy/paste it or use macros to define both (like a poor man's template).
EDITa fine comment suggests that some compilers support variable array size.
So you could pass dimensions alongside your unconstrained array:
void myfunc(int rows, int cols, char emp[rows][cols])
Tested, works with gcc 4.9 (probably on earlier versions too) only on C code, not C++ and not in .cpp files containing plain C (but still beats cumbersome malloc/free calls)
In order to understand why you can't do that, you need to understand how matrices work in C.
A matrix, let's say your char emps[10][50] is a continuous block of storage capable of storing 10*50=500 chars (imagine an array of 500 elements). When you access emps[i][j], it accesses the element at index 50*i + j in that "array" (pick a piece of paper and a pen to understand why). The problem is that the 50 in that formula is the number of columns in the matrix, which is known at the compile time from the data type itself. When you have a char** the compiler has no way of knowing how to access a random element in the matrix.
A way of building the matrix such that it is a char** is to create an array of pointers to char and then allocate each of those pointers:
char **emps = malloc(10 * sizeof(char*)); // create an array of 10 pointers to char
for (int i = 0; i < 10; i++)
emps[i] = malloc(50 * sizeof(char)); // create 10 arrays of 50 chars each
The point is, you can't convert a matrix to a double pointer in a similar way you convert an array to a pointer.
Another problem: Returning a 2D matrix as 'char**' is only meaningful if the matrix is implemented using an array of pointers, each pointer pointing to an array of characters. As explained previously, a 2D matrix in C is just a flat array of characters. The most you can return is a pointer to the [0][0] entry, a 'char*'. There's a mismatch in the number of indirections.

Why will this not print?

Before you feel the need to mark this as a duplicate post, please don't. I have read all the threads on pointers, arrays, and functions I could find but almost all of them are far too advanced to be of any help to me.
I'm not getting an error, however my code will not print my array. It seems the issue here is using scanf. I don't think the values entered are actually being put into the array in main(). I've tried using pointers, but then I get the error "Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)" whenever I try to use scanf to collect user inputted values to put into the array.
What I am working on is limited to declaring my array in the main() function, but all the operations are to be performed in promptData() function. Any help would be great, I'm at my wits end trying to figure this out on my own.
#import <stdio.h>
void promptData(double data[], int numElem);
int main(int argc, const char * argv[])
{
int size, i;
double array[size];
promptData(array, size);
for (i = 0; i < size; i++)
printf("%.2lf\n", array[i]);
return 0;
}
void promptData(double data[], int numElem)
{
int i;
printf("Enter integer values for size of array.\n");
scanf("%i", &numElem);
for (i = 0; i < numElem; i++)
{
printf("Enter array values.\n");
scanf("%lf", &data[i]);
}
}
Your program has undefined behaviour because variable size was not initialized and has indeterminate value.
You should at first in main ask the user to enter the size of the array then define the array itself and only after that fill it with values.
For example
int main(int argc, const char * argv[])
{
int size = 0;
printf( "Enter a positive integer value for the size of the array: ");
scanf( "%i", &size);
if ( size == 0 ) exit( 1 );
double array[size];
promptData(array, size);
//...
Also in C there is no such a directive as
#import <stdio.h>
Use instead
#include <stdio.h>
At least in ANSI C 89 and C 90, you can't give a variable as the size of an array. The size of array should be known at compile time. You should be doing something like double array[size];.
Even in C99, where you can have variable sized arrays; the variables should contain proper index values at the time you declare the array. In that case, you should read the number from stdin and then declare the array.
Also in C, all parameters are passed by value. This means every function takes a copy of the parameters in the function. If you want to modify a variable's value, you should pass a pointer to it, and then modify the pointer's dereferenced value, something like:
void change(int *x)
{
*x = 7;
}
void first(void)
{
int x = 5;
change(&x);
printf("%d\n", x);
}
Adding on to the other, correct, answer by Zenith, if you want a dynamically allocated array (like you want to be able to change its size based on user input), then your only option is to use one of the memory allocation functions like malloc().
Once you actually have the size in your main function, declare your array like this:
int *myArray = malloc(sizeof(int) * size));//note that malloc will return a NULL if it fails
//you should always check
if(myArray != null) {
//do stuff with myArray like you were. You can just use myArray[] as long as you
//make SURE that you don't go beyond 'size'
}
free(myArray);
//VERY important that every malloc() has a free() with it
Note: untested, but the idea is there.
Further, to answer your other question.
If you find yourself in a situation where you need to call a function and use things INSIDE that function to change stuff where you called it, you have only two choices in C.
You can either return the value and assign it to a variable in the calling function like this:
int result = myFunction(someVariable, anotherVariable);
//do stuff with result
Or, use pointers.
I'm not explaining pointers here, that's usually several lectures worth of information, and is one of the more difficult concepts to grasp for introductory programmers. All I can tell you is you need to learn them, but this format is not the right way to go about doing that.
You're passing size to promptData as a copy.
Thus changes to numElem inside promptData will not affect the size variable in your main. Hence size remains uninitialized, i.e. has an undefined value and therefore should not be used as a size for an array.
If you need to initialize an array with a size that's only known at run-time, you need to allocate memory for the array dynamically using malloc, for example:
double* array = malloc(size * sizeof(double));

Array of C structs

If I create a struct in C and want to add them to an array that is not set to a fixed size, how is the array created?
Can one create a tempStruct which is used on every iteration while getting user input and store this in an array, always using the same tempStruct struct in the loop?
How is an array created if the size is unknown as it depends on user input, and how are structs added to this array?
When the size is unknown at compile time, you'll need to allocate the memory on the heap, rather than in the data segment (where global variables are stored) or on the stack (where function parameters and local variables are stored). In C, you can do this by calling functions like malloc.
MyStructType *myArray = (MyStructType *)malloc(numElements * sizeof(MyStructType)
... do something ...
free(myArray)
If you're actully using C++, it's generally better to use new[] and delete[], e.g.
MyStructType *myArray = new MyStructType[numElements]
... do something ...
delete [] myArray
Note that new[] must be paired with delete[]. If you're allocating a single instance, use new and delete (without "[]"). delete[] and delete are not equivalent.
Also, if you're using C++, it's generally easier and safer to use an STL vector.
the C array must be with fixed size this is what we have learned years ago
but memory allocation functions may help you to find a solution
in c++ you can use the operator new
int num=0;
cout<<"please enter the number"<<endl;
cin>>num;
int *x=new int[num];
for(int i=0;i<num;i++)
{
cout<<"enter element "<<(i+1)<<endl;
cin>>x[i];
}
//do your work
and as
Mr Fooz
mentioned delete[] is used to free the memory allocated by new[]
and this is a general example
If you are using the older C89 standard compiler, you cannot use variable length arrays. If you use C99 then you can create variable length array. For clarification: variable-lenght doesnt mean that the array lenght can change during execution. It just means that you can set it during execution instead of fixing a value during compile time.
For eg:
CreateArray(const int numberOfElements)
{
struct MyStruct arrayOfStructs[numberOfElements];
}
This is valid in C99 but not in C89. Check your compiler documentaion.
Yes, you can use a tempStruct during input which you add later to the array.
If the size of the array is unknown, then you are in trouble. You must keep track of the array's size somewhere. Just have an integer variable that you change every time you change your array to keep track of your array's size.
If the size of the struct is not known at compile time it is even more complicated. You either just store Pointers in the array which point to your actual struct elements in memory, or you have to keep track of the sizes of every struct in the array. In the later case you would have to do addressing in the array completely manually calculating a lot. While this is very memory efficient, it is also error prone and extremely hard to debug.
OK. sample to create an array that hold your struct using pointers:
struct MyStruct
{
/* code */
}
main()
{
counter = 0;
struct MyStruct** array = malloc(counter);
// Create new Element
struct MyStruct myElement;
myElement.someData = someValue;
// Add element to array:
array = realloc(array, sizeof(struct MyStruct*) * (counter + 1);
array[counter] = &myElement;
counter++;
// Create yet another new Element
struct MyStruct myElement;
myElement.someData = someOtherValue;
array = realloc(array, sizeof(struct MyStruct*) * (counter + 1);
array[counter] = &myElement;
counter++;
// Now remove the last element
free(array[counter -1]); // may have something more complicated than that, depending on your struct
array = realloc(array, sizeof(struct MyStruct*) * (counter - 1);
counter--;
}
this code is not tested!

Resources