I am trying to declare a data structure in c and set some variables but I'm having a bit of trouble.
struct point {
float *x;
float *y;
float *z;
};
this struct is 24 bytes long so that's fine by me.
const unsigned int sz = 1<<24;
struct point _points[sz];
for(int i = 0; i < sz; ++i)
{
_points[i].x = get_rand_float();
_points[i].y = get_rand_float();
_points[i].z = get_rand_float();
}
// get_rand_float() returns a pointer to float;
The problem that I am having is that the application will crash.
I playing with the code a bit it seems that maybe 1<<24 is too large? Bringing it down to 1<<14 the program runs just fine.
That brings me to another question, why would 1<<24 or about 16 million ints cause my program to crash? It's a fairly trivial program just int main boilerplate and this struct?
You don't want a structure of pointers to floats:
struct point {
float *x;
float *y;
float *z;
};
You want a structure of floats:
struct point {
float x;
float y;
float z;
};
In your code, sz is int variable, not an array. So, techinicaly you cannot use the array subscript operator on sz. That code should not compile.
Maybe, you wanted to write something like
_points[i].x = get_rand_float();
But then again, it depends on get_rand_float() return type. It has to return a float * (which is not very likely seeing the function name).
In case, if get_rand_float() returns afloat value, and you want to store the returned value, then you don't need to use pointers as your structure member variable. You can simply use float x; and so on.
One possible problem is that your array of points is too large for the stack. See here. You could fix that by a dynamic memory allocation, something like:
struct point *_points = malloc(sz*sizeof(struct point));
And of course, don't forget to free the memory when finished.
EDIT: Based on your edit, your crash occurs when you use a massive struct size (1<<24), or 16,777,216 items in the struct. Borrowing an answer from here:
Size limitation of C structure
It would appear that you may be violating C standard by having over 65535 bytes in an object. Since 1<<14 works, which is only 16384, that might be why. To verify, try using anything above 1<<16 - those should all crash because it would be over 65535.
On a side note, it would be helpful if you post the actual error message you get so we have a better idea of what is going on. :)
---Pre-Author Edit Answer---
Assuming get_rand_float() returns what it's supposed to, the problem is that sz is an int, not a struct. It should look like:
int sz = 24;
struct point _points[sz];
for(int i = 0; i < sz; ++i)
{
_points[i].x = get_rand_float();
_points[i].y = get_rand_float();
_points[i].z = get_rand_float();
}
Others have pointed out your two main problems (size too large, and you should be using float not float* in your struct). But there is another potential problem, too: you should not get into the habit of beginning an identifier name with an underscore, because, from Section 7.1.3 of the 1999 C standard:
All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.
All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.
Each macro name in any of the following subclauses (including the future library directions) is reserved for use as specified if any of its associated headers is included; unless explicitly stated otherwise (see 7.1.4).
All identifiers with external linkage in any of the following subclauses (including the future library directions) are always reserved for use as identifiers with external linkage.154
Each identifier with file scope listed in any of the following subclauses (including the future library directions) is reserved for use as a macro name and as an identifier with file scope in the same name space if any of its associated headers is included.
Keeping apart the big size of the array,your program is mainly crashing because there no memory allocated to the pointer variables x,y and z.
You have to allocate memory to the variables before assigning any values.
for(int i = 0; i < sz; ++i)
{
sz[i].x = get_rand_float(); <--- getting crash here!
sz[i].y = get_rand_float();
sz[i].z = get_rand_float();
}
for(i=0;i<sz;i++)
{
_points[i].x =(float *) malloc(sizeof(float));
_points[i].y = (float *) malloc(sizeof(float));
_points[i].z = (float *) malloc(sizeof(float));
*( _points[i].x) = get_rand_float();
*( _points[i].y) = get_rand_float();
*( _points[i].z) = get_rand_float();
}
for(i=0;i<sz;i++)
{
printf("%f %f %f ",*( _points[i].x), *(_points[i].y), *(_points[i].z));
printf("\n");
}
You can make your program simple by taking float as members of the structure instead of float pointers.
struct point {
float x;
float y;
float z;
};
int main()
{
int i;
for(i=0;i<sz;i++)
{
_points[i].x = get_rand_float();
_points[i].y = get_rand_float();
_points[i].z = get_rand_float();
}
for(i=0;i<sz;i++)
{
printf("%f %f %f ", _points[i].x, _points[i].y, _points[i].z);
printf("\n");
}
Related
I tested this code in C++ (doing the correct modifications, e.g. printf to std::cout) and it worked. But in C it doesn't. Why is that? If I remove the default values for my x and y in my typedef struct __POINT everything works fine.
#include <stdio.h>
#include <stdlib.h>
typedef struct __POINT
{
int x = 0, y = 0;
} Point;
int main()
{
Point *x = malloc(sizeof(Point));
x->x = 5;
x->y = 6;
printf("%i\n%i", x->x, x->y);
getchar();
return 0;
}
C - in contrast to C++ - does not support default values defined within a struct. So your program will simply not compile.
If you want to initialise the values to 0, you could overcome this by using calloc (which initializes the memory with 0):
Point *x = calloc(1,sizeof(Point));
C has no choseable default values for struct members, this syntax is just wrong. The only defaults are 0 initialization that is used when a specific field of a struct is missed in an initializer.
Since you are even using malloc, the storage that is allocated isn't initialized at all.
I have a function in C which calculates the mean of an array. Within the same loop, I am creating an array of t values. My current function returns the mean value. How can I modify this to return the t array also?
/* function returning the mean of an array */
double getMean(int arr[], int size) {
int i;
printf("\n");
float mean;
double sum = 0;
float t[size];/* this is static allocation */
for (i = 0; i < size; ++i) {
sum += arr[i];
t[i] = 10.5*(i) / (128.0 - 1.0);
//printf("%f\n",t[i]);
}
mean = sum/size;
return mean;
}
Thoughts:
Do I need to define a struct within the function? Does this work for type scalar and type array? Is there a cleaner way of doing this?
You can return only 1 object in a C function. So, if you can't choose, you'll have to make a structure to return your 2 values, something like :
typedef struct X{
double mean;
double *newArray;
} X;
BUT, in your case, you'll also need to dynamically allocate the t by using malloc otherwise, the returned array will be lost in stack.
Another way, would be to let the caller allocate the new array, and pass it to you as a pointer, this way, you will still return only the mean, and fill the given array with your computed values.
The most common approach for something like this is letting the caller provide storage for the values you want to return. You could just make t another parameter to your function for that:
double getMean(double *t, const int *arr, size_t size) {
double sum = 0;
for (size_t i = 0; i < size; ++i) {
sum += arr[i];
t[i] = 10.5*(i) / (128.0 - 1.0);
}
return sum/size;
}
This snippet also improves on some other aspects:
Don't use float, especially not when you intend to return a double. float has very poor precision
Use size_t for object sizes. While int often works, size_t is guaranteed to hold any possible object size and is the safe choice
Don't mix output in functions calculating something (just a stylistic advice)
Declare variables close to where they are used first (another stylistic advice)
This is somewhat opinionated, but I changed your signature to make it explicit the function is passed pointers to arrays, not arrays. It's impossible to pass an array in C, therefore a parameter with an array type is automatically adjusted to the corresponding pointer type anyways.
As you don't intend to modify what arr points to, make it explicit by adding a const. This helps for example the compiler to catch errors if you accidentally attempt to modify this array.
You would call this code e.g. like this:
int numbers[] = {1, 2, 3, 4, 5};
double foo[5];
double mean = getMean(foo, numbers, 5);
instead of the magic number 5, you could write e.g. sizeof numbers / sizeof *numbers.
Another approach is to dynamically allocate the array with malloc() inside your function, but this requires the caller to free() it later. Which approach is more suitable depends on the rest of your program.
Following the advice suggested by #FelixPalmen is probably the best choice. But, if there is a maximum array size that can be expected, it is also possible to wrap arrays in a struct, without needing dynamic allocation. This allows code to create new structs without the need for deallocation.
A mean_array structure can be created in the get_mean() function, assigned the correct values, and returned to the calling function. The calling function only needs to provide a mean_array structure to receive the returned value.
#include <stdio.h>
#include <assert.h>
#define MAX_ARR 100
struct mean_array {
double mean;
double array[MAX_ARR];
size_t num_elems;
};
struct mean_array get_mean(int arr[], size_t arr_sz);
int main(void)
{
int my_arr[] = { 1, 2, 3, 4, 5 };
struct mean_array result = get_mean(my_arr, sizeof my_arr / sizeof *my_arr);
printf("mean: %f\n", result.mean);
for (size_t i = 0; i < result.num_elems; i++) {
printf("%8.5f", result.array[i]);
}
putchar('\n');
return 0;
}
struct mean_array get_mean(int arr[], size_t arr_sz)
{
assert(arr_sz <= MAX_ARR);
struct mean_array res = { .num_elems = arr_sz };
double sum = 0;
for (size_t i = 0; i < arr_sz; i++) {
sum += arr[i];
res.array[i] = 10.5 * i / (128.0 - 1.0);
}
res.mean = sum / arr_sz;
return res;
}
Program output:
mean: 3.000000
0.00000 0.08268 0.16535 0.24803 0.33071
In answer to a couple of questions asked by OP in the comments:
size_t is the correct type to use for array indices, since it is guaranteed to be able to hold any array index. You can often get away with int instead; be careful with this, though, since accessing, or even forming a pointer to, the location one before the first element of an array leads to undefined behavior. In general, array indices should be non-negative. Further, size_t may be a wider type than int in some implementations; size_t is guaranteed to hold any array index, but there is no such guarantee for int.
Concerning the for loop syntax used here, e.g., for (size_t i = 0; i < sz; i++) {}: here i is declared with loop scope. That is, the lifetime of i ends when the loop body is exited. This has been possible since C99. It is good practice to limit variable scopes when possible. I default to this so that I must actively choose to make loop variables available outside of loop bodies.
If the loop-scoped variables or size_t types are causing compilation errors, I suspect that you may be compiling in C89 mode. Both of these features were introduced in C99.If you are using gcc, older versions (for example, gcc 4.x, I believe) default to C89. You can compile with gcc -std=c99 or gcc -std=c11 to use a more recent language standard. I would recommend at least enabling warnings with: gcc -std=c99 -Wall -Wextra to catch many problems at compilation time. If you are working in Windows, you may also have similar difficulties. As I understand it, MSVC is C89 compliant, but has limited support for later C language standards.
In my header file I have defined some structs:
typedef struct { double X; } feature_t;
typedef struct
{
int n;
feature_t *Features;
float *Weights;
} signature_t;
In my main code I declare some new structs and try to load them:
feature_t *f_x;
int i;
memset(f_x,0,sizeof(feature_t)*n_x);
for(i=0; i<n_x; i++){
f_x[i] = 100.0;
w_x[i] = (float)p_x[i];
}
When I go to compile this, I get the following error:
error: incompatible types when assigning to type ‘feature_t {aka struct <anonymous>}’ from type ‘double’
Why does the compiler having trouble loading this double into this field? I declared it as a double.
thanks!
There is a compile problem and a run-time problem that needs to be fixed once the compile problem is out of the way.
The compile problem is that you cannot cast a float to a struct, even when the struct's only field is a float. You need to assign it like this:
f_x[i].X = ... // some float expression here
The run-time problem is that feature_t *f_x; pointer cannot be used like an array until you assign it some memory. Recall that pointers are not arrays. You need to do something like this:
feature_t *f_x = malloc(sizeof(*f_x)*n_x);
You have two options:
The first: make your feature_t instance an "automatic" variable on the stack - so no extra work needs to be done, but you can't use the object from the caller of the function that creates it:
void doSomething(size_t n) {
struct feature_t f_x[n];
for(size_t i = 0; i < n; i++) {
f_x[i] = {};
f_x[i].X = 100.0;
}
}
(Note the above example uses a VLA, this is not permitted in C++, only C99)
Because f_X lives in the stack, the = {} initialization syntax means the raw object data in the stack is zeroed out.
(Note that you cannot use the ={} syntax to initialize a VLA, each element must be initialized individually)
The second is to use the heap, but you must ensure you deallocate the memory eventually otherwise it will be a memory leak:
void doSomething(size_t n) {
struct feature_t* f_x = calloc( n, sizeof(struct feature_t) );
if( f_x == NULL ) exit( EXIT_FAILURE );
for(size_t i = 0; i < n; i++) {
f_x[i].X = 100.0;
}
free( f_x );
}
In this case, f_x is actually a pointer to the array of feature_t instances that lives on the heap, so its lifespan is potentially beyond the doSomething function scope - however I called free before the function returned.
I used calloc which allocates and zeroes-out memory before returning control to the caller, whereas malloc only allocates memory and exposes what memory contents were there previously, which is generally undesirable unless you absolutely need the performance gains by not explicitly zeroing memory.
I recently learned that copying partially initialized structures through trivial construction or assignment is undefined in C++. Does the same hold true in C or does the standard guarantee that initialization and assignment behave like memcpy?
typedef struct { int i; int j; } A;
void foo() {
A x;
x.i = 0;
// Leave x.j indeterminate. Is the following well defined?
A y = x;
y.j = y.i + 1;
}
x is not "partially initialized" this is not initialized at all.
Reading x in your initializer for y propagates the "indetermined" valueness (if one can say so) to y. If int could have trap representations on your platform, this already would be an error.
But then you don't read that indeterminate field y.j, so there no problem at that particular assignment.
I came across this simple program somewhere
#include<stdio.h>
#include<stdlib.h>
char buffer[2];
struct globals {
int value;
char type;
long tup;
};
#define G (*(struct globals*)&buffer)
int main ()
{
G.value = 233;
G.type = '*';
G.tup = 1234123;
printf("\nValue = %d\n",G.value);
printf("\ntype = %c\n",G.type);
printf("\ntup = %ld\n",G.tup);
return 0;
}
It's compiling (using gcc) and executing well and I get the following output:
Value = 233
type = *
tup = 1234123
I am not sure how the #define G statement is working.
How G is defined as an object of type struct globals ?
First, this code has undefined behavior, because it re-interprets a two-byte array as a much larger struct. Therefore, it is writing past the end of the allocated space. You could make your program valid by using the size of the struct to declare the buffer array, like this:
struct globals {
int value;
char type;
long tup;
};
char buffer[sizeof(struct globals)];
The #define is working in its usual way - by providing textual substitutions of the token G, as if you ran a search-and-replace in your favorite text editor. Preprocessor, the first stage of the C compiler, finds every entry G, and replaces it with (*(struct globals*)&buffer).
Once the preprocessor is done, the compiler sees this code:
int main ()
{
(*(struct globals*)&buffer).value = 233;
(*(struct globals*)&buffer).type = '*';
(*(struct globals*)&buffer).tup = 1234123;
printf("\nValue = %d\n",(*(struct globals*)&buffer).value);
printf("\ntype = %c\n",(*(struct globals*)&buffer).type);
printf("\ntup = %ld\n",(*(struct globals*)&buffer).tup);
return 0;
}
The macro simply casts the address of the 2-character buffer buf into a pointer to the appropriate structure type, then de-references that to produce a struct-typed lvalue. That's why the dot (.) struct-access operator works on G.
No idea why anyone would do this. I would think it much cleaner to convert to/from the character array when that is needed (which is "never" in the example code, but presumably it's used somewhere in the larger original code base), or use a union to get rid of the macro.
union {
struct {
int value;
/* ... */
} s;
char c[2];
} G;
G.s.value = 233; /* and so on */
is both cleaner and clearer. Note that the char array is too small.