> dmp <pate...@gmail.com> writes:
>>how to create a circular linked list in C?
>
> int main( void ){ struct node { struct node * next; } this ={ &this }; }
That's a constraint violation. &this is not an address constant. I
think it is fine with a object static.
--
Ben.
I believe that's only a constraint violation in C90. In C99, an
initializer for an object of automatic storage duration may have
non-constant expressions.
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
I think it's fine just as it is. Could you please explain which
constraint it violates?
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
/root
--
Learn more or lose your rights!
http://www.guncontrolkills.com/
http://www.gunbanobama.com/
Learn more or lose your rights!
[please don't top-post]
> this is a key word in C++.
This is comp.lang.c.
--
Ian Collins
> this is a key word in C++.
this isn't a keyword in C, however, and we're discussing C, not C++.
<snip>
> Keith Thompson <ks...@mib.org> writes:
>>I believe that's only a constraint violation in C90. In C99, an
>>initializer for an object of automatic storage duration may have
>>non-constant expressions.
Yup, wrong standard. It's fine in C99. Thanks.
> I find this example in ISO/IEC 9899:1999 (E), 6.5.2.5, #15:
>
> »EXAMPLE 7 (...)
> struct int_list { int car; struct int_list *cdr; };
> struct int_list endless_zeros = {0, &endless_zeros};
> eval(endless_zeros);«
>
> The statement »eval(endless_zeros);« hints that this is part
> of a compound statement. The right-hand side seems to be a
> »compound literal«.
At the risk of being wrong again, no, it is an ordinary initialiser.
A compound literal starts with a parenthesised type:
(struct int_list){ /* ... */ }
The example appears in the section describing compound literals
because there is no way to write this object without naming it first.
Hence the need for an ordinary initialiser.
<snip>
--
Ben.
> In
> <0.989b9ce7906b86ea9f73.2009...@bsb.me.uk>,
> Ben Bacarisse wrote:
>
>> r...@zedat.fu-berlin.de (Stefan Ram) writes:
>>
>>> dmp <pate...@gmail.com> writes:
>>>>how to create a circular linked list in C?
>>>
>>> int main( void ){ struct node { struct node * next; } this ={ &this
>>> }; }
>>
>> That's a constraint violation. &this is not an address constant. I
>> think it is fine with a object static.
>
> I think it's fine just as it is. Could you please explain which
> constraint it violates?
Yes:
3.5.7 Initialization
...
All the expressions in an initializer for an object that has static
storage duration or in an initializer list for an object that has
aggregate or union type shall be constant expressions.
Sadly, it's a constraint in the wrong standard :-( Old habits die
hard.
--
Ben.
In which case, I think I've found (or at least, this thread may have
revealed) a bug in gcc. Here's my sample program, with enough added
to ensure that gcc can't even pretend that the CV doesn't matter (not
that I think it could anyway, but I wanted to avoid any "as if"
nonsense right at the outset):
$ cat foo.c
#include <stdio.h>
int main(void)
{
struct node
{
struct node *next;
} this = { &this };
printf("%p\n", this.next);
return 0;
}
$ make
gcc -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align
-Wpointer-arith -Wbad-function-cast -Wmissing-prototypes
-Wstrict-prototypes -Wmissing-declarations -Winline -Wundef
-Wnested-externs -Wcast-qual -Wshadow -Wconversion -Wwrite-strings
-ffloat-store -O2 -fno-builtin -g -pg -c -o foo.o foo.c
gcc -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align
-Wpointer-arith -Wbad-function-cast -Wmissing-prototypes
-Wstrict-prototypes -Wmissing-declarations -Winline -Wundef
-Wnested-externs -Wcast-qual -Wshadow -Wconversion -Wwrite-strings
-ffloat-store -O2 -fno-builtin -g -pg -o foo foo.o -lm -lncurses
-lpcl
So where's the diagnostic message? Have I inadvertently turned it off,
I wonder?
> In
> <0.0a63caf823007d208a7d.2009...@bsb.me.uk>,
> Ben Bacarisse wrote:
<snip>
Maybe, but it is fixed in recent gcc:
$ gcc -std=c89 -pedantic foo.c
foo.c: In function ‘main’: foo.c:8:
warning: initializer element is not computable at load time
foo.c:9: warning: format ‘%p’ expects type ‘void *’, but argument 2
has type ‘struct node *’
$ gcc --version
gcc (Ubuntu 4.4.1-4ubuntu8) 4.4.1
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
I get the diagnostic even with exactly the same set of flags.
[BTW, your use of -fno-builtin is probably suppressing the warning
about the printf format/argument mismatch. It does on 4.4.1.]
--
Ben.
> Ben Bacarisse wrote:
>> 3.5.7 Initialization
>> ...
>> All the expressions in an initializer for an object that has
>> static storage duration or in an initializer list for an object
>> that has aggregate or union type shall be constant expressions.
>
> In which case, I think I've found (or at least, this thread may have
> revealed) a bug in gcc. Here's my sample program, with enough added
> to ensure that gcc can't even pretend that the CV doesn't matter (not
> that I think it could anyway, but I wanted to avoid any "as if"
> nonsense right at the outset):
[...]
> So where's the diagnostic message? Have I inadvertently turned it off,
> I wonder?
I don't think a diagnostic message is required:
6.6 Constant expressions
...
10 An implementation may accept other forms of constant expressions.
--
Ben Pfaff
http://benpfaff.org
It is only a constraint violation in C89 and I can't find that wording
in section 3.4 (the section about constant expressions in C89). I
don't have a good copy, so I might be missing it.
--
Ben.
Oops, where is the warning about non-void-* being passed to %p?
Maybe you're not using glibc, which has the right annotations in the
headers.
> return 0;
> }
> $ make
> gcc -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align
> -Wpointer-arith -Wbad-function-cast -Wmissing-prototypes
> -Wstrict-prototypes -Wmissing-declarations -Winline -Wundef
> -Wnested-externs -Wcast-qual -Wshadow -Wconversion -Wwrite-strings
> -ffloat-store -O2 -fno-builtin -g -pg -c -o foo.o foo.c
But you didn't say ``be a c89 compiler''. The code is being treated
as c99.
Also, reports about gcc behavior are not all that informative without the
version.
[fedora@localhost ~]$ gcc -Wall -ansi -pedantic -std=c89 test.c
test.c: In function ‘main’:
test.c:8: warning: initializer element is not computable at load time
test.c:9: warning: format ‘%p’ expects type ‘void *’, but argument 2 has type ‘struct node *’
[fedora@localhost ~]$ gcc --version
gcc (GCC) 4.4.0 20090506 (Red Hat 4.4.0-4)
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[fedora@localhost ~]$ gcc -Wall -ansi -pedantic -std=c99 test.c
test.c: In function ‘main’:
test.c:9: warning: format ‘%p’ expects type ‘void *’, but argument 2 has type ‘struct node *’
This is not particularly new:
[rhel4@localhost ~]$ gcc -Wall -ansi -pedantic test.c
test.c: In function `main':
test.c:8: warning: initializer element is not computable at load time
test.c:9: warning: void format, node arg (arg 2)
[rhel4@localhost ~]$ gcc --version
gcc (GCC) 3.4.3 20050227 (Red Hat 3.4.3-22.1)
Copyright (C) 2004 Free Software Foundation, Inc.
> Richard Heathfield <r...@see.sig.invalid> writes:
>
<snip>
>> So where's the diagnostic message? Have I inadvertently turned it
>> off, I wonder?
>
> Maybe, but it is fixed in recent gcc:
>
> $ gcc -std=c89 -pedantic foo.c
> foo.c: In function ?main?: foo.c:8:
> warning: initializer element is not computable at load time
Oh, fair enough then.
> foo.c:9: warning: format ?%p? expects type ?void *?, but argument 2
> has type ?struct node *?
Oops. :-)
Yes, he did; that's what "-ansi -pedantic" means.
Well, you now have a couple of reasons to upgrade to a more recent
version of gcc ;-) One is that your version is broken (and I'm sure
you've given as a reason for not upgrading something to the effect of,
"if it ain't broke don't fix it"), the other is better diagnostics on
things which do not require them.
--
Flash Gordon
Hang on there, we don't want to go and expose Richard to the evils of
modern technology, or worse still, C99 support....
--
Ian Collins
I would guess that Ben was compiling your code with a C++ compiler and so
got an error - lots of people do this (especially using g++ instead of
gcc).
That's why it is very bad practise to in clude C++ syntax errors in your
C code.
/root
--
Learn more or lose your rights!
http://www.guncontrolkills.com/
http://www.gunbanobama.com/
Learn more or lose your rights!
> Richard
>
> I would guess that Ben was compiling your code with a C++ compiler and so
> got an error - lots of people do this (especially using g++ instead of
> gcc).
No, I used a C compiler. In subsequent messages I even gave the
compile command and the exact output. There is no need to guess.
<snip>
--
Ben.
In <7nav3fF...@mid.individual.net>, Ian Collins wrote:
> Flash Gordon wrote:
>> Richard Heathfield wrote:
>>> Ben Bacarisse wrote:
<snip>
>>>> foo.c:9: warning: format ?%p? expects type ?void *?, but argument
>>>> 2 has type ?struct node *?
>>>
>>> Oops. :-)
>>
>> Well, you now have a couple of reasons to upgrade to a more recent
>> version of gcc ;-)
Um, yes, I do, don't I? And therefore it is now firmly on my To-Do
list. (Admittedly it isn't on top of the list, but it IS on the
list.)
<snip>
> Hang on there, we don't want to go and expose Richard to the evils
> of modern technology, or worse still, C99 support....
The C programming community has had C99 /support/ (in the sense that
some C99 features are provided) since 1972 or so. What I'm waiting
for is C99 *conformance* and C99 *ubiquity* (in the sense that I can
use any C99 feature I like and expect it to work correctly on every
current platform, just like I can with C89).
Bollocks. Every use of a C++ syntax error in posted C code is
a high pass filter that can be used to filter out dull readers.
Phil
--
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
> Richard
>
> I would guess that Ben was compiling your code with a C++ compiler
> and so got an error - lots of people do this (especially using g++
> instead of gcc).
>
> That's why it is very bad practise to in clude C++ syntax errors in
> your C code.
No, it's actually quite a good idea, as it means anyone dense (or
absent-minded) enough to compile C code with a C++ compiler[1] will
find themselves having to stop and think.
Do you write your C++ code so as to be compilable by a Fortran
compiler? Do you write Fortran code that is acceptable to COBOL
compilers? Do you write COBOL that is acceptable to BASIC
interpreters?
[1] Note that P J Plauger doesn't fall into either category, but then
he wouldn't be compiling that particular code anyway.
> In <hepi97$2t2$1...@aioe.org>, root wrote:
>
>> Richard
>>
>> I would guess that Ben was compiling your code with a C++ compiler
>> and so got an error - lots of people do this (especially using g++
>> instead of gcc).
>>
>> That's why it is very bad practise to in clude C++ syntax errors in
>> your C code.
>
> No, it's actually quite a good idea, as it means anyone dense (or
> absent-minded) enough to compile C code with a C++ compiler[1] will
> find themselves having to stop and think.
>
> Do you write your C++ code so as to be compilable by a Fortran
> compiler? Do you write Fortran code that is acceptable to COBOL
> compilers? Do you write COBOL that is acceptable to BASIC
> interpreters?
Only a complete idiot would compare compiling C++ with a Fortran
compiler with compiling C with a C++ compiler.
>
> [1] Note that P J Plauger doesn't fall into either category, but then
> he wouldn't be compiling that particular code anyway.
--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c
No, they will find themselves having to stop, curse, and then add
special case rules for your module to build with a C compiler,
or patch your code to compile as C++, or even have to go out and
install a C compiler.
Over the years, some users of my Kazlib library (current employer included!)
have reported having to add casts to the code and eliminate the use of C++
keywords.
They wanted to (and did!) drop the code into C++ projects, without
switching to a C compiler just for those modules.
I have a new home for this project now, and the new release will be
fully C++ compatible.
A recent project of mine, the txr utility, can be compiled as C or C++.
You can ``./configure --ccname=g++'' and it builds fine.
By supporting this mode, I found a few bugs. From time to time, I
now configure and build this way, to check for regressions.
> Do you write your C++ code so as to be compilable by a Fortran
> compiler?
This is not a particularly apt analogy because C++ code that compiles as
Fortran is not a feasible way of developing anything. A program which can be
interpreted as C++ or Fortran is an obfuscated programming curiosity, with no
economic benefit (I'm guessing; someone point me to a counterexample). Fortran
is not similar to C++; the two are not dialects. So just figuring out how to
make a hello world program which is both C++ and Fortran is a Sunday afternoon
puzzle.
Wheras writing C that compiles as C++ also takes little effort, and provides
a benefits: improved portability, better safety. It is feasible because C++ is
a dialect of C, with the two sharing a subset which is makes a viable
programming language that is exactly as expressive and powerful as C.
Conforming to standards is good, right? So if you can /easily/ conform to two
standards simultaneously, and make people's lives easier by doing that, that's
double good. More bugs found by better diagnostics: double plus plus good.
> dmp <pate...@gmail.com> writes:
>>how to create a circular linked list in C?
>
> int main( void ){ struct node { struct node * next; } this ={ &this }; }
You better do not use the word "this" in C code because it will cause
problems when it is ported to C++.
That's one way of looking at it. Another way of looking at it is: "Use
whatever object names you feel are most appropriate, provided they
follow the rules of C."
Even though it's easy to call C code from C++, there may well be good
reasons for rewriting C modules in C++. "Because I want to" is a good
reason, for a start! But if you decide to do that, presumably you'll
want to use C++ idioms, not C idioms, so you're basically looking at
a rewrite anyway, in which case mere identifier changes are going to
be the least of your problems.
[OT]: sed -e "s/this/that/g" ?
problem solved?
bye
Only if you don't mind renaming "pkthist" (packet history) to "pkthatt",
and you don't care that ``that'' may already be in use.
E.g.:
node *this, *that;
now becomes
node *that, *that;
Oops! This is a lucky case where you get a duplicate definition. There are ways
this can happen in such a way that it leads to a silent change of behavior.
Porting C code to C++ requires thinking; it's not something you can do by
global search and replace.
I have seen people big things up before but this contrived example takes
the biscuit!
Only an idiot would do a global search replace for *anything* without
checking. And this "this" issue is fairly unique.
"Porting" C to C++ is generally trivial.
I think you guys are saying basically the same thing, and are on the
same side of the debate - that is, against the "big heads" who think it
is cool to intentionally insert gratuitous C++ incompatibility into
their C code, their goal being to trip up anyone who has the audacity
to try to compile said code with a C++ compiler. (*)
You seem to be in agreement that a simple global-search-and-replace is
never the solution to a language transformation problem. You also seem
to be in agreement that the "porting" shouldn't be necessary anyway,
since you should do it right from the start - i.e., write your C code as
if it might someday be compiled as C++.
P.S. I recommend the TXL utility for language transformation tasks.
(*) And note, of course, that this thesis fits in with my general idea
of the C inferiority complex that drives this group.
now i see a good reason to always leave blanks around identifiers...
then:
sed -e "s/ this / that /g"
> and you don't care that ``that'' may already be in use.
> E.g.:
>
> node *this, *that;
>
> now becomes
>
> node *that, *that;
>
ok then:
sed -e "s/ that / twat /g"
sed -e "s/ this / that /g"
<OT>
sed is entirely capable of matching and replacing text on word boundaries.
</OT>
That still doesn't imply that sed by itself is a good way to do code
maintenance; at the very least, you should confirm that the changes to
your code are correct (and can be backed out if they aren't).
x = this;
Your "when", rather than "if", presumes that there is no choice.
All C code _will_ be ported to C++ seems to be your principle.
Please share your point of view on the linux kernel mailing list,
in order to fully understand the concept of being flamed to a
frizzle. Some will tell you you're full of crap, others will not
be so polite.
x = this ;
No, I think it would be at least as entertaining to watch someone share some
comp.lang.c style ``Holy ISO standard C is the law'' pontification with that
same mailing list.
> in order to fully understand the concept of being flamed to a
> frizzle. Some will tell you you're full of crap, others will not
> be so polite.
In the early days, there was a time when the Linux kernel was being compiled
with g++. It was for better diagnostics and safety. But g++ wasn't very good at
that time, so the maintenance of this was given up. Or so I hazily recall the
story.
But the point is, that the kernel developers at that time were at least
somewhat open minded to the idea of working in a C dialect that compiles as
C++.
Today, it would be a quite an effort to convert the kernel to a dialect that
compiles with g++. The original reasons for doing so probably wouldn't apply
so much, because the C front end of gcc has improved too in 18 years.
Why would anyone do that?
The Linux kernel isn't written in ISO standard C, and there's
no particular reason it should be; it needs to use non-standard
extensions to do its job.
Nobody has claimed that the C standard is the law. It's merely
the definition of the language that we discuss in this newsgroup.
But if I were working on the Linux kernel sources, I'd certainly
want to understand the language standard well enough to know
what it guarantees and what's specific to the implementation.
Horrible.
puts("When using this program you should:");
--
Flash Gordon
Yep, they'd certainly make mincemeat of the likes of Heathfield.
To be fair though, the mismatch comes from two completely different
approaches to programming.
Linux kernel developers want to produce something useful that will
provide a real benefit to people.
Your typical clc "regular" sees programming as a purely academic and
theoretical exercise, a kind of mental chess game played according to
the rules of an ISO Standard.
Naturally, each will scorn the other, as pragmatists and idealists have
fought across the centuries.
ok i give up ;-)
bye