compiler error: "Expected ;" error in C struct - c

I'm trying to add a struct to my program using this syntax:
struct foo {
char bar[] = "baz";
char qux[] = "abc";
/* and so on */
};
For some reason, I get an error on each variable declaration within the struct saying that I have to add semicolons, and seems to fall into a kind of loop with this. The suggested syntax would be something like
struct foo {
char bar[]; =; ;;;;;;/* infinite semicolons */"baz";
}
This is the first time I've had this kind of error; am I really doing something wrong, or is this just an issue with the compiler itself?

This has nothing to do with Xcode. At all.
You're getting a compiler error because you can't initialize structs like this.
The struct type definition is about types only. Assigning values to members at this point makes no sense. Maybe you meant
struct foo {
char *bar;
char *baz;
};
struct foo x = { "quirk", "foobar" };
instead?

You are doing something wrong. You cannot assign values to the members of the struct… you're in the middle of defining the data type, not an instance of it.
This will give you your struct definition and then directly declare a variable (with initialization) of its type:
struct foo {
char *bar;
char *qux;
} variable_name = {
"baz", "abc"
};

Related

typedef struct but keep new type namespaced under keyword 'struct'

How can I typedef a struct but still keep the new type namespaced under the keyword 'struct'?
example:
struct foo {
int x;
};
typedef struct foo struct bar;
int main(void) {
struct bar bar;
bar.x = 10;
return 0;
}
but this doesn't work obviously.
Here are the errors if anyone is curious:
main.c:5:20: error: two or more data types in declaration specifiers
typedef struct foo struct bar;
^
main.c:5:27: warning: useless storage class specifier in empty declaration
typedef struct foo struct bar;
^
main.c: In function 'main':
main.c:9:13: error: storage size of 'bar' isn't known
struct bar bar;
How can I typedef a struct but still keep the new type namespaced under the keyword 'struct'?
So, it seems that you want to define a structure alias for another structure type.
This is not possible with typedef as it creates a single word alias. The new alias can't be consisted of multiple white space separated words.
But you can use a single name like struct_bar with struct implemented inside of the name to show that bar is a structure.
#include <stdio.h>
struct foo {
int x;
};
typedef struct foo struct_bar;
int main(void) {
struct_bar bar;
bar.x = 10;
return 0;
}
How can I typedef a struct but still keep the new type namespaced under the keyword 'struct'?.
You cannot. A namespace is a declarative region that provides a scope to the identifiers (names of the types, function, variables etc) inside it. The concept of Namespace as it is defined within C++, is not inherent in C.
So, if you are okay with minor changes in your requirements, instead of doing something unnatural, use a simple typedef:
Instead of this:
struct foo {
int x;
};
do this:
typedef struct {
int x;
}foo;
Then this will work:
typedef foo bar;
int main(void )
{
bar b;
b.x = 10;
return 0;
}
Note: Although namespaces are not inherent in in C, as they are in C++, there are some interpretations eg: as discussed here, that argue the point.
C doesn't have any type of support for namespaces (at least not in the sense that C++ does).
When you create a typedef, the new type name is a single identifier, not multiple words. So struct bar can't be an alias for another type. You would have to call it bar or some other one-word name.
You can't. This isn't how it works.
You cannot "create" a type whose name is more than one word, nor can you refer to a type alias using the keyword struct.
The purpose of writing struct, in this context, is to refer to a struct type by a name that wasn't introduced as an alias. The keyword is there to say that that's what you want to do. But it's not part of the name; it cannot be part of the name.
Fortunately, there's no reason to need or even want this.
I found a solution that works for cygwin:
struct foo {
int x;
};
struct bar {
struct foo;
};

Trying to use typedef within a struct: why do I get an error, and is it a good idea in the first place?

