Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #41349 > unrolled thread

complex declarations

Started byRobbie Brown <dac@nomail.invalid>
First post2014-03-04 20:18 +0000
Last post2014-03-05 11:44 +0000
Articles 20 on this page of 24 — 5 participants

Back to article view | Back to comp.lang.c


Contents

  complex declarations Robbie Brown <dac@nomail.invalid> - 2014-03-04 20:18 +0000
    Re: complex declarations James Kuyper <jameskuyper@verizon.net> - 2014-03-04 15:49 -0500
      Re: complex declarations James Kuyper <jameskuyper@verizon.net> - 2014-03-04 16:06 -0500
        Re: complex declarations Robbie Brown <dac@nomail.invalid> - 2014-03-05 12:18 +0000
          Re: complex declarations "BartC" <bc@freeuk.com> - 2014-03-05 12:56 +0000
            Re: complex declarations James Kuyper <jameskuyper@verizon.net> - 2014-03-05 08:24 -0500
              Re: complex declarations "BartC" <bc@freeuk.com> - 2014-03-05 16:26 +0000
          Re: complex declarations James Kuyper <jameskuyper@verizon.net> - 2014-03-05 08:13 -0500
            Re: complex declarations Robbie Brown <dac@nomail.invalid> - 2014-03-05 13:32 +0000
          Re: complex declarations Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-03-05 14:32 +0000
      Re: complex declarations Robbie Brown <dac@nomail.invalid> - 2014-03-04 21:42 +0000
        Re: complex declarations Keith Thompson <kst-u@mib.org> - 2014-03-04 14:04 -0800
          Re: complex declarations Robbie Brown <dac@nomail.invalid> - 2014-03-05 09:22 +0000
            Re: complex declarations James Kuyper <jameskuyper@verizon.net> - 2014-03-05 07:29 -0500
              Re: complex declarations Keith Thompson <kst-u@mib.org> - 2014-03-05 08:38 -0800
        Re: complex declarations James Kuyper <jameskuyper@verizon.net> - 2014-03-04 17:05 -0500
    Re: complex declarations Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-03-04 21:15 +0000
      Re: complex declarations "BartC" <bc@freeuk.com> - 2014-03-04 21:38 +0000
        Re: complex declarations Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-03-04 23:27 +0000
      Re: complex declarations Robbie Brown <dac@nomail.invalid> - 2014-03-04 21:59 +0000
        Re: complex declarations James Kuyper <jameskuyper@verizon.net> - 2014-03-04 17:12 -0500
        Re: complex declarations Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-03-05 00:28 +0000
          Re: complex declarations Robbie Brown <dac@nomail.invalid> - 2014-03-05 09:10 +0000
            Re: complex declarations Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-03-05 11:44 +0000

Page 1 of 2  [1] 2  Next page →


#41349 — complex declarations

FromRobbie Brown <dac@nomail.invalid>
Date2014-03-04 20:18 +0000
Subjectcomplex declarations
Message-ID<lf5cdv$dll$1@dont-email.me>
I have the following code

/* declare signal as function (int, pointer to function (int) returning 
void) returning pointer to function (int) returning void */

void (*signal(int, void (*)(int)) ) (int);

/* simplify things a bit using a typedef */
typedef void (*fptr)(int);

int main(void){

   /* declare and define function that takes int and returns void */
   void foobar(int x){
     printf("%s%d\n", "x in foobar is ", x);
   }

   /* define signal using the typedef, compiles */
   fptr signal(int x, fptr y){
     return NULL;
   }

   /* What I'd like to do now is to replace the fptr typedef with the
      pre typedef type if that makes sense.
      Why?  because it helps my understanding */

   /* Here I can say, void y(), void (y)(), void (*y)(), void y(int),
      void(y)(int) void (*y)(int) for the second arg and they all
      compile */

   fptr signal2(int x, void (*y)(int) ){
      NULL;
   }

   /* finally I want to do something like
      return a pointer to a function taking int and returning void
      but I just can't figure out how to do it. I've tried
      void (*)(int), void (int), (void (*) (int)) etc etc without
      success */

   /* can't get this to compile in any way */
   //void (*x) (int) signal3(int x, void (*y)(int) ){
   //  return  NULL;
   //}

}


How do I code signal3 to completely get rid of my dependence on the 
typedef. Once again, the only reason I want to do this is because I can 
(hopefully)

Thanks

-- 
Rob - not floundering, fishing

[toc] | [next] | [standalone]


#41352

