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.
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 huge problem allocating memory in C
i have this struct
typedef struct{
int x;
int y;
}T;
i want to create a function that dynamically adds a structs to a pointer.
something like:
int main()
{
T* t;
f(&t);
free(t);
}
up to this point i think everything is ok, now the function is where i get lost
void f(T** t)
{
T t1;
T t2;
T t3;
//first i malloc
*t=malloc(sizeof(T)*T_MAX_SIZE);//i want another function to make the array bigger, but this is not as important as the problem
t1.x=11;
t1.y=12;
t2.x=21;
t2.y=22;
t3.x=31;
t3.y=32;
//now i want to copy the values from t1,t2,t3 to t[0],t[1],t[2]
memcpy(&(*t[0]),&t1,sizeof(T));
memcpy(&(*t[1]),&t2,sizeof(T));
memcpy(&(*t[2]),&t3,sizeof(T));
}
i do not know the correct way of copying these structs.
the point of doing this is to use t out of the function
(in the main)
many thanks :D
Your memcpy calls are incorrect.
In the expression &(*t[0]), the array index has top precedence, followed by the pointer indirection. So with explicit parenthesis it looks like &(*(t[0])).
So it first tries to array subscript t, which is the address of t in main. In the case of t[0] it still works, but t[1] references something past that variable, invoking undefined behavior. You want the array index of what t points to, which is (*t)[i].
So the memcpy calls should be:
memcpy(&((*t)[0]),&t1,sizeof(T));
memcpy(&((*t)[1]),&t2,sizeof(T));
memcpy(&((*t)[2]),&t3,sizeof(T));
You don't need any copy functions to assign one structure to another - you simply equate them. So if you have
T var1 = {1, 2};
T var2 = var1;
the whole of var1 is copied to var2. Amending your (simplified) program:
#include <stdio.h>
#include <stdlib.h>
#define T_MAX_SIZE 10
typedef struct{
int x;
int y;
}T;
void f(T** t)
{
T t1;
*t=malloc(sizeof(T)*T_MAX_SIZE);
t1.x=11;
t1.y=12;
(*t)[0] = t1;
}
int main(void) {
T* t;
f(&t);
printf ("Result %d %d\n", t[0].x, t[0].y);
free(t);
return 0;
}
Program output:
Result 11 12
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 have used three different ways, which I think are equivalent, of assigning values to the members of the structures from another function. I am getting the result of b and c in the following structure correct but not that of a. Are these methods of changing the values of the member of the structure not equivalent?
#include<stdio.h>
typedef struct
{
int a,b,c;
}
test_str;
void change(test_str * my_str_ad);
int main()
{
test_str my_str;
change(&my_str);
printf("a: %d, b:%d, c: %d\n", my_str.a, my_str.b, my_str.c);
return 0;
}
void change(test_str * my_str_ad)
{
test_str my_str;
my_str = *my_str_ad;
my_str.a = 5;
(*my_str_ad).b = 6;
my_str_ad->c = 7;
}
my_str in main() is not same as my_str in change().
As you jump to change() the statement test_str my_str; create a new instance of test_str.
So member 'a' of my_str in main will not be effected by change().
(*my_str_ad).b = 6;
my_str_ad->c = 7; will work since you are modifying the test_str of main() using the pointer passed to change().
test_str my_str;
my_str = *my_str_ad;
my_str.a = 5;
What is happening here is that you are COPYING my_str_ad's target variable into my_str. So the changes you make to my_str do not affect the my_str in your main. This cannot be fixed in C. i.e only your other two methods can be used.
[C++ only]
What you can do to get this to work is to change the first line, as I mentioned, to-
test_str& my_str;
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));
}