If ListofChar is a pointer to Char (do not confuse with char) which represents struct charact,
then what does it mean the ListofChar chars in void report(ListofChar chars)?
Does chars just represents the pointer ListofChar?
#include <stdio.h>
#include <stlib.h>
struct charact {
char ch;
int occurs;
struct charact *next;
};
typedef struct charact Char;
typedef Char * ListofChar;
typedef Char * CharNode_ptr;
void letters(char name[50], ListofChar * chars_ptr);
void report(ListofChar chars);
Char * createnode(char ch);
int main() {
char name[50];
ListofChar chars = NULL;
scanf("%s", name);
letters(name, &chars);
report(chars);
return 0;
}
Char * createnode(char ch) {
CharNode_ptr newnode_ptr ;
newnode_ptr = malloc(sizeof (Char));
newnode_ptr -> ch = ch;
newnode_ptr -> occurs = 0;
newnode_ptr -> next = NULL;
return newnode_ptr;
}
Yes and no.
It seems that the code is written to imply the difference of "one charact" and "many pieces of charact".
Something like:
Char is one, a single struct.
ListOfChar in itself is a pointer to a single Char, but it implies that there are more of it following. With some way of identifying the last one, this allows a function to work on several, with only one parameter. Even without knowing immediatly how many there are.
There is another similar construct, which you do not mention in your question and which is apart from declaration not used in the shown code, CharNode_ptr. If you allow some pure speculation, I'd guess that the "more following" from above, is implemented in the rest of the code as a linked list.
The implication here is slightly different (or just more detailed), it suggests the additional detail that you find the "other" characts via following the link next inside each struct, provided that it is not NULL.
It is likely that the code is written to NOT imply this detail when using the ListOfChar type identifier, e.g. in the API (shown prototypes) for functions.
Something like:
ListofChar means:
"Hey user, do not worry, it is somehow more than one; but you do not need to know how exactly."
CharNode_ptr means:
"Hey programmer, keep in mind that you are dealing with linked lists."
This answer is based on my understanding of your question, which is as follows, I think your problem lies with the declaration of an array using pointers and a pointer.
As you know, every variable is a memory location and every memory location has its address defined. A pointer of any given type contains the address to the memory location. For your case, consider the following example.
struct charact * a;
we define a pointer 'a' of type 'struct charact' as of now the pointer 'a' holds a garbage value and if you try to assign something to it will give you an error because when you assign you system goes to 'a' takes up the garbage value and think of it as a memory address where it has to put the given value which cannot be done because the garbage address is probably not assigned to you. In order to assign a value at 'a' you first have to initialise 'a' by using malloc() or any other memory allocation functions. On doing so malloc() would return a memory address to you and then you can start and assign values to 'a'.
Now coming to your question, defining 'a' can act as an array or as a pointer to the structure. This depends on how much memory you are assigning to the variable using malloc(). You would probably assign the value as follows -
a = (struct charact *)malloc(sizeof(struct charact)*n)
if n>1, then you will get a memory address which is capable of holding more then on struct charact and hence will work as an array, and, if n=1 you can hold only one struct charact and hence it is a single entity.
Related
I am trying to work on an assignment with Struct nodes and linked lists. Here is a small part of the code where I am getting an error that I am unable to resolve. Please help Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct term{
char term[200];
double value;
};
void main(){
struct term **terms = (struct term *)malloc(sizeof(struct term));
// Using **terms is mandatory for the project
*terms[0]->term = "abc";
*terms[0]->value = 1; //This is line 15
//I am unable to fix the error in line 15 at "*terms".
//The error message states "Struct term **terms: Operend of '*' must be a pointer"
//The goal is to create nodes that can be accessed using *terms[i] with a for loop of index i
}
The variable "terms" is a ** (pointer to pointer), but you're dereferencing it three times: once with *, once with [], and once with ->. You probably mean "terms[0]->term".
There are a few problems with this implementation. First of all, you are creating a double pointer so you also need to allocate memory for the inner-pointer you are pointing to.
struct term** terms = (struct term**)malloc(sizeof(struct term*));
*terms = (struct term*)malloc(sizeof(struct term));
Secondly, you cannot do an implementation like shown below.
char c[5];
void main(void)
{
c = "abc";
}
This is wrong and compiler will throw an error. What you can do is to assign each character to the char array one-by-one. Alternatively you can use strcpy too.
((*terms)->term)[0] = 'a';
((*terms)->term)[1] = 'b';
((*terms)->term)[2] = 'c';
Given this ...
struct term **terms = (struct term *)malloc(sizeof(struct term));
... terms represents an object of type struct term **, a pointer to a pointer to a struct term. In that case,
*terms[0]->term is equivalent to *((terms[0])->term) by operator precedence
terms[0] is equivalent to *terms. It is a pointer of type struct term *.
terms[0]->term designates the member term of the structure to which terms[0] points, which is an array. This array value is automatically converted to a pointer to the first array element for the purposes of evaluating the larger expression.
*terms[0]->term therefore represents the first character in the array terms[0]->term. It is equivalent to terms[0]->term[0]. It does not make sense to attempt to assign a string literal to this one character.
Similarly, terms[0]->value designates member value of the structure to which terms[0] points. This is not a pointer, so it is not a suitable operand for the * operator. This is what your compiler's error message is telling you.
Syntactically, any of these would be consistent with the type of terms:
terms[0]->value = 1;
(*terms[0]).value = 1;
(*terms)->value = 1;
HOWEVER, even if one of those were used, the code would still be badly broken. I already mentioned the bad assignment to *terms[0].term. Also, the malloc() call reserves the wrong amount of memory for terms to point to, albeit probably more than enough for a single struct term *. Most problematically, however, terms[0] itself, the pointer, is never initialized with a valid (pointer) value. It doesn't point to anything to whose members you could actually assign. Probably, then, you want something more like this:
struct term **terms = malloc(sizeof(*terms)); // enough space for one pointer
*terms = malloc(sizeof **terms)); // enough space for one struct term
strcpy(terms[0]->term, "abc");
terms[0]->value = 1;
// ...
Plus, the return type of main() must be int, not void.
trying to remember the syntax for updating a pointer in a struct.
I have something like this for example.
typedef struct {
char *name;
}car;
And I have a function which is called
void update_Name(car *d, char *newname)
{
car->name = &newname;
}
Is that correct or would it just be simply newname?
Very straight forward dont worry about any other syntaxes or functions needed just wanted to know straight up how that would be updated. Thank you
That is not quite correct.
You have a char *newname function parameters. You have a char *name struct member. &newname creates a pointer to newname which would be char **. Not what you want.
You just want car->name = newname; That assigns a char* to a char*.
Always be sure to compile your programs with maximum warning levels. It will tell you when you assign mismatched pointers.
And also in code like this remember memory and pointer lifetimes. You are assigning a pointer to characters into a structure. Whatever that points to needs to survive at least as long as your car structure or your car->name will become a "dangling pointer" pointing to dead memory.
First, car->name is not correct because car is the name of a type, not a variable. You want d->name instead.
With that correction, the type of d->name is char *. You're attempting to assign an expression of type char ** to it which doesn't match.
newname is already of type char * which matches the type of d->name, so you can assign it directly.
d->name = newname;
I have the following structs:
typedef struct{
char *name;
int size;
void *data;
} Struct1;
typedef struct st2{
char *name;
struct st2 **Struct2array;
Struct1 **Struct1array;
int Struct1_n;
int Struct2_n;
} Struct2;
where the double pointers in Struct2 are used as dynamic arrays of pointers to other Struct2's or Struct1's. The data in Struct1 is used as a dynamic array to store some data. Struct1_n and Struct2_n represent the number of elements inside of their respective dynamic arrays.
When I make a variable of type Struct1, I fill the data by casting a char * to a void * and using memcpy to copy it into data. If I then cast to data back into a char pointer, I can get back the contents and they are generally the same. However, for some reason the values that data in Struct1 is pointing to change after the following line:
struct2pointer->Struct1array[struct2pointer->Struct1_n - 1] = struct1pointer;
Examples:
printf("%d\n", *(char *)(struct1pointer->data));
gives the value of the 1stbyte of struct1pointer->data as -96 immediately after the problematic line regardless of the value it printed immediately before(which was the same one memcpy-d into data). if I add 1 to the pointer before casting it to a char pointer(2nd byte) it always gives 32, if I add 2 (3rd byte)it always gives 96 and so on.
Why is this happening when the struct1pointer is on the right side of the assignment operator and what can be done to fix this?
EDIT:
Functions where content changes:
void struct2_addstruct1(Struct2 struct2pointer, Struct1 *struct1pointer){
struct2->Struct1_n++;
struct2pointer->Struct1array = realloc(struct2pointer->Struct1array, struct2->Struct1_n * sizeof(Struct1 *)); //edited to remove increment that was added on accident, isn't in the original code
struct2pointer->Struct1array[struct2pointer->Struct1_n - 1] = struct1pointer;
}
The function that creates Struct1:
void struct1_init(Struct1 *s, char *name, void *data, int size){
s->name = malloc(strlen(name) + 1);
strcpy(s->name, name);
s->size = size;
s->data = malloc(size);
memcpy(s->data, data, size);
}
This is how that funcion is called when creating struct1:
Struct1 *s;
struct1_init(s, name, data, size);
name, data and size are provided form the outside but shouldn't have anything to do with the problem.
Look at this code:
Struct1 *s;
struct1_init(s, name, data, size);
Here s is uninitialized.
However in struct1_init function you do assume that the pointer s is already pointing to a Struct1.
Maybe you forgot a malloc - like:
Struct1 *s = malloc(sizeof *s);
struct1_init(s, name, data, size);
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.
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...