int/unsigned long * idiocy

  • Thread starter Christopher Benson-Manica
  • Start date
C

Christopher Benson-Manica

I have, in a certain unnamed header file, the following:

#define PIPE_WAIT 0x00000000
#define PIPE_NOWAIT 0x00000001

and a function that the compiler believes has the following prototype:

__stdcall SetNamedPipeHandleState(void *,unsigned long *,
unsigned long *,unsigned long *); /* nonstandard calling convention */

The (unnamed) compiler is perfectly happy with

SetNamedPipeHandleState( NULL, PIPE_WAIT, NULL, NULL );

but has a temper tantrum over

SetNamedPipeHandleState( NULL, PIPE_NOWAIT, NULL, NULL );

(both of which should be valid according to a certain unnamed website)

Of course, what's happening here is clear (0x00000000 is NULL, and
thus compatible with unsigned long *, while 0x00000001 is not). This
isn't really a question, but just a humorous look at how much fun
dealing with this unnamed setup can be. Comments are, of course,
welcome.
 
D

Dan Pop

In said:
I have, in a certain unnamed header file, the following:

#define PIPE_WAIT 0x00000000
#define PIPE_NOWAIT 0x00000001

and a function that the compiler believes has the following prototype:

__stdcall SetNamedPipeHandleState(void *,unsigned long *,
unsigned long *,unsigned long *); /* nonstandard calling convention */

The (unnamed) compiler is perfectly happy with

SetNamedPipeHandleState( NULL, PIPE_WAIT, NULL, NULL );

but has a temper tantrum over

SetNamedPipeHandleState( NULL, PIPE_NOWAIT, NULL, NULL );

(both of which should be valid according to a certain unnamed website)

Of course, what's happening here is clear (0x00000000 is NULL, and
thus compatible with unsigned long *, while 0x00000001 is not). This
isn't really a question, but just a humorous look at how much fun
dealing with this unnamed setup can be. Comments are, of course,
welcome.

The implementor, obviously, never tried to see if PIPE_NOWAIT works.
Why should he bother, when the customers can do the job, as well? ;-)

Dan
 
N

nrk

Christopher said:
I have, in a certain unnamed header file, the following:

#define PIPE_WAIT 0x00000000
#define PIPE_NOWAIT 0x00000001

and a function that the compiler believes has the following prototype:

__stdcall SetNamedPipeHandleState(void *,unsigned long *,
unsigned long *,unsigned long *); /* nonstandard calling convention */

The (unnamed) compiler is perfectly happy with

SetNamedPipeHandleState( NULL, PIPE_WAIT, NULL, NULL );

but has a temper tantrum over

SetNamedPipeHandleState( NULL, PIPE_NOWAIT, NULL, NULL );

(both of which should be valid according to a certain unnamed website)

Of course, what's happening here is clear (0x00000000 is NULL, and
thus compatible with unsigned long *, while 0x00000001 is not). This
isn't really a question, but just a humorous look at how much fun
dealing with this unnamed setup can be. Comments are, of course,
welcome.

It is quite obvious which platform/setup you're talking about. It is
equally clear that you've either:
a) Misread the documentation
or
b) Read documentation that is out of date or incorrect.

http://msdn.microsoft.com/library/d...ry/en-us/ipc/base/setnamedpipehandlestate.asp

Reading that seems to indicate that you need a local unsigned long (or
better yet, DWORD) that can contain the constants defined. It is not
explicitly mentioned, but it is quite clear what is expected. The notation
says LPDWORD is long pointer to double word. Further, even if the
documentation was unclear, the provided example is crystal clear on this
issue. It is also clear from the documentation that you would bitwise or
constants from the two tables to achieve combinations of read and blocking
modes.

This is quite normal with many such system calls that take flags (for
instance, open, creat, fcntl etc.). Even if the documentation was
incorrect, this much can be reasonably inferred by someone with more than a
passing familiarity with C and the system in question.

-nrk.
 
E

Erik de Castro Lopo

Christopher said:
I have, in a certain unnamed header file, the following:

#define PIPE_WAIT 0x00000000
#define PIPE_NOWAIT 0x00000001

and a function that the compiler believes has the following prototype:

__stdcall SetNamedPipeHandleState(void *,unsigned long *,
unsigned long *,unsigned long *); /* nonstandard calling convention */

The (unnamed) compiler is perfectly happy with

SetNamedPipeHandleState( NULL, PIPE_WAIT, NULL, NULL );

but has a temper tantrum over

SetNamedPipeHandleState( NULL, PIPE_NOWAIT, NULL, NULL );

(both of which should be valid according to a certain unnamed website)

Proof yet again that said unamed company has a room full
of monkeys sitting in front of computers.