I get this error when trying to declare an alias via 'typedef' from within a struct in my header file:
error: expected specifier-qualifier-list before ‘typedef’
My initial intent was to test that the scope of the typedef was contained within the struct. This is so that I prevent the unwanted use of this alias if this header were to be included in another source file. If I move the offending line(the one starting with 'typedef') outside the struct and before it, the code compiles.
However, I don't understand why I couldn't call typedef from within the struct, and why I get the aforementioned error instead.
Furthermore, I'm unsure whether this practice is actually necessary. What are the merits of restricting the alias, if any?
#ifndef STUDENT_H
#define STUDENT_H
typedef struct{
typedef char* string;
string name;
int id;
} Student;
#endif
I expect the code to compile, but instead I get the error message:
error: expected specifier-qualifier-list before ‘typedef’
You cannot have a typedef inside a typedef.
You can have:
typedef char* string;
and then use it:
typedef struct{
string name;
int id;
} Student;
Be careful that string is just a pointer, it must "point" to allocated memory before you can use it (especially before writing to it).
However, I don't understand why I couldn't call typedef from within the struct
That is how C worked since ever, and everybody was just fine with it. You will have to learn to accept this "limitation".
Opposite to C++ C is very restricted language. Within a structure data members may not have storage-class specifiers (typedef, extern, static, _Thread_local, auto, register) and typedef as you can see is considered in C as a storage-class specifier.
You can place the typedef before the structure definition like
typedef char* string;
typedef struct{
string name;
int id;
} Student;
and use the typedef throughout your program.
But take into account that if you will write for example
const string s = "Hello Aiman";
it does not mean the same as
const char * s = "Hello Aiman";
It does mean
char * const s = "Hello Aiman";
That is it is not the string literal pointed to by the pointer that is constant. It is the pointer itself that is constant.
Consider the following demonstrative program
#include <stdio.h>
typedef char * string;
void f( const string s )
{
*s = 'B';
*( s + 1 ) = 'y';
*( s + 2 ) = 'e';
*( s + 3 ) = '\0';
// The statement below issues compilation error
// "assignment of read-only parameter 's'"
// s = "Hello";
}
int main( void )
{
char s[] = "Hello";
puts( s );
f( s );
puts( s );
}
Its output is
Hello
Bye
That is within the function the string pointed to by the pointer s can be changed but the pointer itself can not be changed.
So maybe it is better not to introduce such a typedef because using such a typedef in declarations like
const string s
will confuse readers of the code.

Initialize pointer to a struct with a compound literal

I'm new to C and I'm trying to understand the syntax for compound literals. My question is similar to Initializing a pointer to compound literals in C but I don't think that answers it. If have a struct and a type defined as a pointer to the struct like this:
typedef struct thing *thing_t;
struct thing
{
int id;
char *name;
};
Then I can create a thing_t like this:
thing_t instance = & (struct thing) {
.id = 1,
.name = "A"
};
I was wondering if there is a way to initialize a thing_t without explicitly referring to struct thing, e.g. I tried this to see if it was valid syntax:
thing_t instance = (* thing_t) {
.id = 1,
.name = "A"
};
but the compiler errors. The compiler must "know" that the thing_t type holds a pointer to a thing, but is there syntax that allows to use the two interchangably in this context?
(I don't have a particular use case for this, I'm just trying to understand how the type and the struct are related).
I was wondering if there is a way to initialize a thing_t without
explicitly referring to struct thing, e.g. I tried this to see if it
was valid syntax:
thing_t instance = (* thing_t) {
.id = 1,
.name = "A"
};
but the compiler errors. The compiler must "know" that the thing_t
type holds a pointer to a thing,
Yes, it does, though it is poor form to define a type alias that hides pointer nature, as you have done, and it is especially poor form to do so with a name that does not somehow provide a clue about that.
but is there syntax that allows to
use the two interchangably in this context?
The syntax for a compound literal includes the parenthesized type specifier. That's not a cast, it's part of the literal itself. You cannot do without it. If you want to avoid saying struct, though, then you can kill two birds with one stone by changing your type alias so that it describes the struct type itself, not a pointer to one:
typedef struct thing thing_t;
struct thing {
int id;
char *name;
};
thing_t *instance = & (thing_t) {
.id = 1,
.name = "A"
};
Not only does it work, but it's a heck of a lot clearer than your proposal. For example, the use of the & operator matches up with the clear declaration of variable instance as a pointer.

Why is forward declaration of structure not working in my code? When can it be used in C?