FromJames Kuyper <jameskuyper@verizon.net>
Date2014-03-04 15:49 -0500
Message-ID<53163C3C.8060203@verizon.net>
In reply to#41349
On 03/04/2014 03:18 PM, Robbie Brown wrote:
> I have the following code
> 
> /* declare signal as function (int, pointer to function (int) returning 
> void) returning pointer to function (int) returning void */
> 
> void (*signal(int, void (*)(int)) ) (int);
> 
> /* simplify things a bit using a typedef */
> typedef void (*fptr)(int);
> 
> int main(void){

This location is inside the block associated with main.

>    /* declare and define function that takes int and returns void */
>    void foobar(int x){
>      printf("%s%d\n", "x in foobar is ", x);
>    }

C function definitions can only occur at file scope (6.9p1). You can
declare a function at block scope (6.8p2), but you can't define it
there. Because you can't define it with block scope, I also personally
feel it's a bad idea to declare it at file scope - but that's just a
personal preference, not a C rule.

If you got this code to compile (except for the part you're asking
about), then you're taking advantage of a non-conforming extension to C
which allows block scope definitions of functions. If making use of that
extension is important to you, then you should post your questions to a
forum specializing in the particular compiler that supports that
extension. If it supports that extension, it may support others, and
advice that you get from this newsgroup might be useless for that compiler.

>    /* define signal using the typedef, compiles */
>    fptr signal(int x, fptr y){
>      return NULL;
>    }
> 
>    /* What I'd like to do now is to replace the fptr typedef with the
>       pre typedef type if that makes sense.
>       Why?  because it helps my understanding */
> 
>    /* Here I can say, void y(), void (y)(), void (*y)(), void y(int),
>       void(y)(int) void (*y)(int) for the second arg and they all
>       compile */
> 
>    fptr signal2(int x, void (*y)(int) ){
>       NULL;
>    }
> 
>    /* finally I want to do something like
>       return a pointer to a function taking int and returning void
>       but I just can't figure out how to do it. I've tried
>       void (*)(int), void (int), (void (*) (int)) etc etc without
>       success */
> 
>    /* can't get this to compile in any way */
>    //void (*x) (int) signal3(int x, void (*y)(int) ){

That's because you start out declaring an identifier named x to be a
pointer to a function taking an argument of type int. Then you try to
follow that up with the declaration of signal3. You can declare the name
of a function and the names of it's arguments, but you can't declare a
name for the value returned by that function. What you want to do is to
declare signal3 as returning an UNNAMED pointer to a function taking one
argument of type int.

>    //  return  NULL;
>    //}
> 
> }
> 
> 
> How do I code signal3 to completely get rid of my dependence on the 
> typedef. Once again, the only reason I want to do this is because I can 
> (hopefully)

How do you make the pointer returned by signal3 unnamed? You have to use
a type name, which syntactically looks just like the declaration of an
identifier of a function or an object, except that it omits the identifier.

	void (*)(int) signal3(int x, void(*y)(int))

Type names are also used in casts and sizeof() expressions. In C99,
they're also used in compound literals. In C2011, they're also used in
_Generic() associations, _Alignof() expressions, _Atomic() type
specifiers, and _Alignas() specifiers.

[toc] | [prev] | [next] | [standalone]


#41353

FromJames Kuyper <jameskuyper@verizon.net>
Date2014-03-04 16:06 -0500
Message-ID<5316406C.9050905@verizon.net>
In reply to#41352
On 03/04/2014 03:49 PM, James Kuyper wrote:
,,,
> C function definitions can only occur at file scope (6.9p1). You can
> declare a function at block scope (6.8p2), but you can't define it
> there. Because you can't define it with block scope, I also personally
> feel it's a bad idea to declare it at file scope - but that's just a

"file" should have been "block" in that last sentence. That error almost
exactly reverses my intended meaning.

...
> Type names are also used in casts and sizeof() expressions. In C99,
> they're also used in compound literals. In C2011, they're also used in
> _Generic() associations, _Alignof() expressions, _Atomic() type
> specifiers, and _Alignas() specifiers.

I should also mention that function declarations are allowed to use type
names for the parameters; you're only required to name the parameters in
the function definition itself. This is not stated directly by the use
of the phrase "type name", but only implicitly by the fact that 6.7.6p1
does not require a parameter-declaration to contain a declarator, it can
use an abstract-declarator instead. That freedom is retracted for
function definitions (6.9.1p5).

[toc] | [prev] | [next] | [standalone]


#41374

FromRobbie Brown <dac@nomail.invalid>
Date2014-03-05 12:18 +0000
Message-ID<lf74lv$s1q$1@dont-email.me>
In reply to#41353
On 04/03/14 21:06, James Kuyper wrote:
> On 03/04/2014 03:49 PM, James Kuyper wrote:
> ,,,
>> C function definitions can only occur at file scope (6.9p1). You can
>> declare a function at block scope (6.8p2), but you can't define it
>> there. Because you can't define it with block scope, I also personally
>> feel it's a bad idea to declare it at file scope - but that's just a
>
> "file" should have been "block" in that last sentence. That error almost
> exactly reverses my intended meaning.

OK, I suppose I'm pushing my luck here but I'm not entirely sure what 
you are saying so here goes

If I have a 'program' foo.c that (tries to) comply with some seemingly 
nebulous set of rules that are apparently defined in the latest spec I 
can find 'for free' (n1256.pdf) then I can't have nested functions for 
one thing. So, where exactly should I define my functions?

If I have an 'all in one file program' then I don't need function 
prototypes and I declare and define all my sub-functions, that is 
functions that are not main() at the top of the file, once, and use them 
in main(). I'd call this 'file scope'.

I can also declare prototypes at the top of the file and define the 
functions after the end of main() although why I'd want to do this I 
have no idea. Also 'file scope'

I can also declare prototypes at the head of main or in an include file 
and define them somewhere else. What scope is this? It's obviously more 
flexible to have a func.h and func.c dedicated 'function container' as 
it allows easy reuse.