Erik
--
+-----------------------------------------------------------+
Erik de Castro Lopo (e-mail address removed) (Yes it's valid)
+-----------------------------------------------------------+
From Time magazine, "Numbers" section:
$5 million: Estimated annual cost for a 10-year program that
would identify large asteroids most threatening
to earth.
$75 million: Budget for "Deep Impact", a film about the
devastation caused when a comet hits earth.
 
B

Ben Pfaff

Christopher Benson-Manica said:
I have, in a certain unnamed header file, the following:

#define PIPE_WAIT 0x00000000
#define PIPE_NOWAIT 0x00000001

and a function that the compiler believes has the following prototype:

__stdcall SetNamedPipeHandleState(void *,unsigned long *,
unsigned long *,unsigned long *); /* nonstandard calling convention */

The (unnamed) compiler is perfectly happy with

SetNamedPipeHandleState( NULL, PIPE_WAIT, NULL, NULL );

but has a temper tantrum over

SetNamedPipeHandleState( NULL, PIPE_NOWAIT, NULL, NULL );

As I read the unnamed website, the proper invocation is roughly
unsigned long mode = PIPE_(NO)WAIT;
SetNamedPipeHandleState(..., &mode, ...);
 
C

Christopher Benson-Manica

Ben Pfaff said:
As I read the unnamed website, the proper invocation is roughly
unsigned long mode = PIPE_(NO)WAIT;
SetNamedPipeHandleState(..., &mode, ...);

I guess the "big" thing to do is to admit that I'm a moron, although I
still find that invocation to be annoying. Oh well.
 
R

Robert Wessel

Christopher Benson-Manica said:
I have, in a certain unnamed header file, the following:

#define PIPE_WAIT 0x00000000
#define PIPE_NOWAIT 0x00000001

and a function that the compiler believes has the following prototype:

__stdcall SetNamedPipeHandleState(void *,unsigned long *,
unsigned long *,unsigned long *); /* nonstandard calling convention */

The (unnamed) compiler is perfectly happy with

SetNamedPipeHandleState( NULL, PIPE_WAIT, NULL, NULL );

but has a temper tantrum over

SetNamedPipeHandleState( NULL, PIPE_NOWAIT, NULL, NULL );

(both of which should be valid according to a certain unnamed website)

Of course, what's happening here is clear (0x00000000 is NULL, and
thus compatible with unsigned long *, while 0x00000001 is not). This
isn't really a question, but just a humorous look at how much fun
dealing with this unnamed setup can be. Comments are, of course,
welcome.


I'm baffled. You're misusing the function (the function really does
take pointers to DWORDs, aka unsigned longs, not the values directly),
and you're complaining that you get a compilation error? Or are you
complaining that MS choose to use zero as one of the PIPE_xxxx
constants?
 
A

anony*mouse

Of course, what's happening here is clear (0x00000000 is NULL, and
thus compatible with unsigned long *, while 0x00000001 is not).

Surprisingly enough, MSVC does accept 0 or even 0L as NULL in C
language code. I wonder how common this is in other implementations.
It is not accepted in LCC-WIN32. What are peoples' preferences on
this? Should zero be accepted as NULL?

Sample code is provided in a link from the doc page for the specified
function.
Note that PIPE_NOWAIT is obsolete and should not be used. Use
overlapped IO instead. A read mode must also be provided.

Code:
   dwMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; 
   fSuccess = SetNamedPipeHandleState( 
      hPipe,    // pipe handle 
      &dwMode,  // new pipe mode 
      NULL,     // don't set maximum bytes 
      NULL);    // don't set maximum time
 
P

pete

anony*mouse said:
Surprisingly enough, MSVC does accept 0 or even 0L as NULL in C
language code. I wonder how common this is in other implementations.
It is not accepted in LCC-WIN32. What are peoples' preferences on
this? Should zero be accepted as NULL?

A constant with integer type and zero value,
is a null pointer constant.
When zero is used in a pointer context, zero equals NULL.
The type of NULL may be either (void*) or any integer type.
 
R

Richard Bos

Surprisingly enough, MSVC does accept 0 or even 0L as NULL in C
language code.

No kidding.
I wonder how common this is in other implementations.

It should be 100% common, since it is correct.
It is not accepted in LCC-WIN32.

Then LCC-WIN32 is not a C implementation, the way you used it.
What are peoples' preferences on
this? Should zero be accepted as NULL?

Preferences are immaterial. The Standard demands that any integral
constant with value 0 is a null pointer constant, and therefore a
correct definition of NULL.

Richard
 
P

pete

pete said:
A constant with integer type and zero value,
is a null pointer constant.
When zero is used in a pointer context, zero equals NULL.

That's for constants only. An integer object with value zero,
is not a null pointer constant,
and has no meaning in a pointer context.
 
D

Dan Pop

In said:
Surprisingly enough, MSVC does accept 0 or even 0L as NULL in C
language code. I wonder how common this is in other implementations.

It is required by the C standard.
It is not accepted in LCC-WIN32.

