Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > would C be easier to read if...

Reply
Thread Tools

would C be easier to read if...

 
 
Bartc
Guest
Posts: n/a
 
      04-03-2008

"Robert Smith" <(E-Mail Removed)> wrote in message
news:rd5Jj.5608$(E-Mail Removed)...
> some of the syntax wasn't overloaded so much...
>
> Was just musing that if pointer de-referencing and pointer-to-type had
> seperate syntax (ie use a character other than '*' for one of them) it
> would make things much easier to read. You wouldn't get stuff like:
>
> pthread_create(&thread, NULL, (void *(*)(void*))ThreadProc, (void
> *)parameter);


I've got more serious problems with understanding C declarations, for
example:

What on earth does (void *(*)(void*)) mean? It's some sort of cast, so the
type is:

void *(*)(void*)

My guess is it's a function returning type void*, and maybe taking a single
parameter of void*, but what about the (*) in the middle?!

And * does apparently seem to change position. Unless I've got these wrong:

int *a a is pointer to int (* on left)
(int *) pointer to int (* on right)
*a dereference pointer to int (* on left again).

In my case a type declaration that reads linearly from left to right would
help tremendously, because that's what I'm familiar with. Just having the
word 'function' in a function declaration would make things so much clearer!

Maybe C's syntax will get easier with use, I don't know, but since I stay
well clear of anything complicated, probably not.

--
Bart



 
Reply With Quote
 
 
 
 
Ben Pfaff
Guest
Posts: n/a
 
      04-03-2008
"Bartc" <(E-Mail Removed)> writes:

> What on earth does (void *(*)(void*)) mean? It's some sort of cast, so the
> type is:
>
> void *(*)(void*)
>
> My guess is it's a function returning type void*, and maybe taking a single
> parameter of void*, but what about the (*) in the middle?!


That means it's a pointer to a function. The full type is
"pointer to function taking a void * argument and returning void
*".

> And * does apparently seem to change position. Unless I've got these wrong:
>
> int *a a is pointer to int (* on left)


OK.

> (int *) pointer to int (* on right)


That's not a type or a declaration. It's a cast. In a cast,
there is no variable to name, so "a" is omitted. If there was a
variable there, it would be in the same position.

There is one situation where the variable name may be included or
omitted, at your option, and that is in a function prototype (that
is not for a function being defined). So the following are
equivalent, and may be enlightening:
void foo(int *a);
void foo(int *);
See? The variable name is just omitted, and there's no changing
of position going on.
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      04-03-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> On Apr 3, 6:47 pm, Hallvard B Furuseth <(E-Mail Removed)>
> wrote:
>> (E-Mail Removed) writes:
>>> On Apr 3, 6:17 pm, Hallvard B Furuseth <(E-Mail Removed)> wrote:
>>>>> Even if parameter was const char * const parameter = "hello world";
>>>>> the cast can still be omitted, as long as ThreadProc does not try to
>>>>> mutate what is pointed to by parameter.
>>>> No. pthread_create() takes a void* 3rd parameter. It's an error
>>>> to assign or pass a "pointer to const" to a "pointer to not-const".
>>> I don't remember what the POSIX standard says about this, but in C it
>>> is not.

>> You are confusing something with something. Half the purpose of the
>> const qualifier is that the compiler's type checking can help you catch
>> assignments to read-only objects.

> Well, that's *your* opinion. My opinion is that const is there for
> optimization and documentation.


Well most compilers would agree with Hallvard and not with you.

Passing a const pointer to a function with a void* parameter is a
constraint violation and the compiler should issue a diagnostic.

> Ie foo(const int *) informs the programmer foo shall not modify what
> is pointed to by its argument.


True, and foo( int* ) offers no such guarantee, so passing a const int*
to foo risks foo attempting to modify the data pointer to.

>>> (...) what I demonstrate here is a function taking void *, and
>>> passing to that function a const char * const.


>> void* isn't that magical. You can pass a char* to a void* or
>> a const char* to a const void*. Not a const char* to a void*.


> That is not true, and it's not about void *'s "magic". You can also
> assign a const char * to a char * and still have a conforming program.


No, you have a constraint violation.