There are other questions, like, where's the sanity of declaring a 
prototype in block scope when you can't define it in same (this seems 
particularly bizarre)

I'm trying to come up with a sane 'standard approach' to partitioning my 
code. I don't expect an answer as I'm not even sure of the question but 
it's good to get it off my chest :-)


-- 
Rob - not floundering, fishing
========================================================
For every SCoP we generate the polyhedral representation
and transform it back to gimple.
========================================================
Seems perfectly reasonable to me.

[toc] | [prev] | [next] | [standalone]


#41376

From"BartC" <bc@freeuk.com>
Date2014-03-05 12:56 +0000
Message-ID<X9FRu.230858$IS.94538@fx01.am4>
In reply to#41374
"Robbie Brown" <dac@nomail.invalid> wrote in message
news:lf74lv$s1q$1@dont-email.me...
> On 04/03/14 21:06, James Kuyper wrote:
>> On 03/04/2014 03:49 PM, James Kuyper wrote:
>> ,,,
>>> C function definitions can only occur at file scope (6.9p1). You can
>>> declare a function at block scope (6.8p2), but you can't define it
>>> there. Because you can't define it with block scope, I also personally
>>> feel it's a bad idea to declare it at file scope - but that's just a
>>
>> "file" should have been "block" in that last sentence. That error almost
>> exactly reverses my intended meaning.
>
> OK, I suppose I'm pushing my luck here but I'm not entirely sure what you
> are saying so here goes
>
> If I have a 'program' foo.c that (tries to) comply with some seemingly
> nebulous set of rules that are apparently defined in the latest spec I can
> find 'for free' (n1256.pdf) then I can't have nested functions for one
> thing. So, where exactly should I define my functions?

You define one after the other in the file. But not one inside the other.

> If I have an 'all in one file program' then I don't need function
> prototypes and I declare and define all my sub-functions, that is
> functions that are not main() at the top of the file, once, and use them
> in main(). I'd call this 'file scope'.

Without prototypes, you need to define functions in a certain order such
that a function is always defined before it is called. But that's not always
possible.

> I can also declare prototypes at the top of the file and define the
> functions after the end of main() although why I'd want to do this I have
> no idea. Also 'file scope'

Because you (and people maintaining your code who are not familiar with the
call-tree) then have total freedom in editing the code, moving blocks
around, chopping things up, pasting from elsewhere, etc. Otherwise you have
to spend some effort in making sure that all functions are in a particular
order.

But, if any of your functions are exported to another module, then you will
need to produce prototypes for that module anyway. (Actually all C functions
are exported unless you declare them with 'static'. You can also call them
from elsewhere without a prototype; that's how C used to work. These days
prototypes for exported/imported functions are a good idea.)

> I can also declare prototypes at the head of main or in an include file
> and define them somewhere else. What scope is this? It's obviously more
> flexible to have a func.h and func.c dedicated 'function container' as it
> allows easy reuse.
>
> There are other questions, like, where's the sanity of declaring a
> prototype in block scope when you can't define it in same (this seems
> particularly bizarre)

That can work for an 'extern' function defined in another module and 
declared for use here. It would
be unusual though to want to restrict its visibility to just that function 
(or even that block).

> I'm trying to come up with a sane 'standard approach' to partitioning my
> code. I don't expect an answer as I'm not even sure of the question but
> it's good to get it off my chest :-)

This is C. There isn't a standard approach.

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#41378

FromJames Kuyper <jameskuyper@verizon.net>
Date2014-03-05 08:24 -0500
Message-ID<lf78hn$nat$1@dont-email.me>
In reply to#41376
On 03/05/2014 07:56 AM, BartC wrote:
> "Robbie Brown" <dac@nomail.invalid> wrote in message
> news:lf74lv$s1q$1@dont-email.me...
...
> But, if any of your functions are exported to another module, then you will
> need to produce prototypes for that module anyway. (Actually all C functions
> are exported unless you declare them with 'static'. You can also call them
> from elsewhere without a prototype; that's how C used to work. These days
> prototypes for exported/imported functions are a good idea.)

Note to Robbie: Bartc is primarily interested in designing his own
language, and uses the term "export" to describe a feature of that
language. This term has no well-defined meaning in C. C functions have
external linkage unless declared 'static', in which case they have
internal linkage. However, they cannot be called from another
translation unit without a declaration in scope in that translation
unit. The declaration should be a prototype, but that's not required by
the language.

In C90, if a previously undeclared identifier was used as if it were a
function, a declaration was implicitly created for that identifier as
the name of a function returning an int and taking a fixed but
unspecified number of arguments of unspecified types. This was found to
be a very error-prone feature - it was removed in C99.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#41381