Then, this compiler is broken.
What are peoples' preferences on this? Should zero be accepted as NULL?

It shouldn't, but since the C standard says otherwise, our preferences
don't matter.

The right thing would be to introduce the __null (or _Null) keyword
as the *only* null pointer constant and require than NULL expands
to it. This won't break any properly written C code, that *always*
uses NULL when it needs a null pointer constant.

If such a change would be ever made, a two step approach will be needed:
C0x would introduce __null and deprecate all the other null pointer
constants. C1x could then remove all the other null pointer constants,
thus giving people plenty of time to fix their code.

Dan
 
D

Dan Pop

In said:
This is quite normal with many such system calls that take flags (for
instance, open, creat, fcntl etc.).

Except that these functions don't take pointers to flags, they just take
the flags. I have yet to figure a good reason for requiring a pointer
to flags, unless the function is supposed to modify the user specified
flags (which would be really weird, as an API design).

Dan
 
N

nrk

Dan said:
In <[email protected]> nrk


Except that these functions don't take pointers to flags, they just take
the flags. I have yet to figure a good reason for requiring a pointer
to flags, unless the function is supposed to modify the user specified
flags (which would be really weird, as an API design).

You're right, that is a difference. I believe that the function in question
has a counterpart Get* function that needs a pointer. Maybe they just used
a pointer for the Set* as well just for symmetry in the API (not saying its
good design, just giving a possible reason). It might also be possible
(though unlikely) that the flag is modified by the Set* function.
 
A

anony*mouse

It is not accepted in LCC-WIN32.

RETRACTION: Yes it is. Apologies to the defamed. My mistake.

I always thought that the 0 == NULL 'feature' was a product of C++ as
I commonly see C++ code that uses 0 in place of NULL(very ugly), while
I can't remember ever seeing this in C code.
 
D

Dan Pop

In said:
I always thought that the 0 == NULL 'feature' was a product of C++ as
I commonly see C++ code that uses 0 in place of NULL(very ugly), while
I can't remember ever seeing this in C code.

0 as the null pointer constant originated in C. Because it was ugly, it
was hidden behind the NULL macro. C++ inherited it from C. Then, the
C89 standard introduced a second null pointer constant to C, (void *)0.
This one was never adopted by C++.

Well written C code always uses NULL, because it expresses the
programmer's intentions better than any explicit null pointer constant.
After all, this is why this macro was introduced in the first place.

Dan
 
A

Arthur J. O'Dwyer

0 as the null pointer constant originated in C. Because it was ugly, it
was hidden behind the NULL macro. C++ inherited it from C. Then, the
C89 standard introduced a second null pointer constant to C, (void *)0.

I know that what you said is literally true, and the Standard
supports (void*)0 as a "second" null pointer constant, but really
it's just a corollary of the fact that 0 is a null pointer constant.
In C, (void*) can be implicitly converted to any other pointer type,
so (void*)0 and 0 are exactly interchangeable in pointer contexts.
This one was never adopted by C++.

In C++, (void*) cannot be implicitly converted to any other type,
so (void*)0 and 0 are not interchangeable in pointer contexts.

There's no magic going on with (void*)0's being a null pointer
constant; it's just a consequence of the C type system. And it's
not like C++ "decided" not to make (void*)0 equivalent to NULL;
that's just a consequence of the C++ type system.

-Arthur
 
J

Jeremy Yallop

Arthur said:
In C++, (void*) cannot be implicitly converted to any other type,
so (void*)0 and 0 are not interchangeable in pointer contexts.

The first part is true, but that in itself is not a sufficient reason
for dropping (void *)0 as a null pointer constant in C++. Pointer to
void is not implicitly convertible to function pointer types in C, but

void (*f)() = (void *)0;

is valid C code.
There's no magic going on with (void*)0's being a null pointer
constant; it's just a consequence of the C type system.

For the most part that's true, but function pointers are a special
case.

Jeremy.
 
A

Arthur J. O'Dwyer

The first part is true, but that in itself is not a sufficient reason
for dropping (void *)0 as a null pointer constant in C++.
void (*f)() = (void *)0;

Oops! Thanks; I'll try to remember that in future. (Gee, that's
a weird aspect of C... ;-)

-Arthur
 
D

Dan Pop

I know that what you said is literally true, and the Standard
supports (void*)0 as a "second" null pointer constant, but really
it's just a corollary of the fact that 0 is a null pointer constant.

Nope, it isn't.
In C, (void*) can be implicitly converted to any other pointer type,
so (void*)0 and 0 are exactly interchangeable in pointer contexts.

Nope, they aren't: the result of converting an integer to a pointer is
*implementation-defined*, so, a priori, (void*)0 can be *anything*. Its
special semantics come *exclusively* from its *explicit* inclusion in the
definition of the null pointer constant.

Dan
 

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,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top