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.
Related
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");
}
I'm basically curious if you could do something like this, without the use of pointers:
int myVariable = 0;
int varPointer = &myVariable;
*varPointer += 1; //This obviously won't work, but explains the concept
Yes, I know you can do this with pointers. I want to know if it can be done without pointers.
EDIT>
I want to be able to refer to an address contained in a variable without pointers.
The question is basically, "Can you achieve pointer functionality without using actual pointers? If so, how?"
This code uses integer arithmetic instead of pointer arithmetic:
#include <stdio.h>
#include <stdint.h>
int main(void)
{
int myVariable = 0;
uintptr_t varPointer = (uintptr_t)&myVariable;
varPointer += sizeof myVariable;
return 0;
}
You say in comments:
pointers /can/ contain addresses, but do not necessarily.
Pointer variables must either be null pointers or contain the address of an object. If your code appears to do otherwise then your program has already caused undefined behaviour.
"Hex" has nothing to do with it; base 16 is a way of outputting numbers and you can use any base you like.
Bear in mind that pointers do not necessarily correspond to numbers. On platforms where they don't, then uintptr_t will not exist.
#include <stdio.h>
#include <stdint.h>
int main(void){
int myVariable = 0;
intptr_t varPointer = (intptr_t)&myVariable;
*(int*)varPointer += 1;
printf("%d\n", myVariable);
return 0;
}
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.
I am writing a custom "vector" struct. I do not understand why I'm getting a Warning: "one" may be used uninitialized here.
This is my vector.h file
#ifndef VECTOR_H
#define VECTOR_H
typedef struct Vector{
int a;
int b;
int c;
}Vector;
#endif /* VECTOR_ */
The warning happens here on line one->a = 12
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include "vector.h"
int main(void){
Vector* one;
one->a = 12;
one->b = 13;
one->c = -11;
}
one has not been assigned so points to an unpredictable location. You should either place it on the stack:
Vector one;
one.a = 12;
one.b = 13;
one.c = -11
or dynamically allocate memory for it:
Vector* one = malloc(sizeof(*one))
one->a = 12;
one->b = 13;
one->c = -11
free(one);
Note the use of free in this case. In general, you'll need exactly one call to free for each call made to malloc.
You get the warning because you did not assign a value to one, which is a pointer. This is undefined behavior.
You should declare it like this:
Vector* one = malloc(sizeof(Vector));
or like this:
Vector one;
in which case you need to replace -> operator with . like this:
one.a = 12;
one.b = 13;
one.c = -11;
Finally, in C99 and later you can use designated initializers:
Vector one = {
.a = 12
, .b = 13
, .c = -11
};
When you use Vector *one you are merely creating a pointer to the structure but there is no memory allocated to it.
Simply use one = (Vector *)malloc(sizeof(Vector)); to declare memory and instantiate it.
This might not be the most professional solution, but instead of initialising it using malloc, you can also initialise it using new:
Vector *one = new Vector();
I personally find it more elegant.
foo.c
#include "main.h"
unsigned char currentBar;
struct foo myFoo[getNumBars()];
void initMyFoo(void)
{
currentBar=(getNumBars()-1);
for(i=0; i<(sizeof(myFoo)/sizeof(myFoo[0])); i++)
{
myFoo[i].we = 1;
myFoo[i].want = 0;
myFoo[i].your = 0;
myFoo[i].soul = 0;
}
}
main.c
#include "foo.h"
unsigned char getNumBars()
{
return getDipSwitchValues();
}
initMyFoo();
(struct foo is declared in foo.h.)
This code has to execute without hard coding a number for Bars, as the number of Bars will change according to whatever the user sets his DIP switches. Right now I'm not able to initialize myFoo; I get the error "constant expression expected in initializer." Do I have to initialize it like:
struct foo myFoo[];
and change it later? If so, how do I make myFoo[] the correct length? I obviously don't have a constant available that corresponds to the desired size. Do I need to dynamically allocate this or something?
I found this similar answer but it wasn't too helpful for me - C++ a class with an array of structs, without knowing how large an array I need
struct foo* myFoo;
unsigned int myFooSize;
void initMyFoo(void)
{
myFooSize = getNumBars();
myFoo = malloc(myFooSize * sizeof(*myFoo));
for (i=0; i<myFooSize; i++) {
/* ... */
}
}
void cleanupMyFoo(void)
{
free(myFoo);
myFoo = NULL;
myFooSize = 0;
}
1 - in C99 you can use variable length arrays, which allow you to create arrays whose lengths are runtime-determined. You can also use them via compiler extensions (GCC supports them for non-C99 C and C++), but that's not a portable solution.
int someUnknownSize = 0;
/* some code that changes someUnknownSize */
struct foo myFoo[someUnknownSize];
2 - Declare a pointer that will be allocated memory at runtime with malloc or calloc.
struct foo *fooPtr = 0; /* null pointer to struct foo */
int sizeToAlloc = 0;
/* determine how much to allocate/modify sizeToAlloc */
fooPtr = malloc(sizeToAlloc * sizeof(*fooPtr));
/* do stuff with the pointer - you can treat it like you would an array using [] notation */
free(fooPtr);
I usually go for an expected maximum array size and if it's needed, just resize it:
type * a = calloc(sizeof(type),exp_array_size);
and upon pushing a new value onto the array (yeak, OK, I treat it as if it was a stack...), I check its current size against the new one:
if (current_size > max_size) {
max_size *= 2;
realloc(a,max_size*sizeof(type));
}