I am working on a simple filesystem, which (obviously) contains folders, files, etc.
A (simplified version of a) folder is represented by a structure while in RAM like so:
typedef struct{
char label[20];
unsigned int id;
t_node contents[50];
} folder;
Now, i obviously want label to contain the raw byte string with in it the name (even better would be the raw string without trailing 0, but that's a sacrifice I am willing to make).
No,here's how I create and use a struct:
folder* myFolder = (folder *) malloc(sizeof(folder));
myFolder->label = "name";
//Which doesn't work, if I try this:
char name[20] = "name";
myFolder->label = name;
//this too, doesn't work.
The error message says "incompatible types when assigning to type ‘char[20]’ from type ‘char *’".
Which I understand, but don't know how to resolve.
Thanks in advance
Use strncpy():
char name[20] = "name";
strncpy(myFolder->label, name, sizeof(myFolder->label) - 1);
myFolder->label[sizeof(myFolder->label) - 1] = 0;
Try using strncpy():
strncpy( myFolder->label, "name", 20 );
instead of
myFolder->label = "name";
You cannot use the assignment operator to fill the array, in this case the right hand side of "name" will resolve to a char pointer.
Also I would suggest replacing the constant 20 with some defined constant indicating what the value is (ie MAX_FOLDER_LABEL_LEN).
You need to use strcpy
strcpy(myFolder->label, "name");
An array is not a modifiable lvalue, so you can't assign a value to it. You have several solutions:
declares label as pointer to char;
use strcpy (or equivalent).
Related
I made a simple structure with both integer and char types, I am facing an Lvalue required error when assigning "Structures" to my LE structure string. I don't understand why because that's normally how I would assign a string.
#include<stdio>
#include<conio>
struct Lesson{
int lessonNumber;
char lessonName[80];
}LE;
main(){
LE.lessonName = "Structures";
LE.lessonNumber = 1;
printf("%s",LE.lessonName);
printf("%d",LE.lessonNumber);
getch();
}
One easy way to go about is (If you don't want to call strcpy):
#include<stdio.h>
struct Lesson{
int lessonNumber;
char *lessonName;
}LE;
int main(void){
LE.lessonName = "Structures";
LE.lessonNumber = 1;
printf("%s",LE.lessonName);
printf("%d",LE.lessonNumber);
}
Here lessonName is a pointer and not an array. With the assignment operator here: LE.lessonName = "Structures", you are assigning the address of where the string "Structures" is stored to LE.lessonName.
i don't understand why. because thats normally how i would assign a
string
There are a couple of things to keep in mind here. If you declare lessonName as an array (as you have done), you should keep in mind that an array is not something you can assign to. What you can assign to is a specific place / index in an array using the = operator. Thus you could build your c-string character-by-character or, you could call the strcpy function to copy a string character-by-character (including the \0) to lessonName.
When you use a pointer (char *lessonName) and say something like LE.lessonName = "Structure", this piece of string can't be modified. You can't do LE.lessonName[0] = 'g'. Of course you could modify LE.lessonName to point to some other string later on like LE.lessonName = "cat";.
So I have a structure, and one of its members is a string.
struct Output {
char *axis;
int value;
};
struct Output Jsoutput;
My question is, how do I store a string in axis?
char whichaxis[4][3] = {"LX","LY","RY","RX"};
// Store which axis and value of the joystick position in Jsoutput
Jsoutput.axis = whichaxis[jse.number];
printf("%s\n",Jsoutput.axis);
I feel like there should be some & somewhere, but not sure where.
Just use strdup
Jsoutput.axis = strdup(whichaxis[jse.number]);
You can copy a String with the function strcpy(destination, source)from string.h
see http://www.cplusplus.com/reference/cstring/strcpy/
Jsoutput.axis = malloc(3);
strcpy(Jsoutput.axis,whichaxis[jse.number]);
You don't have to "store" the string a second time.
char whichaxis[4][3] = {"LX","LY","RY","RX"};
Stores the string.
char *axis;
Says "I'm going to point at a string".
If you wanted a & in there, you could do:
Jsoutput.axis = & (whichaxis[jse.number][0]) ;
But the original designers of C were very pragmatic and let arrays turn into pointers all the time for convenience. See What is array decaying for more details.
I'm using lex to implement a scanner. I want to build a symbol table while parsing. I have two structs, SymbolEntry and SymbolTable (below). Most of the time, when I call my function for inserting a symbol (registerID, also below) I have all the information for the entry. However, when I have a constant I also want to get it's value, but that is not immediately available when I first create the entry. When I try to change the entries value later in the code, I'm invalidating the whole memory block used by that entry and the name and value are printing garbage.
Here are the two structs:
typedef struct{
char* type;
char* name;
char* value;
} SymbolEntry;
typedef struct{
SymbolEntry *entries;
size_t size;
size_t capacity;
} SymbolTable;
This is the registerID function, called when an {id} is matched. yytext contains the ID.
int registerID(char* type){
//create a new symbol entry with the specified type and name and a default value
SymbolEntry e;
e.type = type;
e.name = (char *)calloc(yyleng+1, sizeof(char));
strcpy(e.name, yytext);
e.value = "";
prevSym = insertSymbol(&table, e);
return prevSym;
}
This is the relevant code for insertSymbol(SymbolTable* st, SymbolEntry entry). pos is always the last element in the array when inserting (otherwise the entry isn't unique and pos is just returned).
st->entries[pos].name = (char *)calloc(strlen(entry.name)+1, sizeof(char));
st->entries[pos].type = (char *)calloc(strlen(entry.type)+1, sizeof(char));
st->entries[pos].value = (char *)calloc(strlen(entry.value)+1, sizeof(char));
strcpy(st->entries[pos].name, entry.name);
strcpy(st->entries[pos].type, entry.type);
strcpy(st->entries[pos].value, entry.value);
Later, after the lex framework has matched the value immediately following a CONSTANTs name, this code is performed (directly in the rule for <CONSTANT_VAL>{number})
table.entries[prevSym].value = (char *)calloc(yyleng+1, sizeof(char));
strcpy(table.entries[prevSym].value, yytext);
Why does this invalidate the the SymbolEntry at this position in the array, and how can I safely change the contents of value?
EDIT:
It doesn't only happen with constants. The first two SymbolEntrys are always garbage. I'm assuming that probably means they ALL are, but the others just haven't been overwritten.
Also, it seems like subsequent calls to registerID is causing the data to get corrupted. With just 9 symbols, only the first two are garbage, with 34, it's the first 7. Adding more text to parse without variables did not cause any issues.
SOLVED
Well it turns out that I just accidentally deleted a line somewhere along the way and that's what introduced the bug. I accidentally erased my call to initSymbolTable. Thanks to chux for asking me how I initialized the table. Sorry about that.
2 potential problems.
1 - Compare
// Fields set with non-malloc'ed memory
e.type = type;
e.value = "";
// Fields set with malloc'ed memory
st->entries[pos].type = (char *)calloc(strlen(entry.type)+1, sizeof(char));
st->entries[pos].value = (char *)calloc(strlen(entry.value)+1, sizeof(char));
strcpy(st->entries[pos].type, entry.type);
strcpy(st->entries[pos].value, entry.value);
Both of these set the fields to valid memory and in the second case, dynamically fill the memory. The concern is subsequent use. How does OP know to free() or realloc() the second kind and not the first. Further concern: With registerID(char* type), how do we know the value passed to type is still valid way later when that pointer is used via field type. Suggest:
e.type = strdup(type); // or the usual strlen()+1, malloc() and copy
e.value = strdup("");
2 - The type and setting of yyleng are not shown. Maybe it is not big enough as compared to strlen(e.name), etc.?
[Edit] after review, I real think e.type = type; is the problem. e.type needs its own copy of type.
Minor: Consider
// st->entries[pos].type = (char *)calloc(strlen(entry.type)+1, sizeof(char));
// strcpy(st->entries[pos].type, entry.type);
size_t Length = strlen(entry.type) + 1;
st->entries[pos].type = malloc(Length);
memcpy(st->entries[pos].type, entry.type, Length);
I have a struct like this:
typedef struct string {
unsigned long length;
unsigned *data;
} string;
Can I write something so that when I do this:
string s;
the length property is zero, instead of whatever happens to be in the memory? data works well, as it's preset to zero or a null pointer.
Example of what happens right now:
string s;
printf("length: %lu\n", s.length);
printf("pointer: %lu\n", (unsigned long) s.data);
Result:
length: 140737488347584
pointer: 0
I want to avoid having to call an initialisation function on each new string just to set length to zero.
More information
Now that I think about it, it may not be really necessary to do this in my particular case (though it would be nice) because most people would initially set the string through ctou (which imports UTF-8 from char pointer) and that function sets length to zero anyway.
You could use
string s = {0,NULL};
To combine the two previous answers (sort of) I'd define something like
#define STRING_INITIALIZER {0, NULL}
.
.
string s = STRING_INITIALIZER;
BTW, your struct declaration itself looks weird for a string. Either this is not a string as we usually understand it in C but merely a dynamic array of unsigned, or it is really a string and then this should be char*.
The accepted answer answered the question that you asked, but didn't address whether you ought.
Your string is a class and has class semantics. The initializer may be fine for kernel code where every last instruction counts, but in application code your static initializers are ugly and error prone.
It is possible to write classes in C, the stdio FILE type is a fabulous example, and here is the same idea applied to your string class:
typedef struct {
int length;
char *data;
} String;
String *sopen() {
String *s = malloc(sizeof(String));
if(s) {
s->length = 0;
s->data = NULL;
}
return s;
}
int sclose(String *s) {
free(s->data);
free(s);
return 0;
}
int main()
{
String *s = sopen();
return sclose(s);
}
Where I've followed the FILE* function name style for metaphoric reasons. Yep, there's more code. Yep, you have to explicitly deallocate the structure; but note that even though you were counting on auto class initialization in your code sample, if data was ever allocated, you couldn't count on leaving scope to automatically deallocate the storage for you.
This approach also has the merit of abstracting the type of data from the users of the class. As there seems to be some confusion about what type you really want to use, this flexibility may come in handy.
#define DEFINE_STRING(s) string s = {0, NULL}
{
DEFINE_STRING(s);
}
You can use a macro to "do this automatically"
How should I write my code to example a specific array index of an array that happens to be a member of a structure? The following code is giving me problems.
// main.c
void clean_buffers(void); // prototype
struct DEV_STATUS {
unsigned char ADDR;
unsigned char DEV_HAS_DATA;
unsigned char ETH_HAS_DATA;
unsigned char DATA[20];
};
struct DEV_STATUS g_cmdQueue[60] = {0};
void main(void) {
clean_buffers();
while (1) {
;// MCU tasks
}
}
void clean_buffers(void) {
unsigned char theCount = 0;
byte queIdx;
for (queIdx = 0; queIdx < 59; queIdx++) {
struct DEV_STATUS *p_struct;
unsigned char *p_data;
p_struct = &g_cmdQueue[queIdx];
p_data = &p_struct->DATA;
p_struct->ADDR = 0;
p_struct->DEV_HAS_DATA = 0;
p_struct->ETH_HAS_DATA = 0;
theCount = 0;
while(*(p_data+theCount) != 0) {
*(p_data+(theCount++)) = 0;
}
}
} // EOF main.c
I get a compiler error "struct/union member expected" on the following line:
p_data = &p_struct->DATA;
How should I write a pointer if I was to access, for example, the specific value of structure member DATA[3]? I'm confused, I thought that as p_data = &p_struct->DATA; is defined, I should be able to get it by using *(pdata+3) but I guess I'm missing something.
Are you sure you are compiling the same code you posted here?
If your compiler complains at this line
p_data = &p_struct->DATA;
with a "struct/union member expected" message, your compiler is probably broken.
Note, that &p_struct->DATA is a perfectly valid expression in C. There's absolutely no problems with this expression by itself.
The problem here is just that this is not what you need in your case. &p_struct->DATA returns a pointer to the entire array 'DATA', i.e a pointer of type unsigned char (*)[20]. You are trying to assign this value to a pointer of type unsigned char *. This is illegal in C, since the types are completely different, but traditionally C compilers responded to it with a mere "type mismatch" warning and performed an implicit conversion (which, BTW, means that your original code, albeit "dirty", should still work as intended).
Even if some compiler decides to flag this mismatch as an error (which is fine), it still should not complain about any problems of "struct/union member expected" kind. There's no such problems here.
P.S. As other already said, what you really need is p_data = &p_struct->DATA[0], but that still does not explain your compiler's strange behavior. Could it be that 'DATA' is a macro defined somewhere before the 'clean_buffers' definition?
Added 10/19/2009: Nate, in your code you access your array using an index theCount. Since you are using the index access anyway, there's really no reason to even create the pointer you are trying to create. The code will work perfectly fine without any additional pointer, just acess the DATA field directly
theCount = 0;
while (p_struct->DATA[theCount] != 0) {
p_struct->DATA[theCount++] = 0;
(I'd probably use a for cycle here).
If you really insist on creating this pointer and still using the index access, the code should look something like the following (the others already suggested that more than once)
p_data = p_struct->DATA; /* or &p_struct->DATA[0] */
...
theCount = 0;
while (p_data[theCount] != 0) {
p_data[theCount++] = 0;
Moreover, you can opt for a more "exotic" variant :)
unsigned char (*p_data)[20]; /* <- note: declared differently */
...
p_data = &p_struct->DATA; /* <- note: your original version */
...
theCount = 0;
while ((*p_data)[theCount] != 0) {
(*p_data)[theCount++] = 0;
However, returning to a unsigned char *p_data version, since you create that pointer, it might make more sense to use a "sliding pointer" technique instead of using index access
unsigned char *p_data;
...
p_data = p_struct->DATA; /* or &p_struct->DATA[0] */
...
while (*p_data != 0) {
*p_data++ = 0;
As always, it is all a matter of personal preference. Of course, nothing of this will work until you get rid of that interference from the macro.
Lose the & in
p_data = &p_struct->DATA;
p_struct is already a pointer. Afterwards, use p_data[] to access your array.
What you should write is one of two things:
p_data = p_struct->DATA; // DATA is the address of the first element.
OR
p_data = &p_struct->DATA[0]; // taking the address of the first element.
Simply remove the & at the beginning, like this:
p_data = p_struct->DATA;
That is special sintax for arrays (remember they are passed always as reference) and it is equivalent to:
p_data = &p_struct->DATA[0];
And yes, now you can use *(pdata+3)
Hope it helps.
Oops! Thank you AndreyT
struct DEV_STATUS *p_struct;
unsigned char *p_data;
p_struct = &g_cmdQueue[queIdx];
p_data = &p_struct->DATA;
p_struct is a pointer to struct DEV_STATUS.
&p_struct is the address of a pointer to struct DEV_STATUS (or a pointer to a pointer to a struct DEV_STATUS).
You probably want to change that line to
p_data = p_struct->DATA;
Oh ... your clean_buffers() function does not "clean" the element g_cmdQueue[59].
And, because it is a global object, the array g_cmdQueue is initialized to all zeros even before the first statement of main() exceutes.