Complicated declarations (of C) [duplicate] - c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to understand complicated function declarations?
Spiral rule and ‘declaration follows usage’ for parsing C expressions
There is a section with the same title, "Complicated Declarations", in K&R's The C Programming Language book as you might have already read. I am just reading the book and trying to better myself in C language. After reading the section mentioned, I think I couldn't get the logic behind the syntax of C declaration statements. 1, 2, 3 and 4 are from that section 5 and 6 are from other pages.
int (*daytab)[13]
daytab: pointer to array[13] of int
void (*comp)()
comp: pointer to function returning void
char (*(*x())[])()
x: function returning pointer to array[] of pointer to function returning char
char (*(*x[3])())[5]
x: array[3] of pointer to function returning pointer to array[5] of
char
typedef int (*PFI)(char *, char *)
creates the type PFI, for ``pointer to function (of two char *
arguments) returning int. How does the syntax works here?
Finally, my questions are:
Can you explain your ways of thinking and reading complicated
declarations possibly by using examples above?
Are the things like
1,3,4 practically usable and needed? If so, can you write some code examples?

I saw The ``Clockwise/Spiral Rule'' on HackerNews in the past week or so. It is a good way to think about C declarations, especially function pointers.

Look at the identifier and the symbol next to it to the right:
If it's a [ the identifier is for an array.
If it is a ( the identifier is for a function
If it is a ) look to the left and you will find a *: the identifier is a pointer
If there is nothing to the right or to the left, the identifier is a "plain old" object.
Elaboration:
int (*daytab)[13]
daytab is a pointer
void (*comp)()
comp is a pointer
char (*(*x())[])()
x is a function
char (*(*x[3])())[5]
x is an array
typedef int (*PFI)(char *, char *)
PFI is a pointer

Related

What's the difference between (int *pointer) and (int* pointer) [duplicate]