> Also, while thinking about it, pthread_create shouldn't be able to
> access what is pointed to by its last argument. Unless POSIX says
> something about it (and I'm positive it does not) then it's POSIX
> conforming too.
>

Nonsense, what's the point in a parameter a function can't access? Even
is there was one, how could it be enforced?

--
Ian Collins.
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      04-03-2008
Hallvard B Furuseth wrote:
> Chris Dollin writes:
>> Robert Smith wrote:
>>> pthread_create(&thread, NULL, (void *(*)(void*))ThreadProc, (void
>>> *)parameter);

>> Surely either `ThreadProc` is already the right type, in which case
>> the cast can and should be discarded, or it isn't, in which case
>> the cast is a bug waiting to manifest and `ThreadProc` should be
>> fixed.
>>
>> Yes?

>
> And hopefully 'parameter' is a non-const pointer so the void* cast
> can be dropped too.
>
> The times where you do need to clutter the code with unreadable
> type casts, it may make sense to typedef the offending type.
>

No, all the typedef dose is introduce an alias, it doesn't remove the
need to cast an inappropriate type.

If you do need to clutter the code with unreadable casts, you are doing
something smelly and should reconsider what you are doing.

--
Ian Collins.
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      04-03-2008
Robert Smith wrote:
> some of the syntax wasn't overloaded so much...
>
> Was just musing that if pointer de-referencing and pointer-to-type had
> seperate syntax (ie use a character other than '*' for one of them) it would
> make things much easier to read. You wouldn't get stuff like:
>
> pthread_create(&thread, NULL, (void *(*)(void*))ThreadProc, (void
> *)parameter);
>

It has already been pointed out that the casts are a smell, but even if
they were required, C provides typedefs to alias complex type declarations.

It's a shame typedefs aren't used more often for function pointer types
in standards. It would make complex function declarations (signal is a
classic) much easier for a human to parse.

--
Ian Collins.
 
Reply With Quote
 
Kenneth Brody
Guest
Posts: n/a
 
      04-03-2008
Robert Smith wrote:
>
> some of the syntax wasn't overloaded so much...
>
> Was just musing that if pointer de-referencing and pointer-to-type had
> seperate syntax (ie use a character other than '*' for one of them) it would
> make things much easier to read. You wouldn't get stuff like:
>
> pthread_create(&thread, NULL, (void *(*)(void*))ThreadProc, (void
> *)parameter);


Aside from what the others said, consider this:

char *p;

The use of "*" is consistent, IMO, because:

"p" is of type "char *", just like the definition says, and
"*p" is of type "char", just like the definition says.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <(E-Mail Removed)>

 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      04-03-2008
(E-Mail Removed) wrote:
>

.... snip ...
>
> Here's a perfectly conforming C99 program
>
> #include <stdio.h>
> int foo(void *);
> int main(void) {
> const char * const p = "hello world";
> foo(p);
> return 0;
> }
> int foo(void *p) { return puts(p); }


And here is one with one less line, no requirements for exact line
equivalence, and much more understandable, especially to the
neophyte.

#include <stdio.h>

int foo(void *p) { return puts(p); }

int main(void) {
char *p = "hello world";

foo(p);
return 0;
}

I also added blank lines to separate code segments. I didn't
install 'static' qualifiers.

I thought I had eliminated all possible warning, but I got:

junk.c:6: warning: initialization discards qualifiers from pointer
target type

and I am confused. Why? gcc is run through an alias for cc:

alias cc=gcc -W -Wall -ansi -pedantic -Wwrite-strings -Wfloat-equal
-gstabs+ -ftrapv -O1

(I suspect the -Wwrite-strings param).

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.



--
Posted via a free Usenet account from http://www.teranews.com

 
Reply With Quote
 
Bartc
Guest
Posts: n/a
 
      04-03-2008

"Ben Pfaff" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> "Bartc" <(E-Mail Removed)> writes:
>
>> What on earth does (void *(*)(void*)) mean? It's some sort of cast, so
>> the
>> type is:
>>
>> void *(*)(void*)
>>
>> My guess is it's a function returning type void*, and maybe taking a
>> single
>> parameter of void*, but what about the (*) in the middle?!

>
> That means it's a pointer to a function. The full type is
> "pointer to function taking a void * argument and returning void
> *".


OK thanks.

>> And * does apparently seem to change position. Unless I've got these
>> wrong:
>> int *a a is pointer to int (* on left)

>
> OK.
>
>> (int *) pointer to int (* on right)

>
> That's not a type or a declaration. It's a cast. In a cast,
> there is no variable to name, so "a" is omitted. If there was a
> variable there, it would be in the same position.


I agree that the type-declaration scheme /is/ logical when you analyse it,
it's just difficult to read! Being adept at it does not change that.

While we're in this fantasy thread, I knocked up this new left-to-right
easy-to-read syntax for C type declarations. Type-decls are constructed with
the following symbols (enums and some other stuff left out):

* Pointer to
type Type name (built-in or typedef-ed)
function Optional function indicator
(...)T Function Takes these params, returns type T
[] Array of
[N] Array of N of
struct{...} Struct of
struct S{...} Struct S of

These are written left to right, example:

*int a,b; a,b are both pointers to int
function(int,int)float Function taking two int params and returning float
result
(int,int)float Same without the 'function'
[10]char s,t s,t are both 10-char arrays
[10]*char list Array of pointers to char (array of strings)
*function(*void)*void Above example
*(*void)*void Above example without 'function'

Pros:
* Easy to read, translates naturally to English
* Variables sharing same array/pointer properties share the one type-decl(as
in above examples)
* The typedef T U statement, in practice may have T and U hopelessly
intermingled for complex type-decls. With this scheme T and U stay separate.
* Also type-decls appear in typedefs, var-decls, casts, and function params
all have the same form

Cons:
* Can't mix declaration of variables that have different array/pointer
attributes (but I think that's a bad idea anyway).

--
Bart



 
Reply With Quote
 
christian.bau
Guest
Posts: n/a
 
      04-03-2008
On Apr 3, 4:56*pm, (E-Mail Removed) wrote:

> Well, that's *your* opinion. My opinion is that const is there for
> optimization and documentation.


"Const" cannot be used for optimization purposes at all. Your code
either modifies objects, or it doesn't. The compiler doesn't need
const qualifiers to see that. But a const qualifier on a pointer does
_not_ in any way whatsoever guarantee or indicate the the object is
not modified in some other way.

The situation is completely different if you use a "const restrict"
pointer in C99.
 
Reply With Quote
 
Default User
Guest
Posts: n/a
 
      04-03-2008
CBFalconer wrote:

> (E-Mail Removed) wrote:
> >

> ... snip ...
> >
> > Here's a perfectly conforming C99 program
> >
> > #include <stdio.h>
> > int foo(void *);
> > int main(void) {
> > const char * const p = "hello world";
> > foo(p);
> > return 0;
> > }
> > int foo(void *p) { return puts(p); }

>
> And here is one with one less line, no requirements for exact line
> equivalence, and much more understandable, especially to the
> neophyte.
>
> #include <stdio.h>
>
> int foo(void *p) { return puts(p); }
>
> int main(void) {
> char *p = "hello world";
>
> foo(p);
> return 0;
> }
>
> I also added blank lines to separate code segments. I didn't
> install 'static' qualifiers.
>
> I thought I had eliminated all possible warning, but I got:
>
> junk.c:6: warning: initialization discards qualifiers from pointer
> target type
>
> and I am confused. Why? gcc is run through an alias for cc:
>
> alias cc=gcc -W -Wall -ansi -pedantic -Wwrite-strings -Wfloat-equal
> -gstabs+ -ftrapv -O1
>
> (I suspect the -Wwrite-strings param).


I suspect you are right.

-Wwrite-strings
When compiling C, give string constants the type "const
char[length]" so that copying the address of one into a
non-"const" "char *" pointer will get a warning; when
compiling C++, warn about the deprecated conversion from
string constants to "char *". These warnings will help
you find at compile time code that can try to write into
a string constant, but only if you have been very
careful about using "const" in declarations and
prototypes. Otherwise, it will just be a nuisance; this
is why we did not make -Wall request these warnings.



Brian
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
an oddball scary kind of thing you would think would never happen richard Computer Support 4 01-31-2010 06:34 PM
read a ruby script like you would read a text file Mmcolli00 Mom Ruby 2 01-27-2009 10:52 PM
Has to be an easier way? (gateway issues) Captain Cisco 13 08-28-2004 12:30 AM
Hash of Structs in a Package, is there an easier way? Norman Ackroyd Perl 1 07-28-2004 11:54 AM
Phone Validation Problem (I reformatted the code to make it easier to read) AnnMarie Javascript 8 11-21-2003 10:37 PM



Advertisments