Syntax of struct, union and enum in C [closed] - c

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 9 years ago.
Improve this question
Sometimes I just get so confused about the syntax in C. In struct, everything is separated by a semicolon and there is one extra semicolon after the last member, while in enum, everything is separated by a comma and there is no extra comma at the end. I always forget the last semicolon in struct since it doesn't seem to make sense to me. Is there any good reason for designing it that way? I hope someone can point out why it is good so that I can get used to it, right now it makes the syntax really hard to memorize.

Perhaps the simplest way to memorize this is that structs and unions are basically nested scopes. They contain declarations, just lie functions or your "root" document (in global scope).
So, you declare struct members:
struct {
int member_a;
int member_b;
} ;
Kind of like how you declare globals or function members:
/* START OF FILE */
int global_a;
int global_b;
/* END OF FILE */
Enums are lists -- kind of like array declarations, or multiple variables, etc...:
int arr[] = {1, 2, 3}; //* see note below
enum Foo { FOO, BAR, BAZ };
int foo, bar, baz;
// multiple "sub-statements" in one statement
// note that this is generally considered bad practice.
foo++, bar++, baz = bar;
Or you could simply remember it this way: Semicolons are statement terminators (they end statements), while commas are separators (they come between elements).
(*note: arrays are an exception in that they optionally allow for a trailing comma. As to why they allow for that in arrays while they don't allow it for enums is beyond me)

In C:
A comma is a seperator. Between values. Example: enum.
A semicolon is a terminator. of Statements and declerations.

Related

Why is the asterisk used before the each variable name instead of after the type? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 months ago.
Improve this question
This is not a duplicate of this question
I understand why it is better to declare variables like this:
int *var;
instead of
int* var
I understand that this avoids the ambiguous case of
int* var1, var2 where it would seem that var1 and var2 are both pointers to integers, but var2 is actually just a regular integer.
My question is why int* var1, var2 doesn't declare both variables as pointers to integers. Intuitively, I would think that int* would act like any other data type, where you would just have to use int* var1, var2 to declare both variables of type int*. In other words, why is C designed so that each variable needs an asterisk before it?
Intuitively, I would think that int* would act like any other data type
If you want to become comfortable with C, you may need to adjust your intuition! Types are at least a little bit complicated; in fact the type system is a lot like a little programming language of its own! int is a type, but "pointer" is a meta-type. You can have pointers to anything, even pointers to pointers.
In other words, why is C designed so that each [pointer] variable needs an asterisk before it?
Because, as explained in several of the answers to that other question, the scheme is that a declaration contains a "base type" and then some "declarators". In the case of arrays, pointers, and functions, the "declarator" is a little sample of whatever thing is going to have the base type. If I say
int i;
the declarator is just i, so I'm saying that i is going to be an int. No mystery there. But if I say
int a[10];
I'm saying that one element of the array I'm declaring — that is, when I later use the array by saying something like a[i] — is going to be an int. If I say
int f();
I'm saying that calling the function is going to return an int.
Finally, if I say
int *ip;
I'm saying that when I take the contents of this pointer, using the expression *ip, then what *ip is going to be is an int.
And of course I can string these together on the same line:
int i, a[10], f(), *ip;
Now, perhaps I'm just rehashing the answers at the other question, and not explaining why things were set up this way. The reason is that it makes it possible to declare arbitrarily-complicated derived types. We can have arrays, and pointers, and functions, and arrays of arrays, and pointers to arrays, and functions returning pointers, and pointers to functions, and arrays of pointers to functions, and functions returning pointers to functions, and types even more numerous and complicated than those, and they can all be declared (in a general and open-ended way) using the same sort of concise, punctuation-rich, unwordy syntax that C is famous for
I don't think it would have been possible to design a type system that could have expressed the concept of "array of pointers to functions" on the left, leaving you to just put the variable name on the right. Or, if you could design such a system, it would have been complicated and confusing and cumbersome to use, even more complicated and confusing than C's present scheme seems to you, with its odd combination of type names on the left, and declarators — with their mixture of names, asterisks, and other punctuation — on the right.
See also Question 1.21 in the C FAQ list.
Or, perhaps I lied. I just said, "I don't think it would have been possible to design a type system that could have expressed [complicated things] on the left, leaving you to just put the variable name on the right." But, in fact, C's typedef facility lets you do precisely that, if you want to build up a complex type in stages.
For example, if you say
typedef int *pointer_to_int;
you have arranged that the identifier pointer_to_int is not an actual variable of type int *, but rather, a synonym for the type int *. Having done that, you can declare several integer pointers at once, without having to re-type those pesky asterisks:
pointer_to_int p1, p2, p3; /* just like int *p1, *p2, *p3; */
And it works for more complicated types, too. I can say
typedef int *(*pointer_to_function_returning_pointer_to_int)();
and then do
pointer_to_function_returning_pointer_to_int x1, x2, x3;
at which point x1, x2, and x3 are all pointers to functions returning pointers to int, just as if I'd said
int *(*x1)(), *(*x2)(), *(*x3)();
In fact, the CS50 course introduces a "handy" typedef
typedef char *string;
which makes the identifier string be an alias for the type "pointer to char", which allegedly makes it easier for beginners to declare lots of strings. Unfortunately, char * isn't really C's One True String type, so the string typedef probably causes as much confusion as it attempts to resolve. (Part of the problem is that pointers do not necessarily make good "opaque" types. If you're dealing with a pointer, you often need to know that you're dealing with a pointer, so hiding it behind a typedef doesn't help.)

Practical uses for compound literal expressions? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
What are the practical applications of compound literals? I am not quite sure how an address of an unnamed region of storage could be useful.
int *pointer = (int[]){2, 4};
I found them mentioned here: https://en.cppreference.com/w/c/language/compound_literal
Here are some great ones:
Working around interfaces that take a pointer to input rather than a value (possibly to return an updated value you don't have any reason to care about):
y = accept(x, &sa, &(socklen_t){sizeof sa});
Implementing functions with named and default-zero/null arguments:
#define foo(...) foo_func(&(struct foo_args){__VA_LIST__})
foo(.a=42, .b="hello" /* .c = NULL implicitly */);
Implementing custom formats for printf (automatically getting per-macro-instantiation temp buffer):
#define fmt_mytype(x) fmt_mytype_func((char[MAX_NEEDED]){""}, x)
printf("...%s...", ..., fmt_mytype(foo), ...);
Compound literals can be used for arrays, but they are just as useful to initialize structs, allowing you to put a complicated initializations in one line, making the code easier to read, and less tedious to write.
Like so:
typedef struct{
int a,b,c;
char *d;
}type;
int main(){
type t=(type){.a=0,.b=1,.c=2,.d="Hello world"};
...
Without a compound literal that would have been at least four lines of code.
They can also simplify transformation functions:
typedef struct{
int a;
int b;
}twoInts;
twoInts swap(twoInts in){
return (twoInts){.a=in.b,.b=in.a};
}
They can be useful when you don't have control over the left part. If possible, you would probably use int pointer[] = {2, 4};. But what if the left part is defined by e.g. an external API, and you want to assign to it? The compound literal would be an option.

C - argument is of type struct <anonymous> [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I get the error for the two arguments of my function:
//incompatible type for argument of swapStruct
//expected Men100mParticipant but argument is of type struct <anonymous>
My code is like this:
int main(){
...
swapStruct(phaseToBeSorted->phase_result[j-1], phaseToBeSorted->phase_result[j]); //error
...
}
phaseToBeSorted is of type Men100mPhaseDetails that is defined as:
typedef struct Men100mPhaseDetails{
char* nameCurrentPhase;
int current_phase;
Men100mParticipant phase_result;
} Men100mPhaseDetails * Men100mPhaseDetails;
While pase_result is supposed to be an array of Men100mparticipant. The typedef is given as is and I can't change it.
This is the declaration of Men100mparticipant:
typedef struct {
char nameOfParticipant[MAX_LEN_NAME];
double* scores[4];
} Men100mparticipant, *Men100mParticipant;
and this the declaration of the function swapStruct:
static void swapStruct(Men100mParticipant a, Men100mParticipant b);
I don't understand what is the problem and I'll be glad to get some help in solving the problem.
You need to use:
swapStruct(&phaseToBeSorted->phase_result[j-1], &phaseToBeSorted->phase_result[j]);
The compiler is doing its best, but the structure type names are confusing.
It actually work but why is a '&' needed?
The type of phaseRoBeSorted->phase_result[j-1] is Men100mparticipant with two lower-case p's — so it is a structure. The swapStruct function takes two arguments of type Men100mParticipant (with an upper-case P), so it takes two pointers. The & passes the address of the array elements, of course, so that the function gets pointers, not copies of the structure.
This typedef (which appears to be given by the course instructors and can't be changed) is gruesome:
typedef struct { … } Men100mparticipant, *Men100mParticipant;
The case of the first letter P determines whether the type is a pointer or not, which is a disaster in the making. In general, Is it a good idea to typedef pointers? says "No". When there is a need (I'm not convinced this is an example of when it might be needed), make the difference clearer than the use of upper-case vs lower-case part way through the name.

Why is there no increment operator for enums in C? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Why is there no increment operator for enums in C? Even if the corresponding integer values are user-defined it does make perfectly sense to me to iterate with ++ to the next member.
To make it more clear
typedef enum myenum t_myEnum;
enum myenum {
eMember1,
eMember2
}
t_myEnum bla = eMember1;
Now I ask what is the reason against bla++ yields eMember2.
User defined assignments to integers values like
enum myenum {
eMember1 = 0,
eMember2 = 10
}
shouldn't be an obstacle in my opinion.
I am sure it is a drawback of C and C++.
Initially enumerations are considered as sets of integer constants as an alternative for the directive #define. Thus an enumeration in C is a common name for a set of such constants. They were made as simple as possible.:)
There was made a step ahead in C++ and enumerators started to have types of their enumerations. Also you can overload operators ++ for enumerations though I agree with you that it would be better that these operators would be built-in.
For example enumerations could be implemented a similar way as std::initializer_list in C++.
So in my opinion there are only historical reasons for the absence of these operators.
An other drawback is impossibility to get the number of enumerators defined in an enumeration.
I would guess there is no such operator since the work-around is so trivial:
typedef enum
{
eMember1 = 0,
eMember2 = 10
} myenum;
const myenum TABLE [] =
{
eMember1,
eMember2
};
for(size_t i=0; i<sizeof(TABLE)/sizeof(*TABLE); i++)
{
do_something_with(TABLE[i]);
}
Similarly, you could use a const myenum* as iterator.
Another reason why such an operator doesn't exist might be that it doesn't make much sense. Lets pretend there was one, what do you think this code would do?
myenum e = eMember2;
e++;
And what would code like eMember1+1 mean? Value 1 or value 10? Again, there's no consistent logic to it.
Nothing in the C Standard prevent incrementing variables of enum types.
In your example, the typedef is incorrect because you have a forward reference to an enum type, but the following code demonstrates what I think your question is about:
#include <stdio.h>
typedef enum myenum {
eMember1,
eMember2,
} t_myEnum;
int main(void) {
t_myEnum bla = eMember1;
printf("bla=%d\n", bla);
printf("bla++=%d\n", bla++);
printf("bla=%d\n", bla);
return 0;
}
Output:
bla=0
bla++=0
bla=1
Of course the value of bla is just incremented by 1, it may correspond to another enumeration value or not, depending on the actual values of the enumeration values in the enum type.
There is no way to enumerate the defined values of a given enum type.

Are there specific rules for defining a function in C? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am writing a script that can process .c and .h files. Using regular expressions I am finding all functions within a given file. During my experiences with C I always defined functions in the following manner:
void foo(int a){
//random code
}
Is it possible to declare a function in the following manner:
void
foo(int a){
//random code
}
I always assumed that the function type, name, and parameters needed to be in the same line, but I've been told otherwise so I'm not exactly sure.
Firstly, what kind of whitespace - space, newline, tab etc. - you use in C source code does not matter, as long as there's whitespace where whitespace is required. Also, it does not matter how much whitespace you use.
Secondly, taking into account C preprocessor capabilities, one can write function declarations (and the rest of the code) as
vo\
id f\
o\
o(i\
n\
t\
\
a)
(Obviously, there are many more different ways in which preprocessor can obfuscate a function definition. For your particular task, it would be a better idea to work on already preprocessed source code.)
Thirdly, C still supports K&R-style function definitions that look as follows
void foo(a)
int a;
{
...
}
C is a free-form language; white space is not significant, in general, except to separate tokens. (There are caveats to that assertion, notably in preprocessor directives, and inside string literals and character literals, but in general that is accurate.) Thus, the following is a ghastly but legitimate C function definition:
/* Comment before the type */ SomeUserDefinedTypeName
/??/
* comments, with trigraphs to boot
*??/
/
FunctionName
(
SomeType param1,
AnotherType
(
*
param2
)
[
]
)
/\
/ one line comment
// another line comment \
yes, this is part \
of that one-line comment too
{
...
}
Of course, anyone who produces a function like that deserves to be hung, drawn and quartered — or, at least, severely castigated — but you will have to decide on how general-purpose you want your code to be. If it needs to work with any C whatsoever, you will need to handle c**p1 like this. On the other hand, you can probably get away with a lot less sophisticated parsing.
1 There's an A and an R missing, and I'm not talking about fish.
Don't try to parse C with regexes
This is a valid C function, named test, which takes a const pointer to void (named ptr) and returns a pointer to a function that takes an array of five pointer to functions which return an int and returns an unsigned int.
unsigned int (*(test)(const void *ptr)) (int (*[5])())
{
return 0;
}
(bonus points if someone can find a real-world scenario where this thing could have any use)
Although deprecated, you may also come in contact with the "old style" function notation:
// declaration
unsigned int test2();
// definition
unsigned int test2(ptr)
const void *ptr;
{
return 0;
}
Intermixed in this you can find comments (both multi-line and single-line since C99), trigraphs and even macros:
#define defun(fn) fn (
#define fstart ){
#define fend }
void defun(test3) int a, double b
fstart
printf("%d %f", a, b);
fend
http://ideone.com/JDDeMr
Even excluding the pathological macro scenario, "plain" regexes cannot even start to parse this thing because they can't match parentheses; maybe you can do something with extended regexes, but let's be honest, do you really want to cope with this stuff? Use a ready-made parser or even a compiler (libclang comes to mind) and let it do the dirty work.
I think that for a beginner user writing from zero a code that uses regex in order to parse a source code, is quite difficult but it could be quite inefficient too.
As I've stated before, I suggest to use a well written library like pyparsing that will let you translate the BNF notation of the language to the specific object of the library.
After you have defined a parsing element written using the pyparsing API, you can easily parse a simple string or a complex file using the library too.
In a first moment could be a bit difficult, but I think that you can easily use it with great results.
I suggest you to have a look to this simple C grammar defined using the pyparsing library. It's very well written and documented.
Both of these are correct (will compile) because the C compiler will ignore whitespace(s) between the return type and function-name. The format for function definition is usually:
<return type> <function name> (<parameter list>) {
<body>
}
During compilation the return type and function-name are separate tokens, the parser will ignore the whitespace(s) between them. Hope this helps.
So, whitespace includes characters like tabs, newlines, and spaces (among others).
In general, these whitespace characters are interchangeable. That is, you could replace every space with a newline (or vice-versa), and the compiler wouldn't care.
There are a few places where newlines are treated specially. Some that come to mind include the preprocessor, string literals, character literals, and single line comments.
With the two examples that you've shown, both are parsed identically. Additionally, we could also write it as:
void
foo (
int
a
) { //random code
}
or:
void
foo
(
int
a
)
{
//random code
}
or:
void foo(int a){ /* random code */ }

Resources