Why do most C programmers name variables like this:
int *myVariable;
rather than like this:
int* myVariable;
Both are valid. It seems to me that the asterisk is a part of the type, not a part of the variable name. Can anyone explain this logic?
They are EXACTLY equivalent.
However, in
int *myVariable, myVariable2;
It seems obvious that myVariable has type int*, while myVariable2 has type int.
In
int* myVariable, myVariable2;
it may seem obvious that both are of type int*, but that is not correct as myVariable2 has type int.
Therefore, the first programming style is more intuitive.
If you look at it another way, *myVariable is of type int, which makes some sense.
Something nobody has mentioned here so far is that this asterisk is actually the "dereference operator" in C.
*a = 10;
The line above doesn't mean I want to assign 10 to a, it means I want to assign 10 to whatever memory location a points to. And I have never seen anyone writing
* a = 10;
have you? So the dereference operator is pretty much always written without a space. This is probably to distinguish it from a multiplication broken across multiple lines:
x = a * b * c * d
* e * f * g;
Here *e would be misleading, wouldn't it?
Okay, now what does the following line actually mean:
int *a;
Most people would say:
It means that a is a pointer to an int value.
This is technically correct, most people like to see/read it that way and that is the way how modern C standards would define it (note that language C itself predates all the ANSI and ISO standards). But it's not the only way to look at it. You can also read this line as follows:
The dereferenced value of a is of type int.
So in fact the asterisk in this declaration can also be seen as a dereference operator, which also explains its placement. And that a is a pointer is not really declared at all, it's implicit by the fact, that the only thing you can actually dereference is a pointer.
The C standard only defines two meanings to the * operator:
indirection operator
multiplication operator
And indirection is just a single meaning, there is no extra meaning for declaring a pointer, there is just indirection, which is what the dereference operation does, it performs an indirect access, so also within a statement like int *a; this is an indirect access (* means indirect access) and thus the second statement above is much closer to the standard than the first one is.
Because the * in that line binds more closely to the variable than to the type:
int* varA, varB; // This is misleading
As #Lundin points out below, const adds even more subtleties to think about. You can entirely sidestep this by declaring one variable per line, which is never ambiguous:
int* varA;
int varB;
The balance between clear code and concise code is hard to strike — a dozen redundant lines of int a; isn't good either. Still, I default to one declaration per line and worry about combining code later.
I'm going to go out on a limb here and say that there is a straight answer to this question, both for variable declarations and for parameter and return types, which is that the asterisk should go next to the name: int *myVariable;. To appreciate why, look at how you declare other types of symbol in C:
int my_function(int arg); for a function;
float my_array[3] for an array.
The general pattern, referred to as declaration follows use, is that the type of a symbol is split up into the part before the name, and the parts around the name, and these parts around the name mimic the syntax you would use to get a value of the type on the left:
int a_return_value = my_function(729);
float an_element = my_array[2];
and: int copy_of_value = *myVariable;.
C++ throws a spanner in the works with references, because the syntax at the point where you use references is identical to that of value types, so you could argue that C++ takes a different approach to C. On the other hand, C++ retains the same behaviour of C in the case of pointers, so references really stand as the odd one out in this respect.
A great guru once said "Read it the way of the compiler, you must."
http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835
Granted this was on the topic of const placement, but the same rule applies here.
The compiler reads it as:
int (*a);
not as:
(int*) a;
If you get into the habit of placing the star next to the variable, it will make your declarations easier to read. It also avoids eyesores such as:
int* a[10];
-- Edit --
To explain exactly what I mean when I say it's parsed as int (*a), that means that * binds more tightly to a than it does to int, in very much the manner that in the expression 4 + 3 * 7 3 binds more tightly to 7 than it does to 4 due to the higher precedence of *.
With apologies for the ascii art, a synopsis of the A.S.T. for parsing int *a looks roughly like this:
Declaration
/ \
/ \
Declaration- Init-
Secifiers Declarator-
| List
| |
| ...
"int" |
Declarator
/ \
/ ...
Pointer \
| Identifier
| |
"*" |
"a"
As is clearly shown, * binds more tightly to a since their common ancestor is Declarator, while you need to go all the way up the tree to Declaration to find a common ancestor that involves the int.
That's just a matter of preference.
When you read the code, distinguishing between variables and pointers is easier in the second case, but it may lead to confusion when you are putting both variables and pointers of a common type in a single line (which itself is often discouraged by project guidelines, because decreases readability).
I prefer to declare pointers with their corresponding sign next to type name, e.g.
int* pMyPointer;
People who prefer int* x; are trying to force their code into a fictional world where the type is on the left and the identifier (name) is on the right.
I say "fictional" because:
In C and C++, in the general case, the declared identifier is surrounded by the type information.
That may sound crazy, but you know it to be true. Here are some examples:
int main(int argc, char *argv[]) means "main is a function that takes an int and an array of pointers to char and returns an int." In other words, most of the type information is on the right. Some people think function declarations don't count because they're somehow "special." OK, let's try a variable.
void (*fn)(int) means fn is a pointer to a function that takes an int and returns nothing.
int a[10] declares 'a' as an array of 10 ints.
pixel bitmap[height][width].
Clearly, I've cherry-picked examples that have a lot of type info on the right to make my point. There are lots of declarations where most--if not all--of the type is on the left, like struct { int x; int y; } center.
This declaration syntax grew out of K&R's desire to have declarations reflect the usage. Reading simple declarations is intuitive, and reading more complex ones can be mastered by learning the right-left-right rule (sometimes call the spiral rule or just the right-left rule).
C is simple enough that many C programmers embrace this style and write simple declarations as int *p.
In C++, the syntax got a little more complex (with classes, references, templates, enum classes), and, as a reaction to that complexity, you'll see more effort into separating the type from the identifier in many declarations. In other words, you might see see more of int* p-style declarations if you check out a large swath of C++ code.
In either language, you can always have the type on the left side of variable declarations by (1) never declaring multiple variables in the same statement, and (2) making use of typedefs (or alias declarations, which, ironically, put the alias identifiers to the left of types). For example:
typedef int array_of_10_ints[10];
array_of_10_ints a;
A lot of the arguments in this topic are plain subjective and the argument about "the star binds to the variable name" is naive. Here's a few arguments that aren't just opinions:
The forgotten pointer type qualifiers
Formally, the "star" neither belongs to the type nor to the variable name, it is part of its own grammatical item named pointer. The formal C syntax (ISO 9899:2018) is:
(6.7) declaration:
declaration-specifiers init-declarator-listopt ;
Where declaration-specifiers contains the type (and storage), and the init-declarator-list contains the pointer and the variable name. Which we see if we dissect this declarator list syntax further:
(6.7.6) declarator:
pointeropt direct-declarator
...
(6.7.6) pointer:
* type-qualifier-listopt
* type-qualifier-listopt pointer
Where a declarator is the whole declaration, a direct-declarator is the identifier (variable name), and a pointer is the star followed by an optional type qualifier list belonging to the pointer itself.
What makes the various style arguments about "the star belongs to the variable" inconsistent, is that they have forgotten about these pointer type qualifiers. int* const x, int *const x or int*const x?
Consider int *const a, b;, what are the types of a and b? Not so obvious that "the star belongs to the variable" any longer. Rather, one would start to ponder where the const belongs to.
You can definitely make a sound argument that the star belongs to the pointer type qualifier, but not much beyond that.
The type qualifier list for the pointer can cause problems for those using the int *a style. Those who use pointers inside a typedef (which we shouldn't, very bad practice!) and think "the star belongs to the variable name" tend to write this very subtle bug:
/*** bad code, don't do this ***/
typedef int *bad_idea_t;
...
void func (const bad_idea_t *foo);
This compiles cleanly. Now you might think the code is made const correct. Not so! This code is accidentally a faked const correctness.
The type of foo is actually int*const* - the outer most pointer was made read-only, not the pointed at data. So inside this function we can do **foo = n; and it will change the variable value in the caller.
This is because in the expression const bad_idea_t *foo, the * does not belong to the variable name here! In pseudo code, this parameter declaration is to be read as const (bad_idea_t *) foo and not as (const bad_idea_t) *foo. The star belongs to the hidden pointer type in this case - the type is a pointer and a const-qualified pointer is written as *const.
But then the root of the problem in the above example is the practice of hiding pointers behind a typedef and not the * style.
Regarding declaration of multiple variables on a single line
Declaring multiple variables on a single line is widely recognized as bad practice1). CERT-C sums it up nicely as:
DCL04-C. Do not declare more than one variable per declaration
Just reading the English, then common sense agrees that a declaration should be one declaration.
And it doesn't matter if the variables are pointers or not. Declaring each variable on a single line makes the code clearer in almost every case.
So the argument about the programmer getting confused over int* a, b is bad. The root of the problem is the use of multiple declarators, not the placement of the *. Regardless of style, you should be writing this instead:
int* a; // or int *a
int b;
Another sound but subjective argument would be that given int* a the type of a is without question int* and so the star belongs with the type qualifier.
But basically my conclusion is that many of the arguments posted here are just subjective and naive. You can't really make a valid argument for either style - it is truly a matter of subjective personal preference.
1) CERT-C DCL04-C.
Because it makes more sense when you have declarations like:
int *a, *b;
For declaring multiple pointers in one line, I prefer int* a, * b; which more intuitively declares "a" as a pointer to an integer, and doesn't mix styles when likewise declaring "b." Like someone said, I wouldn't declare two different types in the same statement anyway.
When you initialize and assign a variable in one statement, e.g.
int *a = xyz;
you assign the value of xyz to a, not to *a. This makes
int* a = xyz;
a more consistent notation.

