Here are my two structs:
typedef struct simple_command_t {
char * in, *out, *err;
char **tokens;
int builtin;
} simple_command;
typedef struct command_t {
struct command_t *cmd1, *cmd2;
simple_command* scmd;
char oper[2];
} command;
And here is the code I'm using:
int main() {
command *check1;
if ((check1 -> scmd -> tokens) == NULL){
printf("tokens are null");
}
return 0;
}
Since I've read that you can't check if a struct is NULL I've tried checking the members inside of the empty struct instead. Unfortunately everything I've tried so far has been giving me segfaults. What's the problem?
There is no such thing as an "empty" struct. (The phrase "empty struct" would make sense if C permitted structs with no members, but it doesn't, and that's not what you're referring to anyway.)
I think what you're trying to do is check whether the struct has been initialized, either via an initializer or an assignment. There is no way to do that.
Here's a simpler example:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *ptr;
/* code that may or may not initialize ptr */
if (<ptr has been initialized>) {
printf("ptr = %p, *ptr = %d\n", (void*)ptr, *ptr);
}
else {
fprintf(stderr, "ptr is uninitialized\n");
exit(EXIT_FAILURE);
}
}
There is no way to write the condition <ptr has been initialized>. Since ptr is not a static object, its initial value is not necessarily a null pointer or any other particular value; it is indeterminate garbage. It could, just by coincidence, happen to contain a valid address; there is no way to distinguish between that possibility and an actual valid value that was stored in ptr deliberately.
The only reliable way to determine whether ptr has been initialized or not is to initialize it:
int *ptr = NULL;
The same reasoning applies to your example. You define a pointer object:
command *check1;
It's defined in side a function, it's not static, so its initial value is indeterminate garbage. Just reading the value of the pointer:
if (check1 == NULL) ...
has undefined behavior; even if it didn't, the result of the comparison wouldn't tell you anything useful. You must carefully write your code so that you never attempt to use the value of check1 before assigning a known value to it. The easiest way to do that is simply to initialize it:
command *check1 = NULL;
If you initialize it to NULL it doesn't point to anything; there is no structure object to test. You can create a structure and assign its address to check1:
check1 = malloc(sizeof *check1);
Now check1 has a valid value (which could still be a null pointer of malloc failed; always check for that). If malloc succeeded, check1 points to a struct object whose value itself is indeterminate garbage. The same considerations that applied to check1 itself now apply to the struct object *check1, and to each of its members.
One common approach is to define a function that creates a struct object and properly initializes all its members.
Related
I have this struct
struct FluxCapacitor{
unsigned char* c_string;
unsigned int value;
};
Now I need to create an instance of this struct. I googled this problem and found that I have to use something like this
typedef struct FluxCapacitor{
unsigned char* c_string
unsigned int value;
};
But I dont really understand the next step with malloc(). Can someone explain it to me?
You do not need malloc() to create an instance of a struct. And I would recommend that you avoid typedefing structures merely to reduce keystrokes. The extra keystrokes would only be saved in declarations and function prototypes (and maybe if you need to cast something), since you don't need the struct keyword elsewhere; the advantage is that when you see struct FluxCapacitor, you know exactly what it is. If you only see FluxCapacitor alone, you don't know if it is a typedef for a struct, or a union, or an integer type or what.
Note that the posted code was missing the semicolon at the end of the declaration. Also, it is unclear why you have unsigned char* c_string;. This may not allow assignment to a string literal. I have changed this in the code below. You can create a single struct like this:
struct FluxCapacitor
{
char *c_string;
unsigned int value;
};
...
struct FluxCapacitor fcap_1;
You can then assign values to the fields of fcap_1:
fcap_1.c_string = "McFly";
fcap_1.value = 42;
Note that you could also use designated initializers at the point of declaration:
struct FluxCapacitor fcap_2 = { .c_string = "Biff",
.value = 1985
};
If you need an array of FluxCapacitor structures, just declare one:
struct FluxCapacitor fcaps[2];
You can assign to the fields of each array member in a loop:
struct FluxCapacitor fcaps[2];
char *somestrings[] = { "McFly", "Biff" };
unsigned somevalues[] = { 42, 1985 };
for (size_t i = 0; i < 2; i++) {
fcaps[i].c_string = somestrings[i];
fcaps[i].value = somevalues[i];
}
Alternatively, you can use designated initializers here too:
struct FluxCapacitor fcaps[2] = { { .c_string = "McFly", .value = 42 },
{ .c_string = "Biff", .value = 1985}
};
Using malloc()
Since OP seems determined to use malloc(), it would be good to first recall that memory allocated with malloc() must later be deallocated with free(). Also note that malloc() can fail to allocate memory, returning a null pointer. Thus the result of a call to malloc() must be checked before attempting to dereference this pointer. The additional complexity should be avoided in favor of the above approaches unless OP has good reason to do manual allocation.
In the code below, the function create_flux_cap() takes a string and an unsigned int as arguments, and returns a pointer to a newly allocated FluxCapacitor structure with the arguments assigned to the appropriate fields. Note that since the FluxCapacitor structure is accessed through a pointer, the arrow operator is used instead of the dot operator.
Inside the function, the return value from the call to malloc() is checked before attempting assignment. If the allocation has failed, no assignment is made and a null pointer is returned to the calling function. Note that in the call to malloc(), the result is not cast, since there is no need for this in C and it needlessly clutters the code. Also observe that an identifier is used instead of an explicit type with the sizeof operator. This is less error-prone, easier to maintain if types change in the future, and is much cleaner code. That is, instead of this:
new_fcap = (struct FluxCapacitor *)malloc(sizeof (struct FluxCapacitor));
use this:
new_fcap = malloc(sizeof *new_fcap);
In main(), the return values from the calls to create_flux_cap() are checked. If an allocation has failed, the program exits with an error message.
The stdlib.h header file has been included for the function prototypes of malloc() and exit(), and also for the macro EXIT_FAILURE.
#include <stdio.h>
#include <stdlib.h>
struct FluxCapacitor
{
char* c_string;
unsigned value;
};
struct FluxCapacitor * create_flux_cap(char *, unsigned);
int main(void)
{
struct FluxCapacitor *fcap_1 = create_flux_cap("McFly", 42);
struct FluxCapacitor *fcap_2 = create_flux_cap("Biff", 1985);
/* Check for allocation errors */
if (fcap_1 == NULL || fcap_2 == NULL) {
fprintf(stderr, "Unable to create FluxCapacitor\n");
exit(EXIT_FAILURE);
}
/* Display contents of structures */
printf("%s, %u\n", fcap_1->c_string, fcap_1->value);
printf("%s, %u\n", fcap_2->c_string, fcap_2->value);
/* Free allocated memory */
free(fcap_1);
free(fcap_2);
return 0;
}
struct FluxCapacitor * create_flux_cap(char *str, unsigned val)
{
struct FluxCapacitor *new_fcap;
new_fcap = malloc(sizeof *new_fcap);
if (new_fcap != NULL) {
new_fcap->c_string = str;
new_fcap->value = val;
}
return new_fcap;
}
You need malloc for dynamic allocation of memory.In your case, both the types char and int are known to the compiler, it means the compiler can know the exact memory requirement at compile time.
For e.g. you can create a struct object like in the main function
#include<stdio.h>
#include<stdlib.h>
struct FluxCapacitor{
unsigned char* c_string;
unsigned int value;
};
int main() {
FluxCapacitor x;
x.c_string = "This is x capacitor"
x.value = 10
}
The x is of value type. You can make a copy and pass around this value. Also, observe we are using . notation to access its member variables.
But this doesn't happen at all time. We are not aware of future FluxCapacitor requirement and so above program will need more memory as while it is running and by using the malloc we can ask the compiler to provide us requested memory. This is a good place to use malloc, what malloc does is, it returns us a pointer to a piece of memory of the requested size. It is dynamic memory allocation.
Here's a simple example: let suppose if you need struct declaration of FluxCapacitor but don't know how many you will need, then use malloc
#include<stdio.h>
#include<stdlib.h>
typedef struct FluxCapacitor {
unsigned char* c_string;
int value;;
} flux;
// typedef is used to have the alias for the struct FluxCapacitor as flux
int main() {
flux *a = malloc(sizeof(flux)); // piece of memory requested
a -> c_string = "Hello World"; // Pointer notation
a -> value = 5;
free(a); // you need to handle freeing of memory
return 0;
}
.
I am taking the operating system class in mit online, I completed the first assignement http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-828-operating-system-engineering-fall-2012/assignments/MIT6_828F12_assignment1.pdfbut what surprised me is how they return the data structures, they work with a data structure and they return a smaller data structure, and to use it they just cast it back. I see that it can optimize the code but is this safe ? is it good practice ?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct small
{
int n ;
};
struct big
{
int n ;
char * string ;
};
struct small* f()
{
struct big* x = malloc(sizeof(struct big));
x->n = 'X';
x->string = strdup("Nasty!");
return (struct small*) x ;
}
int main(int argc, char *argv[])
{
struct big *y = (struct big*)f();
printf("%s\n",y->string);
}
EDIT 1 : here is the link from mit, i just replicated the idea in my own code.
http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-828-operating-system-engineering-fall-2012/assignments/sh.c
No structure is returned, but a pointer to a structure. A pointer contains the address of the memory where the actual object is located. (In this case it has been allocated dynamically with malloc, hence has dynamic storage duration and will live until the pogram ends or a free is called on the pointer.)
The code is legal and has defined semantics. 6.3.2.3/7 of the n1570 draft says
A pointer to an object type may be converted to a pointer to a
different object type. If the resulting pointer is not correctly
aligned for the referenced type, the behavior is undefined. [does not apply here. -ps]
Otherwise, when converted back again, the result shall compare equal
to the original pointer.
Note that the structures could be completely unrelated (the first data element does not need to be the same type). The cast could even be to a built-in type like int.
The issue may be different if the object were accessed through a pointer of the wrong type (which it isn't) because of aliasing issues.
To answer your questions:
Is it safe?
Obviously not. Just casting the type of a pointer to something else is something you should only do if you are positively sure it's the right type.
However, if you know that, everything is fine.
Is it good practice?
No, not in this shape.
You sometimes do Object Oriented Programming in C in a similar way (compare CPython's PyObject): You use one "base" object, and one "type" struct which have a structure like:
struct obj_type {
const char* name;
size_t length; // this is important so that you can copy the object later on without knowing its insides
};
struct obj_base {
obj_type* type;
};
Because it is guaranteed that in C, pointers to structs point to the address of their first element, you can use further objects that build atop of that:
struct more_complex_object {
obj_type* type;
int value;
};
...
int main() {
obj_type *more_complex_object_type = malloc(sizeof(obj_type));
more_complex_object_type->name = "A more complex object type";
more_complex_object_type->length = sizeof(more_complex_object);
more_complex_object *obj = malloc(more_complex_object_type->length);
obj->type = more_complex_object_type;
obj->value = 10;
...
//let's now use it as a simple instance of the "super" object
obj_base* just_an_object = (obj_base*)more_complex_object;
//when we copy things, we make sure to copy the full length:
obj_base* target = malloc(sizeof(more_complex_object));
memcpy(target, just_an_object, just_an_object->type->length);
//now, when handling an object, we can check its type
if(just_an_object->type == more_complex_object_type) {
more_complex_object *my_obj = (more_complex_object)just_an_object;
printf("value: %d\n", my_obj->value);
}
}
Yes it is safe, as long your compiler follows the C standard
Why doesn't GCC optimize structs?
But no, I do not consider this a good practice.
Good practices are relative, and should never be use as a rule. This construction is required if you want to simulate OO inheritance behavior with C.
I have declared the structure:
typedef struct keyValuePairs{
char* type;
char* key;
char* valueType;
char* value;
} keyValueType;
keyValueType keyValuePairs[1000];
And in a function declared the local variables as:
char key[500];
char value[500];
to hold the key value pair values as:
key[i]="abc";
value[i]="xyz"
I have assigned these local variables to the global variable as:
keyValuepairs[1].key=key.
Once i come out of the function, the values assigned in the structure is getting lost. Can someone explain where I am going wrong?
Please note I am fairly new to C.
Both key and value variables are pointers to arrays that are allocated in the stack when you are in the function. After keyValuepairs[1].key=key the global variable points to that same place in the stack. After exiting the function, the memory where those arrays were is reused.
I suggest you read up on static vs dynamic allocation in C
If I understand you correctly, you are trying something along the lines of:
typedef struct
{
char* val;
} A;
A alist[10];
void foo()
{
char t[10];
t = "abc";
alist[0].val = t;
}
int main()
{
foo();
}
First of all, the line
t = "abc";
is syntactically incorrect. You have to use something like:
strcpy(t, "abc");
But the most important error is that when you return from foo, alist[0].val points to an address that is not good any more. To make sure alist[0].val points to a valid address, you have to allocate memory from the heap for it and copy the contents of t to it.
void foo()
{
char t[10];
strcpy(t,"abc");
alist[0].val = malloc(strlen(t)+1);
strcpy(alist[0].val, t);
}
To do a thorough job, you'll have to make sure that you call free on that allocated memory at some point before you return from main.
You have not allocated memory for type, key, valueType and value.
Try static memory allocation :
typedef struct keyValuePairs{
char* type[n];
char* key[n];
char* valueType[n];
char* value[n];
}
Where n is a defined constant
I have a following problem in which I can't figure out how to assign a char* called funcName to a char* called fname. Need some help, thanks.
#define MAX_PARMS 5
typedef enum {C_INT, C_SHORT, C_CHAR, C_FLOAT, C_INT_PTR} DataType;
typedef struct {
char name;
int *value;
DataType dType;
} VarType;
typedef struct {
char *funcName;
VarType parms[MAX_PARMS];
int numParms;
} FrameType;
void enterSumFunc (StackType *stkPtr, char *fname, int num, int *arr, int *sum) {
FrameType *temp;
//temp->funcName = fname;
strcpy(temp->funcName, fname);
}
As you can see I have tried both strcpy and manually setting the char* but nothing works; both give a segmentation fault. Any help will be useful, thanks.
FrameType *temp;
temp->funcName ...
dereferences an uninitialized pointer, which yields undefined behavior, which in this case you are able to observe as segmentation fault. One of the possible solutions is using an object with automatic storage duration instead of pointer:
FrameType temp;
temp.funcName ...
Also note that
temp->funcName = fname;
assigns the value of pointer fname (i.e. an address it points to) to the pointer funcName, no copying is performed and once the memory associated with fname is freed, this temp->funcName will be an invalid (dangling) pointer and using it will also result in undefined behavior.
On the other hand:
strcpy(temp->funcName, fname);
tries to copy null-terminated string stored in fname to funcName and in case the string is not null terminated or there is no memory associated with this pointer, it will result in undefined behavior as well.
Note that:
typedef struct {
char *funcName;
VarType parms[MAX_PARMS];
int numParms;
} FrameType;
only declares a pointer funcName so you should either explicitly allocate a memory using malloc before trying to copy a string to it or yet even better, use a buffer with automatic storage duration instead:
typedef struct {
char funcName[255];
VarType parms[MAX_PARMS];
int numParms;
} FrameType;
temp is not set, so dereferencing it (->) will never be valid.
Based on edited code (specifying FrameType)
FrameType *temp = malloc(sizeof(FrameType));
temp->funcName = fname;
or
FrameType obj;
FrameType *temp = &obj;
temp->funcName = fname;
Will "work", but it's a "shallow copy" of data. If the "owner" of fname deletes it or changes it, then your temp object becomes invalid. You can either use strdup() to copy the name, or put a char[] in the FrameType instead of just a pointer.
If temp really is a temp (and doesn't have to live past the end of the function call) then the second approach is probably better.
Remember for each malloc you need a free or elase you will leak memory. The second approach shown above reduces that risk...
Code is as follows:
/* set.h */
struct setElement{
char *element;
setElement *next;
};
typedef struct setElement *Set; //Set is now the equivalent of setElement*
Set a;
setInit(&a);
/* setInit function declaration # setInit.c */
int setInit(Set *a){
(*a)->element = "asdf"; //results in a seg fault
}
Trying to malloc 'a' works, but if I try to access any member within the set 'a' doesn't work. I understand I'm passing a reference of the set from the main() function to setInit, so I believe the pointer contained within setInit is addressing the memory allocated by 'Set a' in the main() function, so a malloc wouldn't be required...
Iunno. Help is appreciated :)
The problem is that you have not allocated the setElement you are trying to assign to. In the main part of the code you are creating a Set, which is just a pointer to a setElement. This pointer is never set to point to anything sensible. I.e. you need something like
Set a = malloc(sizeof(setElement));
Alas, it is unclear where exactly your variables are defined. I assume your main.c is something like
#include "set.h"
Set a;
int main()
{
setInit(&a);
}
If so, your a, which is a pointer by itself, should point to somewhere.
If your framework wants malloc()ed data, you should do
int main()
{
a = malloc(sizeof(*a)); // *a is a struct setElement now, with 2 pointer-sized members.
setInit(&a); // Now seInit should be able to operate on the struct as wanted.
}
As #amaurea has mentioned, you'll need to make use of malloc() for your setElement structure. In addition to this, you need to do the same for the setElement struct's element member. A char* is merely a pointer to a char or char array and will not implicitly allocate anything.
int setInit(Set *a){
(*a)->element = "asdf"; //results in a seg fault
}
Could be re-written
int setInit(Set *a){
(*a)->element = malloc(sizeof("asdf"));
strcpy((*a)->element,"asdf");
}
Which the above could be rewritten to take a second parameter of the actual element contents.