From"BartC" <bc@freeuk.com>
Date2014-03-05 16:26 +0000
Message-ID<0gIRu.3381$0X5.30@fx31.am4>
In reply to#41378
"James Kuyper" <jameskuyper@verizon.net> wrote in message
news:lf78hn$nat$1@dont-email.me...
> On 03/05/2014 07:56 AM, BartC wrote:
>> "Robbie Brown" <dac@nomail.invalid> wrote in message
>> news:lf74lv$s1q$1@dont-email.me...
> ...
>> But, if any of your functions are exported to another module, then you
>> will
>> need to produce prototypes for that module anyway. (Actually all C
>> functions
>> are exported unless you declare them with 'static'. You can also call
>> them
>> from elsewhere without a prototype; that's how C used to work. These days
>> prototypes for exported/imported functions are a good idea.)
>
> Note to Robbie: Bartc is primarily interested in designing his own
> language,

(Not quite true, I've been trying to avoid doing so. However....)

> and uses the term "export" to describe a feature of that
> language. This term has no well-defined meaning in C. C functions have
> external linkage unless declared 'static', in which case they have
> internal linkage.

If you define a function F in translation unit A, to be called from
translation unit B, would anyone really be completely flummoxed if I
described F as being exported from A, and imported by B?

And I tend to declare such a function F (even when writing C), with a
'global' prefix (an empty macro) in A, and with an 'extern' prefix in B.

Proper C of course prefers to use no prefix when declaring F when it is
defined in A, and no prefix either when declaring it in B, just to make it
perfectly clear what is what! With un-exported local functions needing a
'static' prefix, obviously.

-- 
Bartc

 

[toc] | [prev] | [next] | [standalone]


#41377

FromJames Kuyper <jameskuyper@verizon.net>
Date2014-03-05 08:13 -0500
Message-ID<lf77ub$iu8$1@dont-email.me>
In reply to#41374
On 03/05/2014 07:18 AM, Robbie Brown wrote:
> On 04/03/14 21:06, James Kuyper wrote:
>> On 03/04/2014 03:49 PM, James Kuyper wrote:
>> ,,,
>>> C function definitions can only occur at file scope (6.9p1). You can
>>> declare a function at block scope (6.8p2), but you can't define it
>>> there. Because you can't define it with block scope, I also personally
>>> feel it's a bad idea to declare it at file scope - but that's just a
>>
>> "file" should have been "block" in that last sentence. That error almost
>> exactly reverses my intended meaning.
> 
> OK, I suppose I'm pushing my luck here but I'm not entirely sure what 
> you are saying so here goes
> 
> If I have a 'program' foo.c that (tries to) comply with some seemingly 
> nebulous set of rules that are apparently defined in the latest spec I 
> can find 'for free' (n1256.pdf) then I can't have nested functions for 
> one thing. So, where exactly should I define my functions?

At file scope, in as many or as few different files as you like.

> If I have an 'all in one file program' then I don't need function 
> prototypes and I declare and define all my sub-functions, that is 
> functions that are not main() at the top of the file, once, and use them 
> in main(). I'd call this 'file scope'.
> 
> I can also declare prototypes at the top of the file and define the 
> functions after the end of main() although why I'd want to do this I 
> have no idea. Also 'file scope'

Some people (not including myself) prefer that approach because they
consider it more logical.

> I can also declare prototypes at the head of main or in an include file 
> and define them somewhere else. What scope is this?

That depends upon what you mean by "head of main", and where you
#include the header file:

bar.h:
#ifndef H_BAR
#define H_BAR
int bar(int);
#endif

foo.h:
#ifndef H_FOO
#define H_FOO
void foo();
#endif

main.c:
// Is this what you mean by "head of main"?
// create a file scope declaration for bar():
#include "bar.h"
int file_scope_declaration(double);

int main()
{
    // Or is this what you mean by "head of main"?
    // NB: I do NOT recommend block scope function declarations
    double block_scope_declaration(int);
    // Create block scope declaration for foo()
    #include "foo.h"
    // Do NOT do this with any standard header - the behavior is
    // undefined (7.1.2p4).

    foo();

    return bar(file_scope_declaration(block_scope_declaration(0));
}


> There are other questions, like, where's the sanity of declaring a 
> prototype in block scope when you can't define it in same (this seems 
> particularly bizarre)

While I agree with you about that, those who disagree with us say that
by doing so, they're limiting the scope of the prototype, reducing the
danger of naming conflicts.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#41379

FromRobbie Brown <dac@nomail.invalid>
Date2014-03-05 13:32 +0000
Message-ID<lf790u$r13$1@dont-email.me>
In reply to#41377
On 05/03/14 13:13, James Kuyper wrote:
> On 03/05/2014 07:18 AM, Robbie Brown wrote:
>> On 04/03/14 21:06, James Kuyper wrote:
>>> On 03/04/2014 03:49 PM, James Kuyper wrote:
>>> ,,,
>>>> C function definitions can only occur at file scope (6.9p1). You can
>>>> declare a function at block scope (6.8p2), but you can't define it
>>>> there. Because you can't define it with block scope, I also personally
>>>> feel it's a bad idea to declare it at file scope - but that's just a
>>>
>>> "file" should have been "block" in that last sentence. That error almost
>>> exactly reverses my intended meaning.
>>
>> OK, I suppose I'm pushing my luck here but I'm not entirely sure what
>> you are saying so here goes

<snip>

> That depends upon what you mean by "head of main", and where you
> #include the header file:
>
> bar.h:
> #ifndef H_BAR
> #define H_BAR
> int bar(int);
> #endif
>
> foo.h:
> #ifndef H_FOO
> #define H_FOO
> void foo();
> #endif
>
> main.c:
> // Is this what you mean by "head of main"?

Yes, my fault for not being clear.
I think I've probably got this now, interesting point about defining 
functions after main(). I can see some sense in that now.

> // create a file scope declaration for bar():
> #include "bar.h"
> int file_scope_declaration(double);
>
> int main()
> {
>      // Or is this what you mean by "head of main"?
>      // NB: I do NOT recommend block scope function declarations
>      double block_scope_declaration(int);
>      // Create block scope declaration for foo()
>      #include "foo.h"
>      // Do NOT do this with any standard header - the behavior is
>      // undefined (7.1.2p4).

Yea, I'd probably run screaming into the night if I came across this.
Never even considered it.



-- 
Rob - not floundering, fishing
========================================================
For every SCoP we generate the polyhedral representation
and transform it back to gimple.
========================================================
Seems perfectly reasonable to me.

[toc] | [prev] | [next] | [standalone]


#41380

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2014-03-05 14:32 +0000
Message-ID<0.6152c1dc32819d503544.20140305143203GMT.87y50o90nw.fsf@bsb.me.uk>
In reply to#41374
Robbie Brown <dac@nomail.invalid> writes:
<snip>
> There are other questions, like, where's the sanity of declaring a
> prototype in block scope when you can't define it in same (this seems
> particularly bizarre)

Yes, but it's easy to support and it would seem strange to outlaw it for
no good reason.  The prohibition on *defining* function inside others is
due to the fact that it might impose extra costs on the implementation.
I say "might" because I think gcc has found a way to avoid the cost
except when it must be paid, but in the early days of C I suspect the
cost was seen as being inevitable.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#41356

FromRobbie Brown <dac@nomail.invalid>
Date2014-03-04 21:42 +0000
Message-ID<lf5hca$oqi$1@dont-email.me>
In reply to#41352
On 04/03/14 20:49, James Kuyper wrote:
> On 03/04/2014 03:18 PM, Robbie Brown wrote:
>> I have the following code

<snip>

> C function definitions can only occur at file scope (6.9p1). You can
> declare a function at block scope (6.8p2), but you can't define it
> there. Because you can't define it with block scope, I also personally
> feel it's a bad idea to declare it at file scope - but that's just a
> personal preference, not a C rule.
>
> If you got this code to compile (except for the part you're asking
> about), then you're taking advantage of a non-conforming extension to C
> which allows block scope definitions of functions.

I used gcc -std=c99 complexdecl.c and you are right. Apparently the 
ability to define a function within a function (nesting of functions) is 
a gcc extension, sheesh, you really gotta be on the ball with this stuff 
haven't you?

<snip>

> That's because you start out declaring an identifier named x to be a
> pointer to a function taking an argument of type int. Then you try to
> follow that up with the declaration of signal3. You can declare the name
> of a function and the names of it's arguments, but you can't declare a
> name for the value returned by that function. What you want to do is to
> declare signal3 as returning an UNNAMED pointer to a function taking one
> argument of type int.

<snip>

>> How do I code signal3 to completely get rid of my dependence on the
>> typedef. Once again, the only reason I want to do this is because I can
>> (hopefully)
>
> How do you make the pointer returned by signal3 unnamed? You have to use
> a type name, which syntactically looks just like the declaration of an
> identifier of a function or an object, except that it omits the identifier.
>
> 	void (*)(int) signal3(int x, void(*y)(int))

That was one of the first things I tried and for some reason that 
(obviously) escapes me it doesn't compile.

So, I simplified the code, now I have (with emacs line no's)

3.  void (*signal(int, void (*)(int)) ) (int);
4.
5.  void (*) (int) sig(int x, void (*y)(int) ){
6.    return  NULL;
7.  }
8.
9.  int main(void){
10.
11. }

I used gcc -std=c99 complexdecl.c

Compilation failed with
complexdecl.c:5:8: error: expected identifier or ‘(’ before ‘)’ token

5:8 is just after the leftmost ) in the definition.
Just for a laugh I tried with sig nested inside main and still failure.
I have also tried -std=gnu99 as I noticed that that can do some weird 
stuff.

Like I say, one of the first things I tried was
void (*) (int) sig(int x, void (*y)(int) ) and I was surprised
that it didn't compile.

Obviously I'm missing something here but I don't really know what to try 
next. Any ideas much appreciated.

Thanks


-- 
Rob - not floundering, fishing
========================================================
For every SCoP we generate the polyhedral representation
and transform it back to gimple.
========================================================
Seems perfectly reasonable to me.

[toc] | [prev] | [next] | [standalone]


#41358

FromKeith Thompson <kst-u@mib.org>
Date2014-03-04 14:04 -0800
Message-ID<lnob1lwrgy.fsf@nuthaus.mib.org>
In reply to#41356
Robbie Brown <dac@nomail.invalid> writes:
> On 04/03/14 20:49, James Kuyper wrote:
>> On 03/04/2014 03:18 PM, Robbie Brown wrote:
>>> I have the following code
>
> <snip>
>
>> C function definitions can only occur at file scope (6.9p1). You can
>> declare a function at block scope (6.8p2), but you can't define it
>> there. Because you can't define it with block scope, I also personally
>> feel it's a bad idea to declare it at file scope - but that's just a
>> personal preference, not a C rule.
>>
>> If you got this code to compile (except for the part you're asking
>> about), then you're taking advantage of a non-conforming extension to C
>> which allows block scope definitions of functions.
>
> I used gcc -std=c99 complexdecl.c and you are right. Apparently the 
> ability to define a function within a function (nesting of functions) is 
> a gcc extension, sheesh, you really gotta be on the ball with this stuff 
> haven't you?

Use "gcc -std=c99 -pedantic" to make it warn about violations of the C99
standard.  gcc is not a conforming C compiler without the "-pedantic"
option.  Use "-pedantic-warnings" to turn those warnings into fatal
errors.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#41371

FromRobbie Brown <dac@nomail.invalid>
Date2014-03-05 09:22 +0000
Message-ID<lf6qd4$m55$1@dont-email.me>
In reply to#41358
On 04/03/14 22:04, Keith Thompson wrote:
> Robbie Brown <dac@nomail.invalid> writes:
>> On 04/03/14 20:49, James Kuyper wrote:
>>> On 03/04/2014 03:18 PM, Robbie Brown wrote:
>>>> I have the following code

<snip>

> Use "gcc -std=c99 -pedantic" to make it warn about violations of the C99
> standard.  gcc is not a conforming C compiler without the "-pedantic"
> option.  Use "-pedantic-warnings" to turn those warnings into fatal
> errors.

OK, well my gcc doesn't support -pedantic-warnings.

However

-pedantic warns and still produces an executable
-pedantic-errors produces an error message and does not produce an 
executable, so I guess it's the same difference.

It's a bit of a minefield though isn't it?

Now I know there's no such thing but
Does the 'average C developer' actually need to know all this all the 
time or do people often/sometimes 'specialize' in a particular compiler 
implementation along with it's extensions?

Thanks for the reply


-- 
Rob - not floundering, fishing
========================================================
For every SCoP we generate the polyhedral representation
and transform it back to gimple.
========================================================
Seems perfectly reasonable to me.

[toc] | [prev] | [next] | [standalone]


#41375

FromJames Kuyper <jameskuyper@verizon.net>
Date2014-03-05 07:29 -0500
Message-ID<lf75b0$au$1@dont-email.me>
In reply to#41371
On 03/05/2014 04:22 AM, Robbie Brown wrote:
> On 04/03/14 22:04, Keith Thompson wrote:
>> Robbie Brown <dac@nomail.invalid> writes:
>>> On 04/03/14 20:49, James Kuyper wrote:
>>>> On 03/04/2014 03:18 PM, Robbie Brown wrote:
>>>>> I have the following code
> 
> <snip>
> 
>> Use "gcc -std=c99 -pedantic" to make it warn about violations of the C99
>> standard.  gcc is not a conforming C compiler without the "-pedantic"
>> option.  Use "-pedantic-warnings" to turn those warnings into fatal
>> errors.
> 
> OK, well my gcc doesn't support -pedantic-warnings.

I'm pretty sure that was a typo for -pedantic-errors

> However
> 
> -pedantic warns and still produces an executable
> -pedantic-errors produces an error message and does not produce an 
> executable, so I guess it's the same difference.

I don't usually bother with -pedantic-errors, but there is a real
benefit to using it:  if there is no executable, you can't be tempted to
try executing it.

> It's a bit of a minefield though isn't it?
> 
> Now I know there's no such thing but
> Does the 'average C developer' actually need to know all this all the 
> time or do people often/sometimes 'specialize' in a particular compiler 
> implementation along with it's extensions?

Most people specialize in some way - my personal choice was to
specialize in writing to the C standard, avoiding compiler-specific
extensions, but that's mainly because my company's client has imposed a
strong portability requirements on our code. You should be able to
compile and successfully execute our code on any system with sufficient
memory and disk space that supports POSIX (1003.1, IIRC) and C95. you
might have to make minor modifications to the make file, but you
shouldn't have to do anything to the source code to make it work. I
avoid even depending upon POSIX unless necessary. Some of my code relies
on POSIX's guarantee that CHAR_BIT == 8; but most of it would continue
to work properly even if that weren't true.

People writing code that has weaker portability requirements can and
usually do justify learning more about the quirks of a particular
compiler than I ever have.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#41382

FromKeith Thompson <kst-u@mib.org>
Date2014-03-05 08:38 -0800
Message-ID<lnk3c8wqfz.fsf@nuthaus.mib.org>
In reply to#41375
James Kuyper <jameskuyper@verizon.net> writes:
> On 03/05/2014 04:22 AM, Robbie Brown wrote:
>> On 04/03/14 22:04, Keith Thompson wrote:
[...]
>>> Use "gcc -std=c99 -pedantic" to make it warn about violations of the C99
>>> standard.  gcc is not a conforming C compiler without the "-pedantic"
>>> option.  Use "-pedantic-warnings" to turn those warnings into fatal
>>> errors.
>> 
>> OK, well my gcc doesn't support -pedantic-warnings.
>
> I'm pretty sure that was a typo for -pedantic-errors

Yes.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#41359

FromJames Kuyper <jameskuyper@verizon.net>
Date2014-03-04 17:05 -0500
Message-ID<53164E3B.3090800@verizon.net>
In reply to#41356
On 03/04/2014 04:42 PM, Robbie Brown wrote:
> On 04/03/14 20:49, James Kuyper wrote:
>> On 03/04/2014 03:18 PM, Robbie Brown wrote:
>>> I have the following code
> 
> <snip>
> 
>> C function definitions can only occur at file scope (6.9p1). You can
>> declare a function at block scope (6.8p2), but you can't define it
>> there. Because you can't define it with block scope, I also personally
>> feel it's a bad idea to declare it at file scope - but that's just a
>> personal preference, not a C rule.
>>
>> If you got this code to compile (except for the part you're asking
>> about), then you're taking advantage of a non-conforming extension to C
>> which allows block scope definitions of functions.
> 
> I used gcc -std=c99 complexdecl.c and you are right. Apparently the 
> ability to define a function within a function (nesting of functions) is 
> a gcc extension, sheesh, you really gotta be on the ball with this stuff 
> haven't you?

If you add "-pedantic" to "-std=c99", you will have eliminated most of
your dependence on gcc extensions, though I personally would recommend
adding "-Wall -Wpointer-arith -Wcast-align -Wstrict-prototypes
-Wmissing-prototypes" as well. Other people like to turn on several
additional warnings, particularly -Wextra, but I find a lot of those
warnings to be spurious.

> <snip>
> 
>> That's because you start out declaring an identifier named x to be a
>> pointer to a function taking an argument of type int. Then you try to
>> follow that up with the declaration of signal3. You can declare the name
>> of a function and the names of it's arguments, but you can't declare a
>> name for the value returned by that function.

<snip incorrect advice from my previous message, except for final
recommendation:>
...
>> 	void (*)(int) signal3(int x, void(*y)(int))
> 
> That was one of the first things I tried and for some reason that 
> (obviously) escapes me it doesn't compile.

That's because I managed to get confused during the process of
responding to you. I put a lot of effort into making that message
complete; I should have put a bit more effort into making it correct. A
simple test compile would have reminded me of my error, and I would have
known how to correct it, but I didn't do such a test.

Ben's answer is the correct one, and it renders irrelevant everything I
said about type names. It was all correct (I think), except for the part
about a type name being the answer to your problem. :-(

[toc] | [prev] | [next] | [standalone]


#41354

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2014-03-04 21:15 +0000
Message-ID<0.6deb784efb3a9c1024d1.20140304211557GMT.87txbdbr76.fsf@bsb.me.uk>
In reply to#41349
Robbie Brown <dac@nomail.invalid> writes:

> I have the following code
>
> /* declare signal as function (int, pointer to function (int)
> returning void) returning pointer to function (int) returning void */
>
> void (*signal(int, void (*)(int)) ) (int);
>
> /* simplify things a bit using a typedef */
> typedef void (*fptr)(int);
>
> int main(void){
>
>   /* declare and define function that takes int and returns void */
>   void foobar(int x){
>     printf("%s%d\n", "x in foobar is ", x);
>   }

Nested functions are an extension.  The fact that your code compiles
means you are not using the compiler in its strictest mode.  When you
are trying to understand things, it helps to get the compiler to tell
you as much a possible and using this extension prevents you from doing
that.

>   /* define signal using the typedef, compiles */
>   fptr signal(int x, fptr y){
>     return NULL;
>   }
>
>   /* What I'd like to do now is to replace the fptr typedef with the
>      pre typedef type if that makes sense.
>      Why?  because it helps my understanding */
>
>   /* Here I can say, void y(), void (y)(), void (*y)(), void y(int),
>      void(y)(int) void (*y)(int) for the second arg and they all
>      compile */
>
>   fptr signal2(int x, void (*y)(int) ){
>      NULL;
>   }
>
>   /* finally I want to do something like
>      return a pointer to a function taking int and returning void
>      but I just can't figure out how to do it. I've tried
>      void (*)(int), void (int), (void (*) (int)) etc etc without
>      success */
>
>   /* can't get this to compile in any way */
>   //void (*x) (int) signal3(int x, void (*y)(int) ){
>   //  return  NULL;
>   //}
>
> }
>
> How do I code signal3 to completely get rid of my dependence on the
> typedef. Once again, the only reason I want to do this is because I
> can (hopefully)

You gave the declaration of such a function right at the top of the post:

  void (*signal(int, void (*)(int)) ) (int);

To convert the declaration to a definition, give the parameters names
and replace the ';' with the function body.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#41355

From"BartC" <bc@freeuk.com>
Date2014-03-04 21:38 +0000
Message-ID<cKrRu.1365$k11.765@fx14.am4>
In reply to#41354
"Ben Bacarisse" <ben.usenet@bsb.me.uk> wrote in message
news:0.6deb784efb3a9c1024d1.20140304211557GMT.87txbdbr76.fsf@bsb.me.uk...
> Robbie Brown <dac@nomail.invalid> writes:

>> void (*signal(int, void (*)(int)) ) (int);

>> How do I code signal3 to completely get rid of my dependence on the
>> typedef. Once again, the only reason I want to do this is because I
>> can (hopefully)
>
> You gave the declaration of such a function right at the top of the post:
>
>  void (*signal(int, void (*)(int)) ) (int);
>
> To convert the declaration to a definition, give the parameters names
> and replace the ';' with the function body.

Which ones are the parameters?!

(I ran this with CDECL (http://www.lemoda.net/c/cdecl/index.cgi) which was
only mildly helpful, even after I varied the ints a bit so I could see which
was which.

I /think/ the first parameter name goes after the first int, and the second
one after the * in (*).)

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#41362

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2014-03-04 23:27 +0000
Message-ID<0.24a2a8577ef8e1bf655b.20140304232706GMT.87ob1lbl4l.fsf@bsb.me.uk>
In reply to#41355
"BartC" <bc@freeuk.com> writes:

> "Ben Bacarisse" <ben.usenet@bsb.me.uk> wrote in message
> news:0.6deb784efb3a9c1024d1.20140304211557GMT.87txbdbr76.fsf@bsb.me.uk...
>> Robbie Brown <dac@nomail.invalid> writes:
>
>>> void (*signal(int, void (*)(int)) ) (int);
>
>>> How do I code signal3 to completely get rid of my dependence on the
>>> typedef. Once again, the only reason I want to do this is because I
>>> can (hopefully)
>>
>> You gave the declaration of such a function right at the top of the post:
>>
>>  void (*signal(int, void (*)(int)) ) (int);
>>
>> To convert the declaration to a definition, give the parameters names
>> and replace the ';' with the function body.
>
> Which ones are the parameters?!

  void (*signal(int signum, void (*newaction)(int)) ) (int);

> (I ran this with CDECL (http://www.lemoda.net/c/cdecl/index.cgi) which was
> only mildly helpful, even after I varied the ints a bit so I could see which
> was which.
>
> I /think/ the first parameter name goes after the first int, and the second
> one after the * in (*).)

Yes.  How can one tell?  Well, signal is a function because its name is
followed by an (.  That ( starts the comma separated list of parameters
that ends with the matching ).  I.e. this is the parameter list:

  int, void (*)(int)

It's clear where the first name goes.  The second is a little harder but
we know it's a pointer parameter and pointer types always have a * to
the immediate left of the name.  There's only one place to put a name so
that it has a * immediately on to the left.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#41357

FromRobbie Brown <dac@nomail.invalid>
Date2014-03-04 21:59 +0000
Message-ID<lf5ic0$9q$1@dont-email.me>
In reply to#41354
On 04/03/14 21:15, Ben Bacarisse wrote:
> Robbie Brown <dac@nomail.invalid> writes:
>
>> I have the following code
>>
>> /* declare signal as function (int, pointer to function (int)
>> returning void) returning pointer to function (int) returning void */
>>
>> void (*signal(int, void (*)(int)) ) (int);
>>
>> /* simplify things a bit using a typedef */
>> typedef void (*fptr)(int);
>>
>> int main(void){
>>
>>    /* declare and define function that takes int and returns void */
>>    void foobar(int x){
>>      printf("%s%d\n", "x in foobar is ", x);
>>    }
>
> Nested functions are an extension.  The fact that your code compiles
> means you are not using the compiler in its strictest mode.  When you
> are trying to understand things, it helps to get the compiler to tell
> you as much a possible and using this extension prevents you from doing
> that.
>
>>    /* define signal using the typedef, compiles */
>>    fptr signal(int x, fptr y){
>>      return NULL;
>>    }
>>
>>    /* What I'd like to do now is to replace the fptr typedef with the
>>       pre typedef type if that makes sense.
>>       Why?  because it helps my understanding */
>>
>>    /* Here I can say, void y(), void (y)(), void (*y)(), void y(int),
>>       void(y)(int) void (*y)(int) for the second arg and they all
>>       compile */
>>
>>    fptr signal2(int x, void (*y)(int) ){
>>       NULL;
>>    }
>>
>>    /* finally I want to do something like
>>       return a pointer to a function taking int and returning void
>>       but I just can't figure out how to do it. I've tried
>>       void (*)(int), void (int), (void (*) (int)) etc etc without
>>       success */
>>
>>    /* can't get this to compile in any way */
>>    //void (*x) (int) signal3(int x, void (*y)(int) ){
>>    //  return  NULL;
>>    //}
>>
>> }
>>
>> How do I code signal3 to completely get rid of my dependence on the
>> typedef. Once again, the only reason I want to do this is because I
>> can (hopefully)
>
> You gave the declaration of such a function right at the top of the post:
>
>    void (*signal(int, void (*)(int)) ) (int);
>
> To convert the declaration to a definition, give the parameters names
> and replace the ';' with the function body.


OK, I did this and ... it compiles, now my brain hurts

void (*signal(int x, void (*i)(int y)) ) (int z){
   return NULL;
}

I just can't see how the above and

typedef void (*fptr)(int);

fptr signal (int x, fptr);

which also compiles are equivalent

What a headbanger.


-- 
Rob - not floundering, fishing
========================================================
For every SCoP we generate the polyhedral representation
and transform it back to gimple.
========================================================
Seems perfectly reasonable to me.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web