What is the significance of asterisks postfixing a variable type in a method header? [duplicate]

This question already has answers here:
difference between int* i and int *i
(9 answers)
Why is the asterisk before the variable name, rather than after the type?
(12 answers)
Closed 3 years ago.
I have been trying to learn C as a programming language, and have been trying to solve sample problems on site like LeetCode in C programs. When I was reading over some of the skeleton code that was provided as a function header for a problem on LeetCode that I want to solve in C, the function header had asterisks post fixing some of the types, specifically like this:
int* twoSum(int* nums, int numSize, int target, int* returnSize) {
/* Code goes here */
}
After doing a fair bit of reading, I learned that prefixing a variable with an asterisk when declaring a variable reserves the variable as a pointer, but I have not been able to find anything about what it means when the type specifier itself is post fixed with an asterisk.
The spaces there don't matter.
int* nums is identical to int *nums. So are int * nums and int*nums.
All four of these declare nums as pointer to int.
It's a matter of style preference (though I wouldn't use that last one), with no effect on the generated code.

What is int (*fp)() [duplicate]

This question already has answers here:
How do function pointers in C work?
(12 answers)
Closed 4 years ago.
I am not familiar with the syntax below for the following struct
struct fp {
int (*fp)();
}
What is int (*fp)() ? I understand that it is an integer and *fp is a pointer but I do not understand what that parentheses in (*fp)() do.
fp is a pointer to a function with empty parameters list.
I.e.
int myfunc() //define function
{
return 0;
}
struct fp //define structure
{
int (*fp)();
} mystruct;
mystruct.fp = &myfunc; //assign function pointer to structure element
int a = mystruct.fp(); //Call function through pointer
There are many ways to read C declarations, that can be very complicate in some cases. Start reading this https://parrt.cs.usfca.edu/doc/how-to-read-C-declarations.html.
You can google for "how to read c declarations" for more in depth explanation and further tips.
As Swordfish pointed out, the use of empty parameter list imply other sensible points about function definitions, that could be worth to deep. Please refer to Swordfish's comment below for the main points relative to functions definition.
I will refer only to the §6.11.6 Function declarators (of §6.11 Future language directions):
The use of function declarators with empty parentheses (not
prototype-format parameter type declarators) is an obsolescent
feature.
It is a function pointer. They are powerful and quite hard to get your head around if you are a beginner.
It is a strcture that wraps a function-pointer.
Have a look here: How do function pointers in C work?
It is a declaration of the variable fp which is a pointer to a function that returns an int and takes an unspecified list of arguments.

