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...
Related
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.
I have structure with char pointer. I want to allocate static memory to this struct member. How can I do this?
Example:
struct my_data {
int x;
bool y;
char *buf;
};
How to assign 10 bytes static memory to this char pointer? I know malloc to assign dynamic memory allocation. Is this Ok?
struct my_data data;
char buffer[10];
data.buf = &buffer[0];
PS: I am not allowed to change this struct and use malloc to assign dynamic memory.
That will be even simpler (array decays to pointer automatically):
data.buf = buffer;
note that buffer must have an ever-lasting lifetime or you have to make sure that it's not deallocated (i.e. routine where it is declared returns) while you're using it or referencing it.
Allocating from a subroutine and returning will cause underfined behaviour because memory will be deallocated on return.
For instance don't do this (as we often see in questions here):
struct my_data foo()
{
struct my_data data;
char buffer[10];
data.buf = &buffer[0];
return data;
}
int main()
{
struct my_data d = foo(); // buffer is already gone
Bugs introduced by this kind of UB are nasty because the code seems to work for a while, until the unallocated buffer gets clobbered by another function call.
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 want my struct to carry a string. I defined it like so:
typedef struct myStruct {
char* stringy
} myStruct
and a function
free(char *stringy){
//structObj is a struct object
structObj->stringy = stringy
}
Is this correct? I have a feeling that since it's a local variable, stringy will be lost, and the pointer will point to garbage.
Sorry, new with C.
It would be garbage if you were somehow using char** stringy, but structObj->stringy = stringy means "you know the thing that stringy points to? Now structObj->stringy points to that". Of course, it is still possible to unset the value which the pointer is pointing to, and at that point dereferencing will yield garbage.
Here's an example to make it clearer:
#include<stdio.h>
typedef struct mStruct {
char* stringy;
} myStruct;
myStruct * structObj;
void doSomething(char* stringy)
{
structObj->stringy = stringy;
}
int main(int argc, char* argv)
{
char* a = "abc\n";
structObj = malloc(sizeof(myStruct));
doSomething(a);
a = "qxr\n";
printf(structObj->stringy);
}// prints "abc\n"
If stringy is defined in callers of free function, as long as they keep the actual string in its place (where stringy points), no problem.
There is not any local variable declaration in your code.
You have to declare:
typedef struct myStruct {
char* stringy
} myStruct;
free(char *stringy){
myStruct *structObj;
structObj->stringy = stringy;
}
Pay attention to the semicolon that I've added to the end of the typedef declaration.
This was not not in your code.
The object structObj is a struct whose type is myStruct.
Now, your parameter stringy comes from another site, it is not lost.
But the struct structObj will have duration only inside your "free" function.
EDIT
I have fixed an error: the right declaration has to be "pointer to structObj", which is done in this way:
myStruct *structObj;
Observe that now myStruct is a non-initialized pointer, so the following assignment is legal:
structObj->stringy = stringy;
but will not work.
However I think this goes beyond the scope of the original question...
myStruct is type which you defined for your struct myStruct .that to you need to create an object before using.
you need to do like this:
typedef struct myStruct {
char *stringy;
} myStruct_t; //user defined data type
myStruct_t *obj;
// you need to allocate memory dynamically.
obj= (myStruct_t *) malloc(sizeof(myStruct_t));
usage:
scanf("%s",obj->stringy);
printf("%s",obj->stringy);
in function:
my_free(char *str) //str is local string
{
obj->stringy=str;
}
your can also try this code :
typedef struct myStruct {
char stringy[20]; //char *stringy
} myStruct_t; //user defined data type
myStruct_t obj; //object creation
usage:
scanf("%s",obj.stringy);
printf("%s",obj.stringy);
in function:
my_free(char *str) //str is local string
{
strcpy(obj.stringy,str);
}
You're correct that as soon as what it points to goes out of scope, it will point to garbage: this is a dangling pointer. You'll need to allocate some memory and perform a copy to fix this:
add_string(my_struct* s, const char* c)
{
size_t len = strlen(c);
s->file = malloc(len + 1);
strcpy(s->file, c);
}
Don't forget that you'll need to free it when you're done:
void destroy_struct(my_struct* s)
{
free(s->file);
free(s);
}
I have the following structure:
struct hashItem {
char userid[8];
char name[30];
struct hashItem *next;
};
In the function below I take a char pointer (char array) argument that I wish to assign to the struct.
void insertItem(struct hashItem *htable[], char *userid, char *name)
{
int hcode = hashCode(userid);
struct hashItem *current = htable[hcode];
struct hashItem *newItem = (struct hashItem*) malloc(sizeof(struct hashItem));
newItem->userid = userid;
newItem->name = name;
[...]
}
Instead I get the following error:
hashtable.c: In function ‘insertItem’:
hashtable.c:62: error: incompatible types in assignment
hashtable.c:63: error: incompatible types in assignment
Line 62 and 63 are the `newItem->..." lines.
You almost certainly don't want to just assign the char* to the char[] - as the compiler points out, the types are incompatible, and the semantics are not what you think. I assume you want the struct members to contain the values of the two char* strings - in which case, you want to call strncpy.
strncpy(target, source, max_chars);
You should chang your struct in
struct hashItem {
char userid[8];
char *name;
struct hashItem *next;
};
to assign a char pointer to a name. In the struct you defined
char name[30] are just 30 chars.
You can't assign a pointer to a string to a character array like you are trying to. Instead you need to copy the contents of the string with strncpy as Adam indicated:
strncpy (newItem->userid, userid, 8);
When you declare the struct with a character array in it, you are allocating memory inside the structure itself to store a string of the given length.
When you pass a pointer into your function, you are passing a memory address (an integer) that indicates where a null-terminated string can be found.
To assign the pointer to the array doesn't make sense. The array has memory allocated for it already -- it can't be made to "point" to another location.
While you can use pointers in your structure, you need to be very careful that when you assign them, you are telling them to point to something that is going to be valid for the duration of the time you will use the structure. For example, this code is bad, because the string passed to insertItem no longer exists after fillStructure returns:
struct hashItem
{
char * userid;
};
void insertItem (struct hashItem * item, char * userid)
{
item->userid = userid;
}
void fillStructure (struct hashItem * item)
{
const char string[] = "testing";
insertItem (item, string);
}
int main(void)
{
struct hashItem item;
fillStructure (&item);
/* item->userid is now a dangling pointer! */
}
For more, I would recommend reading the "Arrays and Pointers" chapter of the C FAQ -- start with Question 6.2 and keep reading from there.