Isn't forward declaration, whether for structures or functions, supposed to do what forward declaration is expected to do, ie, to let us use the structure or function before they are defined? Why is the forward declaration of a structure not working in my code? And the main thing that just misses me, is forward declaration of structures of any use in C at all? When is it used? Can you please give me a small C program example to illustrate this?
My program gives the error error: storage size of 'x' isn't known|.
#include<stdio.h>
struct test;
int main(void)
{
struct test x;
printf("%zu",sizeof(x)); //Gives Error
//printf("%zu",sizeof(struct test));//This fails too
}
struct test
{
int a;
char b;
};
New Edit I tried to do what Carl Noum said,but even this is not working:
#include<stdio.h>
struct test;
void foo(struct test*);
int main(void)
{
struct test x={53,'x'},*ptr=&x;
foo(ptr);
}
void foo(struct test* p)
{
printf("%d,%c",p->a,p->b);
}
struct test
{
int a;
char b;
};
The compiler has to know the struct's layout when it compiles the main function.
A forward declaration is useful if you only have a pointer but not the actual type.
For example if you have a struct that contains a pointer to another struct
struct foo {
struct bar *b;
...
};
It is also essential if the bar also contain foo like
struct bar;
struct foo {
struct bar *b;
};
struct bar {
struct foo f;
};
In this case you have to have bar pre-declared.
A forward declaration usually means that you don't have to include .h file inside other .h file. This can speed up compilation significantly if the .h file is big.
Functions yes, structures no. struct test is an incomplete type where you use it.
A common use case for incomplete types is to declare an opaque type. In a header file, you declare:
struct test;
And then some API that uses struct test only via pointers:
int func1(struct test *);
struct test *func2(void);
In the accompanying implementation, you include the full declaration so that your functions know what to do with the structure:
struct test
{
int a;
char b;
};
void func1(struct test *t)
{
return t->a;
}
Edit:
Your new code doesn't do anything differently - you're still trying to operate on an incomplete type, and you still can't do that. In particular, this declaration:
struct test x = {53,'x'};
Can't work if struct test is an incomplete type. You can (generally) only use pointers to an incomplete type. In this case, that might mean creating a function that allocates and returns a pointer to a new structure, rather than trying to declare and initialize one on the stack.
Struct type declared by a forward declaration (i.e. an incomplete type) can be used only in a limited number of ways. Applying sizeof to such a truct type is not one of them. On top of that, you can't use incomplete types in object definitions and you cannot access data fields of incomplete struct types.
In other words, sizeof requires a complete type. Your forward-declared struct type is not a complete type. Operator -> also requres a complete type of the left-hand side. Object definition (like struct test x) also requires a complete type.

C Struct initialization : strange way

While reading a code I came across, the following definition and initialization of a struct:
// header file
struct foo{
char* name;
int value;
};
//Implementation file
struct foo fooElmnt __foo;
// some code using fooElmnt
struct foo fooElmnt __foo = {
.name = "NAME";
.value = some_value;
}
What does this mean in C and how is it different from usual declarations?
It's called designated initialization,
In a structure initializer, specify
the name of a field to initialize with
.fieldname = before the element
value. For example, given the
following structure,
struct point { int x, y; };
the following initialization
struct point p = { .y = yvalue, .x = xvalue };
is equivalent to
struct point p = { xvalue, yvalue };
If you read on, it explains that .fieldname is called a designator.
UPDATE: I'm no C99 expert, but I couldn't compile the code. Here's the changes I had to make:
// header file
struct foo{
char* name;
int value;
};
//Implementation file
//struct foo fooElmnt __foo;
// some code using fooElmnt
struct foo fooElmnt = {
.name = "NAME",
.value = 123
};
Were you able to compile it? I used TCC.
Those are designated initializers, introduced in c99. You can read more here
Without them, you'd use
struct foo fooElmnt __foo = {
"NAME",
some_value
};
While in this case it doesn't matter much - other than the c99 way is more verbose, and its easier to read which element is initialized to what.
It does help if your struct has a lot of members and you only need to initialize a few of them to something other than zero.
This is a designated initialization. This also initializing the fields by their name, which is more readable than anomynous initialization when the structures are getting large. This has been introduced by the C99 standard.

Resources