Noob question: why the confusing syntax (data typevariable_name(value)) for initialization

K

krishna

What is the need of this syntax for initializing values, isn't this
ambiguous to function call?
e.g., int func_name(20); this looks like function call (of course not
totally as there is no function body), but is declaration and
initialization of an integer variable 'func_name', is it step towards
completeness of OOP abstraction in the language, here one could say we
are creating and initializing an integer object, but then again it
(this way of object initialization) is not so much OOPy (so to speak),
so, maybe that's not true.

Thanks for your time

Krishna
 
N

news.aioe.org

krishna said:
What is the need of this syntax for initializing values, isn't this
ambiguous to function call?
e.g., int func_name(20); this looks like function call (of course not
totally as there is no function body), but is declaration and
initialization of an integer variable 'func_name', is it step towards
completeness of OOP abstraction in the language, here one could say we
are creating and initializing an integer object, but then again it
(this way of object initialization) is not so much OOPy (so to speak),
so, maybe that's not true.

Thanks for your time

Krishna

Looks like a function call with no function body? When did function calls start
to have a body? You mean function declaration? When did function declarations
start to take a const as an argument? I am not so sure about the reasoning
behind why the language allows such an initialization, though nothing object
oriented or ambiguous about it, it follows the same pattern as member
initialization in the constructor definitions.

class X
{ int y;
public:
X() : y(10) {}
};
 
S

Stephen Horne

What is the need of this syntax for initializing values, isn't this
ambiguous to function call?

Specifically for initialisers, well, an initialiser *is* a function
call. Specifically a constructor call. Though it may be translated to
something else, as with int which doesn't have a constructor as such.

IIRC in variable declarations, the initialiser and assignment syntax
are defined as equivalent - they always refer to a constructor if one
is available.

That said, despite the other replies, in a sense, you are right.

A common criticism of C, C++ and similar languages is the amount of
ambiguity in the grammars. This can be difficult for both people and
for compilers.

For compilers, it means that they have to keep track of "context" -
what the code actually means so far - in order to parse the next bit
correctly. So there are times when the parser needs to know that a
particular identifier actually refers to a datatype in order to parse
the next bit of code, even though that datatype may have been declared
hundreds of lines ago or even in a library somewhere.

In otherwise, parsing and semantic analysis have to run somewhat
concurrently. This is nasty hackishness.

People have essentially the same problem. You often need to know what
an identifier refers to in order to determine what construct a piece
of code is using - as opposed to the ideal in which the code gives
plenty of clues as to what is being done with what. The reader should
be trying to understand the logic, not the syntax.

For the most part, the solution is naming conventions. We all know
that 'int' is a type, but for user-defined types there are various
conventions to ensure that it's clear. An '_t' suffix, or a 'C' or 'I'
prefix for classes and interface-classes respectively, are common.

Much as I'm a big fan of C++, I have to admit that languages like
Pascal and Ada have this right. Better to avoid the ambiguity from the
start. But so long as the programmer takes responsibility for what he
is writing, it's not such a big deal.
 
F

Fred Zwarts

krishna said:
What is the need of this syntax for initializing values, isn't this
ambiguous to function call?
e.g., int func_name(20); this looks like function call (of course not
totally as there is no function body), but is declaration and
initialization of an integer variable 'func_name', is it step towards
completeness of OOP abstraction in the language, here one could say we
are creating and initializing an integer object, but then again it
(this way of object initialization) is not so much OOPy (so to speak),
so, maybe that's not true.

Note that the alternative way of initializing

int func_name = 20;

looks ambiguous, as well. It looks like an assignment.
In C++ assignment is very different from initialization.
So, both ways of writing an initializer are "ambiguous".
The ambiguity is solved by the context in both cases.
 
P

Pascal J. Bourguignon

krishna said:
What is the need of this syntax for initializing values, isn't this
ambiguous to function call?

My theory is that it's because C and C++ language designers
are lazy bums who can't type with more than two fingers.

So they had somewhere code to parse ident(expr[,expr]*),
and since they need to match a member ident to an expression,
they just copy-and-pasted the grammar rule and the parsing code.

See:
http://steve-yegge.blogspot.com/2008/09/programmings-dirtiest-little-secret.html
 
J

James Kanze

What is the need of this syntax for initializing values, isn't
this ambiguous to function call?

History. It's generally recognized as an embarassing feature.
(I believe it has been referred to as "C++'s most embarassing
parse".)
e.g., int func_name(20); this looks like function call (of
course not totally as there is no function body), but is
declaration and initialization of an integer variable
'func_name',

You mean it looks like a function declaration, not a function
call. And it gets worse. Consider:

int f( x ) ;

Whether this declares a variable initialized with x, or a
function which takes an argument of type x, depends on whether x
is declared as a variable or a type. Or:

T1 f( T2( x ) ) ;

This is a declaration of a function, always (supposing T1 and T2
are types). Even if what you meant was to explicitly convert x
to type T2, and use it to initialize a variable of type T1.
This leads to some very strange error messages at times:

std::vector< int > v( std::istream_iterator< int >( source ),
std::istream_iterator< int >() ) ;

actually declares a function named v, which takes an
std::istream_iterator<int> as its first argument, a pointer to a
function which returns an std::istream_iterator<int> as its
second argument, and returns an std::vector<int>. Which is
perfectly legal, but when you try to use v later, as a vector,
you get some strange error messages about a function not being
legal in such and such a context.

If the language were being designed from scratch, with no
concerns of backwards compatiblity or history, I'm sure that the
declaration syntax would be significantly different. But it's
not, and wasn't. In the early days, and even now to some
extent, there is a requirement of C compatibility. And since
the declaration syntax in C is horribly broken, no matter what
C++ does with it will cause problems somewhere.
 
J

James Kanze

My theory is that it's because C and C++ language designers
are lazy bums who can't type with more than two fingers.

My theory is that C's designers only had teletypes. If you've
ever worked near a teletype which is outputting something, you
can understand their desire to reduce the number of characters
to a minimum.

As for the motivation of C++'s designer, it's clear: C
compatibility. (I think it was Stroustrup who categorized C's
declaration syntax as an experiment which failed.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top