Pointer C - declaration [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
In C, what is the correct syntax for declaring pointers?
I am fighting with the c language. Pointers are new to me, and I think I am getting closer and closer to understanding them.
I have though one questions.
What is the difference between:
int k = 4;
int* pcp = &k;
and
int k = 4;
int *pcp = &k;
I cant seem to find any difference between these declarations of the pointer, is it just syntactical sugar - or is there any difference?
Thanks
There is no difference in those declarations, but there is a difference between the following two declarations:
int* p, p2; // declares a pointer to int and a regular int
and:
int *p, *p2; // declares two pointers to int
that might be hidden by your example.
So I prefer the second declaration.
you can try it out yourself. just type both, printf it and see what happens :P
if i'm not terribly mistaken though, it's the same ;)

array of N pointers to functions returning pointers to functions

This was asked to me in an interview!
i really got confused
How do I declare an array of N
pointers to functions returning
pointers to functions returning
pointers to characters
could anybody please help?
Typedefs are for wusses. Here's a straightforward, mechanical method for figuring out hairy declarations:
a -- a
a[N] -- is an N-element array
*a[N] -- of pointers
(*a[N])() -- to functions
*(*a[N])() -- returning pointers
(*(*a[N])())() -- to functions
*(*(*a[N])())() -- returning pointers
char *(*(*a[N])())() -- to char.
So, the answer is in the neighborhood of char *(*(*a[N])())();. I say "in the neighborhood" since it's never specified what arguments the functions take.
It's an obnoxious interview question (types this ugly are truly rare IME), but it does give the interviewer an idea of how well you understand declarators. Either that or they were bored and just wanted to see if they could make your brain sieze.
EDIT
Most everyone else recommends using typedefs. The only time I recommend using a typedef is if the type is intended to be truly opaque (i.e., not manipulated directly by the programmer, but passed to an API, sort of like the FILE type). Otherwise, if the programmer is meant to manipulate objects of that type directly, then IME it's better to have all that information available in the declaration, ugly as it may be. For example, something like
NameFuncPickerPointer a[N];
gives me no information on how to actually use a[i]. I don't know that a[i] is callable, or what it returns, or what arguments it should take (if any), or much of anything else. I have to go looking for the typedef
typedef char *NameFunc();
typedef NameFunc *NameFuncPicker();
typedef NameFuncPicker *NameFuncPickerPointer;
and from that puzzle out how to write the expression that actually calls one of the functions. Whereas using the "naked", non-typedef'd declaration, I know immediately that the structure of the call is
char *theName = (*(*a[i])())();
typedef char* (* tCharRetFunc)();
typedef tCharRetFunc (* tFuncRetCharFunc)();
tFuncRetCharFunc arr[N];
Divide big problem into smaller parts:
/* char_func_ptr is pointer to function returning pointer to char */
typedef char* (*char_func_ptr)();
/* func_func_ptr is a pointer to function returning above type */
typedef char_func_ptr (*func_func_ptr)();
/* the_array is array of desired function pointers */
func_func_ptr the_array[42];
array of N pointers to functions returning pointers to functions returns a char:
int (*(*arr_fp[n])(void))(void)
Is this what you are looking for:
typedef char* charptr;
typedef charptr (*innerfun)();
typedef innerfun (*outerfun)();
const size_t N = 10;
outerfun my_outerfun_array[N];
I hope I got it correct, it seems a strange question to me especially in an interview :(
Using typedefs as Christopher tells you is really th only humane way of declaring such a thing. Without tyedefs , it'll become:
char *(*(*arr[10])(void ))(void );
(yes I had to cheat and ran
cdecl> declare arr as array 10 of pointer to function(void) returning pointer to function(void) returning pointer to char )

Resources