I need to store an array of point (x,y). I read the points from a file, and the number of points are not constant, but i can get it at the first line of the file. So i write a procedure load() to loading the points from the file and store them in a global array. It doesn't work.
My code:
int *array[][]; // this is a pointer to a 2-dimensional array??
void load(){
..
int tempArray[2][n]; //n is the first line of the file
..
array = tempArray;
}
You're trying to return a pointer to memory that is local to the function that defines the variable. Once that function stops running ("goes out of scope"), that memory is re-used for something else, so it's illegal to try and reference it later.
You should look into dynamic allocation, and have the loading function allocate the needed memory and return it.
The function prototype could be:
int * read_points(const char *filename, size_t *num_points);
Where filename is of course the name of the file to open, num_points is set to the number of points found, and the returned value is a pointer to an array holding x and y values, interleaved. So this would print the coordinates of the first point loaded:
size_t num_points;
int *points;
if((points = load_points("my_points.txt", &num_points)) != NULL)
{
if(num_points > 0)
printf("the first point is (%d,%d)\n", points[0], points[1]);
free(points);
}
This declaration of yours does not work:
int *array[][]; // this is a pointer to a 2-dimensional array??
First, it is trying to declare a 2D array of int *. Second, when you declare or define an array, all dimensions except the first must be specified (sized).
int (*array)[][2]; // This is a pointer to a 2D array of unknown size
This could now be used in a major variant of your function. It's a variant because I misread your question at first.
void load(void)
{
...
int tempArray[n][2]; // Note the reversed order of dimensions!
...
array = &tempArray;
...there must be some code here calling functions that use array...
array = 0;
}
Note that the assignment requires the & on the array name. In the other functions, you'd need to write:
n = (*array)[i][j];
Note, too, that assigning the address of a local array to a global variable is dangerous. Once the function load() returns, the storage space for tempArray is no longer valid. Hence, the only safe way to make the assignment is to then call functions that reference the global variable, and then to reset the global before exiting the function. (Or, at least, recognize that the value is invalid. But setting it to zero - a null pointer - will more nearly ensure that the program crashes, rather than just accessing random memory.
Alternatively, you need to get into dynamic memory allocation for the array.
Your question actually is wanting to make a global pointer to a VLA, variable-length array, where the variable dimension is not the first:
int tempArray[2][n]; // Note the reversed order of dimensions!
You simply can't create a global pointer to such an array.
So, there are multiple problems:
Notation for pointers to arrays
Initializing pointers to arrays
Assigning global pointers to local variables
You can't have global pointers to multi-dimensional VLAs where the variable lengths are not in the first dimension.
You should minimize the use of globals.
A more elegant version might go like this:
typedef struct point_ { int x; int y; } point;
point * create_array(size_t n)
{
return calloc(n, sizeof(point));
}
void free_array(point * p)
{
free(p);
}
int main()
{
size_t len = read_number_from_file();
point * data = create_array(len);
if (!data) { panic_and_die(); }
for (size_t i = 0; i != len; ++i)
{
/* manipulate data[i].x and data[i].y */
}
free_array(data);
data = 0; /* some people like to do this */
}
You are trying to assign an array but in C arrays cannot be assigned.
Use memcpy to copy one array to another array. Arrays elements in C are guaranteed to be contiguous.
int bla[N][M] = {0};
int blop[N][M];
/* Copy bla array to blop */
memcpy(blop, bla, sizeof blop);
Related
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
}
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.
I'm in the process of teaching myself C and I'm mistified as to what's causing the following issue: when I create an array in a method and return it as a pointer to the calling function, none of the content is correct. I've boiled down this problem to the following example:
char * makeArr(void){
char stuff[4];
stuff[0]='a';
stuff[1]='b';
stuff[2]='c';
stuff[3]='d';
printf("location of stuff:%p\n",stuff);
int i;
for(i = 0; i < 4; i++){
printf("%c\n",stuff[i]);
}
return stuff;
}
int main(void){
char* myarr;
myarr = makeArr();
int i;
printf("\n");
printf("location of myarr:%p\n", myarr);
for(i = 0; i < 4; i++){
printf("%c\n",myarr[i]);
}
}
The output returns the following:
location of stuff:0028FF08
a
b
c
d
location of myarr:0028FF08
Ä
ÿ
(
(a null character)
So I've verified that the locations between the two values are the same, however the values differ. I imagine that I'm missing some critical C caveat; I could speculate it's something to do with an array decaying into a pointer or a problem with the variable's scope, but and any light that could be shed on this would be much appreciated.
What you're attempting to do is return the address of a local variable, one that goes out of scope when the function exits, no different to:
char *fn(void) {
char xyzzy = '7';
return &xyzzy;
}
That's because, other than certain limited situations, an array will decay into a pointer to the first element of that array.
While you can technically return that pointer (it's not invalid in and of itself), what you can't do is dereference it afterwards with something like:
char *plugh = fn();
putchar (*plugh);
To do so is undefined behaviour, as per C11 6.5.3.2 Address and indirection operators /4 (my bold):
If an invalid value has been assigned to the pointer, the behaviour of the unary * operator is undefined.
Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.
Having stated the problem, there are (at least) two ways to fix it.
First, you can create the array outside of the function (expanding its scope), and pass its address into the function to be populated.
void makeArr (char *stuff) {
stuff[0]='a';
stuff[1]='b';
stuff[2]='c';
stuff[3]='d';
}
int main(void) {
char myarr[4];
makeArr (myarr);
// Use myarr here
}
Second, you can dynamically allocate the array inside the function and pass it back. Items created on the heap do not go out of scope when a function exits, but you should both ensure that the allocation succeeded before trying to use it, and that you free the memory when you're finished with it.
char *makeArr (void) {
char *stuff = malloc (4);
if (stuff != NULL) {
stuff[0]='a';
stuff[1]='b';
stuff[2]='c';
stuff[3]='d';
}
return stuff;
}
int main(void) {
char *myarr;
myarr = makeArr();
if (myarr != NULL) {
// Use myarr here
free (myarr);
}
}
stuff[] only exists on the stack during function call, it gets written over after return. If you want it to hold values declare it static and it will do what you want.
However, the whole idea is fundamentally lame, don't do that in real life. If you want a function to initialize arrays, declare an array outside of the function, pass a pointer to this array as a parameter to the function and then initialize an array via that pointer. You may also want to pass the size of the array as a second parameter.
Since you're learning, a sample code is omitted intentionally.
Your array stuff is defined locally to the function makeArr. You should not expect it to survive past the life of that function.
char * makeArr(void){
char stuff[4];
Instead, try this:
char * makeArr(void){
char *stuff=(char*)calloc(4, sizeof(char));
This dynamically creates an array which will survive until you free() it.
In this toy code example:
int MAX = 5;
void fillArray(int** someArray, int* blah) {
int i;
for (i=0; i<MAX; i++)
(*someArray)[i] = blah[i]; // segfault happens here
}
int main() {
int someArray[MAX];
int blah[] = {1, 2, 3, 4, 5};
fillArray(&someArray, blah);
return 0;
}
... I want to fill the array someArray, and have the changes persist outside the function.
This is part of a very large homework assignment, and this question addresses the issue without allowing me to copy the solution. I am given a function signature that accepts an int** as a parameter, and I'm supposed to code the logic to fill that array. I was under the impression that dereferencing &someArray within the fillArray() function would give me the required array (a pointer to the first element), and that using bracketed array element access on that array would give me the necessary position that needs to be assigned. However, I cannot figure out why I'm getting a segfault.
Many thanks!
I want to fill the array someArray, and have the changes persist outside the function.
Just pass the array to the function as it decays to a pointer to the first element:
void fillArray(int* someArray, int* blah) {
int i;
for (i=0; i<MAX; i++)
someArray[i] = blah[i];
}
and invoked:
fillArray(someArray, blah);
The changes to the elements will be visible outside of the function.
If the actual code was to allocate an array within fillArray() then an int** would be required:
void fillArray(int** someArray, int* blah) {
int i;
*someArray = malloc(sizeof(int) * MAX);
if (*someArray)
{
for (i=0; i<MAX; i++) /* or memcpy() instead of loop */
(*someArray)[i] = blah[i];
}
}
and invoked:
int* someArray = NULL;
fillArray(&someArray, blah);
free(someArray);
When you create an array, such as int myArray[10][20], a guaranteed contiguous block of memory is allocated from the stack, and normal array arithmetic is used to find any given element in the array.
If you want to allocate that 3D "array" from the heap, you use malloc() and get some memory back. That memory is "dumb". It's just a chunk of memory, which should be thought of as a vector. None of the navigational logic attendant with an array comes with that, which means you must find another way to navigate your desired 3D array.
Since your call to malloc() returns a pointer, the first variable you need is a pointer to hold the vector of int* s you're going to need to hold some actual integer data IE:
int *pArray;
...but this still isn't the storage you want to store integers. What you have is an array of pointers, currently pointing to nothing. To get storage for your data, you need to call malloc() 10 times, with each malloc() allocating space for 20 integers on each call, whose return pointers will be stored in the *pArray vector of pointers. This means that
int *pArray
needs to be changed to
int **pArray
to correctly indicate that it is a pointer to the base of a vector of pointers.
The first dereferencing, *pArray[i], lands you somewhere in an array of int pointers, and the 2nd dereferencing, *p[i][j], lands you somewhere inside an array of ints, pointed to by an int pointer in pArray[i].
IE: you have a cloud of integer vectors scattered all over the heap, pointed to by an array of pointers keeping track of their locations. Not at all similar to Array[10][20] allocated statically from the stack, which is all contiguous storage, and doesn't have a single pointer in it anywhere.
As others have eluded to, the pointer-based heap method doesn't seem to have a lot going for it at first glance, but turns out to be massively superior.
1st, and foremost, you can free() or realloc() to resize heap memory whenever you want, and it doesn't go out of scope when the function returns. More importantly, experienced C coders arrange their functions to operate on vectors where possible, where 1 level of indirection is removed in the function call. Finally, for large arrays, relative to available memory, and especially on large, shared machines, the large chunks of contiguous memory are often not available, and are not friendly to other programs that need memory to operate. Code with large static arrays, allocated on the stack, are maintenance nightmares.
Here you can see that the table is just a shell collecting vector pointers returned from vector operations, where everything interesting happens at the vector level, or element level. In this particular case, the vector code in VecRand() is calloc()ing it's own storage and returning calloc()'s return pointer to TblRand(), but TblRand has the flexibility to allocate VecRand()'s storage as well, just by replacing the NULL argument to VecRand() with a call to calloc()
/*-------------------------------------------------------------------------------------*/
dbl **TblRand(dbl **TblPtr, int rows, int cols)
{
int i=0;
if ( NULL == TblPtr ){
if (NULL == (TblPtr=(dbl **)calloc(rows, sizeof(dbl*))))
printf("\nCalloc for pointer array in TblRand failed");
}
for (; i!=rows; i++){
TblPtr[i] = VecRand(NULL, cols);
}
return TblPtr;
}
/*-------------------------------------------------------------------------------------*/
dbl *VecRand(dbl *VecPtr, int cols)
{
if ( NULL == VecPtr ){
if (NULL == (VecPtr=(dbl *)calloc(cols, sizeof(dbl))))
printf("\nCalloc for random number vector in VecRand failed");
}
Randx = GenRand(VecPtr, cols, Randx);
return VecPtr;
}
/*--------------------------------------------------------------------------------------*/
static long GenRand(dbl *VecPtr, int cols, long RandSeed)
{
dbl r=0, Denom=2147483647.0;
while ( cols-- )
{
RandSeed= (314159269 * RandSeed) & 0x7FFFFFFF;
r = sqrt(-2.0 * log((dbl)(RandSeed/Denom)));
RandSeed= (314159269 * RandSeed) & 0x7FFFFFFF;
*VecPtr = r * sin(TWOPI * (dbl)(RandSeed/Denom));
VecPtr++;
}
return RandSeed;
}
There is no "array/pointer" equivalence, and arrays and pointers are very different. Never confuse them. someArray is an array. &someArray is a pointer to an array, and has type int (*)[MAX]. The function takes a pointer to a pointer, i.e. int **, which needs to point to a pointer variable somewhere in memory. There is no pointer variable anywhere in your code. What could it possibly point to?
An array value can implicitly degrade into a pointer rvalue for its first element in certain expressions. Something that requires an lvalue like taking the address (&) obviously does not work this way. Here are some differences between array types and pointer types:
Array types cannot be assigned or passed. Pointer types can
Pointer to array and pointer to pointer are different types
Array of arrays and array of pointers are different types
The sizeof of an array type is the length times the size of the component type; the sizeof of a pointer is just the size of a
pointer
I have a function that I pass an array into and an int into from my main function. I am doing operations to the array inside this new function, let's call it foo. In foo, I initialize another array with 52 cells all with 0. I do operations on the array that I passed from main, and transfer that data to the newly initialized array. I want to return the new array back to the main function. But of course, I can't return data structures like arrays. So I instead return an int pointer that points to this array. Inside the int main, I pass the pointer to have it point to various cells in the array. When I print the results of what the pointer is pointing to, it should either be pointing to 0 or an integer greater than 0. But instead, I get inconsistent results. For some reason, some of the values that SHOULD be 0, prints out garbage data. I've been trying to spot the bug for some time, but I just wanted a second hand look at it. Here is just the GENERAL idea for the code for this portion anyways...
int main(){
int *retPtr;
char input[] = "abaecedg";
retPtr = foo(input, size);
for(i=0; i<52; i++){
// error displayed here
printf("%d\n", *(retPr + i));
}
}
int foo(char input[], int size)
{
int arr[52] = {0}; // should initialize all 52 cells with 0.
int i=0, value; // looking for non-zero results in the end.
int *ptr = &arr[0];
for(i=0; i<size; i++){
if(arr[i] > 64 && arr[i] < 91){
value = input[i] - 65;
arr[value]++;
}
}
return ptr;
}
Hopefully this makes sense of what I'm trying to do. In the foo function, I am trying to find the frequency of certain alphabets. I know this might be a bit cryptic, but the code is quite long with comments and everything so I wanted to make it as succinct as possible. Is there any possible reason why I'm getting correct values for some (numbers > 0, 0) and garbage values in the other?
The reason you get garbage back is that the array created in foo is allocated in foos stack frame, and you then return a pointer into that frame. That frame is discarded when foo returns.
You should allocate the array on the heap (using malloc and friends) if you want it to remain after foo returns. Don't forget to free() it when you're done with the array.
int main(){
char input[] = "abaecedg";
int retPtr[] = foo(input, size); //An array and a pointer is the same thing
...
free(retPtr);
}
int *foo(char input[], int size)
{
int arr[] = calloc(52*sizeof(int); // should initialize all 52 cells with 0.
...
arr[value]++;
...
return arr;
}
Another way is to let foo take an array as a parameter and work with that, in this way:
int main(){
int ret[52] = {0};
...
foo(input, size, ret);
...
}
void foo(char input[], int size, int *arr)
{
...
arr[value]++;
...
return; //Don't return anything, you have changed the array in-place
}
The reason this works is because an array is the exact same thing as a pointer, so you are really passing the array by reference into foo. arr will be pointing to the same place as ret, into the stack frame of main.
In function foo the array arr is a local array, that is, allocated on the stack. You must not return any pointer of data allocated on the stack, since the stack is rewinded after you return from the function, and its content is no more guaratneed.
If you want to return an array you should allocate it on the heap using malloc, for example, and return the pointer malloc returned. But you will then have to free that memory somewhere in your program. If you fail to free it you will have what's called a "memory leak", which may or may not crash/disturb this program from running again, depending on your environment. A not clean situation, that's for sure.
That's why I consider C not so good for functional programing idioms, such as returning things from function (unless they are primitive types). I would achieve what you tried to do by passing another array to foo - an output array, companioned by a size variable, and fill that array.
Alternately, you could wrap the array within a struct and return that struct. Structs can be returned by value, in which case they are copied via the stack to the caller function's returned value.