[comp.lang.c] Why didn't ANSI make initialisation consistent ????

vic@grep.co.uk (Victor Gavin) (04/24/91)

I (after many, many years of C programming) found that I couldn't perform what
I considered to be a reasonable assignment command.

I traced it back to my use of
	char *fred = "bert"
being the same as
	char fred[] = {'b', 'e', 'r', 't', '\0'}


Which made me believe that I could use the following code:

	struct bert { int a, b; }
	struct fred { struct bert *abc; } blip = { {1,1} };

[[ie That the compiler will place the data for the structure into one of the
data segments and then place it's address into the pointer variable.]]


Of course none of my compilers liked this.

Could anyone tell me whether the ANSI committee pondered over the problem of
tidying up the inconsistencies of the C initializations ?

		vic
--
Victor Gavin <vic@grep.co.uk||..!ukc!grep!vic||..!ukc!vision!grep!vic>

worley@compass.com (Dale Worley) (04/25/91)

In article <1991Apr24.141206.18103@grep.co.uk> vic@grep.co.uk (Victor Gavin) writes:
   I traced it back to my use of
	   char *fred = "bert"

   Could anyone tell me whether the ANSI committee pondered over the problem of
   tidying up the inconsistencies of the C initializations ?

Actually, initializations *are* consistent -- other than the object
named in the declaration, an initialization *never* allocates memory.
What is allocating the "extra" memory is the string literal "bert".
String literals *always* allocate memory for themselves, except in the
special case when they are used as the initializer for an array of
chars.  For instance,

	char *p;

	p = "1234";

allocates 5 bytes of memory to hold the string literal.

Dale Worley		Compass, Inc.			worley@compass.com
--
So you want to have a shameful affair?
Yet, somehow you can't justify it?

The next time you are contemplating a decision in which you are debating
whether or not to go for the gusto, ask yourself this Important Question:

	How long will I be dead?

With that perspective, you can now make a free, fearless choice to do
just about any goddamned sneaky thing your devious little mind can think
up.  Go ahead.  Have your fun.  You're welcome.  Go on.  See you in
Hell.
		--Matt Groening

steve@taumet.com (Stephen Clamage) (04/26/91)

vic@grep.co.uk (Victor Gavin) writes:

>... Which made me believe that I could use the following code:

>	struct bert { int a, b; }
>	struct fred { struct bert *abc; } blip = { {1,1} };

>[[ie That the compiler will place the data for the structure into one of the
>data segments and then place it's address into the pointer variable.]]

>Could anyone tell me whether the ANSI committee pondered over the problem of
>tidying up the inconsistencies of the C initializations ?

IMHO, this is not an inconsistency.  There is no way to specify an
anonymous aggregate constant in C.  Further, if we accept the syntax you
show, it would have to try to assign the aggregate constant to a pointer,
which would be rejected in any case.
You would need something more like this:
	struct fred { struct bert *abc; } blip = { &{1,1} };
This has some problems, in that {1, 1} has no type.

Bracketed initializers are syntactic ways to supply values to members
of the aggregate being initialized.  "{1,1}" has no meaning on its own.
You would need to extend the C language to support anonymous aggregate
constants, perhaps along the lines of
	(struct bert){1, 1}
(This is not a recommendation.)

I don't know whether X3J11 ever discussed such a thing, but I'm sure
they would have considered it outside their purview, there being no
such existing practice.

BTW, if one struct is "bert", shouldn't the other be "ernie"?
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

jackm@agcsun.UUCP (Jack Morrison) (04/26/91)

In article <1991Apr24.141206.18103@grep.co.uk> vic@grep.co.uk (Victor Gavin) writes:
>I (after many, many years of C programming) found that I couldn't perform what
>I considered to be a reasonable assignment command.
>I traced it back to my use of
>	char *fred = "bert"
>being the same as
>	char fred[] = {'b', 'e', 'r', 't', '\0'}

We'll assume ;-) you really meant that it's similar to

	char _fred[] = {'b', 'e', 'r', 't', '\0'};
	char *fred = _fred;

>Which made me believe that I could use the following code:
>	struct bert { int a, b; }
>	struct fred { struct bert *abc; } blip = { {1,1} };
>
>[[ie That the compiler will place the data for the structure into one of the
>data segments and then place it's address into the pointer variable.]]
>Of course none of my compilers liked this.

It's not so much an *initialization* inconsistency, but the limitation that
you can't write a constant structure value the same way you can a constant
string. For example, it would also be nice to be able to call

	void foo(struct bert b);

[NOT "struct bert *b", mind you] as

	foo( {1,1} );

or, if the compiler would like a little more help, 

	foo( (struct bert){1,1} );

I have no answer as to whether anyone official has considered it before...

-- 
"How am I typing?  Call 1-303-279-1300"     Jack C. Morrison
Ampex Video Systems    581 Conference Place, Golden CO 80401

gwyn@smoke.brl.mil (Doug Gwyn) (04/26/91)

In article <1991Apr24.141206.18103@grep.co.uk> vic@grep.co.uk (Victor Gavin) writes:
>Could anyone tell me whether the ANSI committee pondered over the problem of
>tidying up the inconsistencies of the C initializations ?

I doubt that we would have considered proposals for changing those
long-established parts of the C language that you described, for
any longer than it would take to unanimously reject them.  The
charter of X3J11 did not include redesigning the language, rather
merely standardizing existing practice and addressing perceived
significant deficiencies.  Well-established existing correct
practice had to continue to be permitted.

chap@art-sy.detroit.mi.us (j chapman flack) (04/26/91)

In article <1991Apr24.141206.18103@grep.co.uk> vic@grep.co.uk (Victor Gavin) writes:
>   ...
>I traced it back to my use of
>	char *fred = "bert"
>being the same as
>	char fred[] = {'b', 'e', 'r', 't', '\0'}

Ah, but they're not the same.  You can tell by the result of
  sizeof fred
in both cases.  What the first is really (more or less) equivalent to is:

   char bill[] = {'b','e','r','t','\0'};
   char *fred = bill; /* == &(bill[0]) */

It works because "bert" is one of the few types of constant defined into the
C language (i.e., decimal, octal, hex, character, string, that's it).  As a
constant, "bert" is a character array in its own right; it can be used to
initialize a character array, as in

char fred[] = "bert"; /* which *is* the same as char fred[]={'b','e',...} */

or its address can be taken and used to initialize a char pointer, which
happens implicitly in

char *fred = "bert";
>
>Which made me believe that I could use the following code:
>
>	struct bert { int a, b; }
>	struct fred { struct bert *abc; } blip = { {1,1} };
>

The difference is that the C definition doesn't build in a "structure
constant".  {1,1} is not a structure in its own right the way "garbonzo"
is a character array in its own right.  How could it be?--{1,1} doesn't
contain enough information to create a finished struct declaration.  So you
can't just take the address of {1,1} as you could "garbonzo".  You would need
the form:

struct bert { int a, b; } bill = {1,1};
struct fred { struct bert *abc } blip = { &bill };

I hope this helps.  I don't think the problem is an inconsistency in C, it's
just a consequence of C's lack of a "structure constant."  If you wanted to
add such a thing to the langauge, you'd have to define a syntax that included
everything needed to declare an appropriate structure, such as element names,
in the constant.  I think that would add unnecessary complexity to the
langauge.
-- 
Chap Flack                         Their tanks will rust.  Our songs will last.
chap@art-sy.detroit.mi.us                                   -Mikos Theodorakis

Nothing I say represents Appropriate Roles for Technology unless I say it does.

jamshid@ut-emx.uucp (Jamshid Afshar) (04/27/91)

In article <959@agcsun.UUCP> jackm@agcsun.UUCP (Jack Morrison) writes:
>In article <1991Apr24.141206.18103@grep.co.uk> vic@grep.co.uk (Victor Gavin) writes:
...
>>Which made me believe that I could use the following code:
>>	struct bert { int a, b; }
>>	struct fred { struct bert *abc; } blip = { {1,1} };
...
>It's not so much an *initialization* inconsistency, but the limitation that
>you can't write a constant structure value the same way you can a constant
>string. For example, it would also be nice to be able to call
>
>	void foo(struct bert b);
>
>	foo( {1,1} );
>or, if the compiler would like a little more help, 
>	foo( (struct bert){1,1} );

I just thought I'd mention that this kind of structure-on-the-fly stuff
is possible in C++.
	struct bert { 
		int a, b; 
		bert(int the_a, int the_b) : a(the_a), b(the_b) {}
	};
	foo( bert b );  // you don't need the keyword 'struct'
	...
		foo( bert(5, 6) );  // call foo() with temporary bert

Yes, it's a temporary created on the stack, but you can make a static
object:
	static bert a_bert = bert(5, 6);
or	static bert a_bert(5, 6);   // these two definitions are equivalent

But, as Jack said, you can't write a constant structure value the same
way you can a constant string in C or C++ (can't gcc do something like
this, though?).  Therefore, there is no way to do what Victor wanted
to do without another variable.

Anyway, I think every C programmer should take a look at C++, even if
she or he doesn't do object-oriented programming (though I have found
OOP to be a Very Good Thing).  C++ removes alot of restrictions on
initializations, has type-safe i/o (doesn't use var. args), is more
strongly typed, has type-safe linkage, and IMO is just a better C.  An
ANSI C program should compile without any changes (except C++ requires
a cast when assigning a void pointer to a typed pointer).

Just another cog in the wheel of the OOP propaganda machine, :)
Jamshid Afshar
jamshid@emx.utexas.edu