printf() error with long double and null pointer.

F

fieldfallow

Richard said:
fieldfallow said:
Yes. Even after commenting out the first printf(), I still get the same
wrong output.

It does that for me, too[0]. When I remove the references to long
doubles in the printf(), it prints the expected[1] value for v_p, too.
It appears at first glance that gcc and the MinGW library are not in
accord over the size of a long double. How pernicious.

Try this: print (using sizeof) the size of your double and long double.

Output is:
sizeof (double) == 8
sizeof (long double) == 12
Dev-C++ on this computer says 8 and 12, respectively. But the headers
claim that long double is the same as double, and all values in
<float.h> for LDBL_* are the same as for DBL_*. Presumably, *printf()
assume that sizeof (double) == sizeof (long double), too.

Well, I use MinGW from the command line. The float.h in the main include
directory includes MS specific extensions and 'include_next' the ISO
float.h from 'lib/gcc/mingw32/3.4.5/include' directory. For me, the
relevant values are given as:
/* Maximum representable finite floating-point number,

(1 - b**-p) * b**emax
*/
#undef FLT_MAX
#undef DBL_MAX
#undef LDBL_MAX
#define FLT_MAX __FLT_MAX__
#define DBL_MAX __DBL_MAX__
#define LDBL_MAX __LDBL_MAX__

<<<<<<<<<<<<<
Anyone know the right channel to report this to MinGW?

Richard

There are probably mailing-lists for submitting bug reports on the MinGW
website.

Thanks for your help.
 
R

Richard G. Riley

In code. Nowhere else. Not in memory; not in output. NULL is a null
pointer constant, _not_ a null pointer object. (And note that that
question does talk about what the programmer should use in his code, not
about anything else.)


Very common, but also wrong.

Would you agree that a "null pointer" had a value of NULL? Possibly
I'm missing something here or giving the OP too much of the benefit of
the doubt.



Richard.
 
P

pete

Richard said:
Would you agree that a "null pointer" had a value of NULL?

I wouldn't disagree.
I would say that a null pointer compares equal to NULL.
I would say that a null pointer compares equal to zero.

But these kinds of comparisons invlove conversions,
and when comparisons involve conversions,
then equivalence becomes context dependant.

if (0 > -1 && -1 > 0u && 0 == 0u) {
puts("If one constant compares greater than -1"
"and another compares less than -1,"
"can they have the same value?");
}
 
R

Richard G. Riley

I wouldn't disagree.
I would say that a null pointer compares equal to NULL.
I would say that a null pointer compares equal to zero.

And I would agree with your statements. In the same way I would say
that "1 compares equal to an int holding 1".

Does the compiler possibly cover up internal representations in these
cases too or do the standards limit it to pointers? Keeping in mind we
are talking C and not some higher level overloaded language.
But these kinds of comparisons invlove conversions,
and when comparisons involve conversions,
then equivalence becomes context dependant.

if (0 > -1 && -1 > 0u && 0 == 0u) {
puts("If one constant compares greater than -1"
"and another compares less than -1,"
"can they have the same value?");
}

http://c-faq.com/null/confusion4.html

... is a good description of how the NULL pointer might actually be
represented "out of code". The main issue, to my mind, is the
potential for a NULL pointer to hold a bit to raise HW
exceptions. Makes sense.

I assume the the compiler is smart enough to guess at ptr==NULL for
the following?

if(!ptr){
...
}

Or is that taking liberties?
 
A

A. Sinan Unur

Which part?

Start from 5.1, continue until 5.20. The null pointer FAQs are organized
very well, starting with the definition, and answering each question in a
way that builds on the previous discussion.

Sinan
 
P

pete

Richard G. Riley wrote:
http://c-faq.com/null/confusion4.html

.. is a good description of how the NULL pointer might actually be
represented "out of code". The main issue, to my mind, is the
potential for a NULL pointer to hold a bit to raise HW
exceptions. Makes sense.

I assume the the compiler is smart enough to guess at ptr==NULL for
the following?

Yes.
if(!ptr){
..
}

Or is that taking liberties?

No.

(!(a)) means exactly the same thing as ((a) == 0)
no matter what type (a) is.

In a pointer context,
((ptr) == 0) means exactly the same thing as ((ptr) == NULL)
 
J

Jordan Abel

For uninitialised objects,
you can only portably do operations which don't access the values.
That's pretty much limited to having the variables be
operands of the address operator and or the sizeof operator.

and the assignment operator.

and va_start() and va_copy() (macros which presumably invoke the
assignment operator)
 
R

Richard G. Riley

Start from 5.1, continue until 5.20. The null pointer FAQs are organized
very well, starting with the definition, and answering each question in a
way that builds on the previous discussion.

Sinan


Firstly, I'm not trying to be purposefully counter productive
here. But I am confused as to your answer : especially when the OPs
problem was correctly disgnosed elsewhere as nothing to do with the
pointer value.

How would you disagree that the NULL pointer has a value of 0 for the
purposes of comparison and display? Which is what the OP asked and to
suggest he is wrong on this is a misleading thing in the context of
his problems isnt it?

It was very explicit that NULL and 0 are the same in the context of
pointers and comparisons. Note this is different to internal
representation as covered in other posts in the thread.

But anyhwere else that a NULL pointer is used in terms of being used
for mathematical manipulation of any time its value is 0.

Isn't it?

Have I tied myself up in knots here? Possibly.
 
J

Jordan Abel

It does.


You're welcome.

One reason that we obsess about undefined behavior in code here,
is that sometimes the effects are not where you expect to see them,
somewhat similarly to the way that the long double problem
affected the void pointer output.

I realise that this was not
a case of code containing undefined behavior,
but rather a case of it being the implementation's fault.

Probably in this case it's more mingw's fault than the printf
implementation's fault - for not using the same calling convention for
variadic functions [or perhaps any function at all] that take an
argument of long double type as windows natively uses. When using an
imlpementation built from pieces written by different groups of people,
and pieces which are themselves compiled on different implementations,
there is always a possibility of something like this.
 
J

Jordan Abel

Firstly, I'm not trying to be purposefully counter productive
here. But I am confused as to your answer : especially when the OPs
problem was correctly disgnosed elsewhere as nothing to do with the
pointer value.

How would you disagree that the NULL pointer has a value of 0 for the
purposes of comparison and display? Which is what the OP asked and to
suggest he is wrong on this is a misleading thing in the context of
his problems isnt it?


It might not for the purpose of display. Given that the _only_ thing
meaningful you can do with a pointer as far as 'display' is to print it
with the format specifier %p, the "value" of any pointer, including the
null pointer, for the purpose of display is an implementation-defined
string of characters.
It was very explicit that NULL and 0 are the same in the context of
pointers and comparisons. Note this is different to internal
representation as covered in other posts in the thread.

But anyhwere else that a NULL pointer is used in terms of being used
for mathematical manipulation of any time its value is 0.

You can't "mathematically manipulate" the null pointer. The only thing
you can do is compare it to another pointer. If you compare it to 0 or
to the macro NULL, that 0 is converted to a pointer before the
comparison.
Isn't it?

Have I tied myself up in knots here? Possibly.

"Comparisons" is superfluous here because the comparison causes 0 [or
the macro NULL, if it's not already a pointer] to be converted to a
pointer, just as an assignment would.
 
R

Richard G. Riley

It might not for the purpose of display. Given that the _only_ thing
meaningful you can do with a pointer as far as 'display' is to print it
with the format specifier %p, the "value" of any pointer, including the
null pointer, for the purpose of display is an implementation-defined
string of characters.


You can't "mathematically manipulate" the null pointer. The only
thing

Sorry. Nomenclature. I (think) meant a pointer which is NULL. Or a
NULLed pointer : is this not a correct term? e.g.

ptr=NULL;

you can do is compare it to another pointer. If you compare it to 0 or
to the macro NULL, that 0 is converted to a pointer before the
comparison.

you mean if I

if(0==ptr)

then 0 is cast to a pointer of same type as ptr? I would expect that.

Hypothetical situation :

a char * which needs to point to memory address 0. What is the
thoughts on this? In this case the pointer must "hold 0" but is not
necessarily a NULL pointer?

I'm not *sure* I am disagreeing : maybe I'll print this out and go
through it again.



Isn't it?

Have I tied myself up in knots here? Possibly.

"Comparisons" is superfluous here because the comparison causes 0 [or
the macro NULL, if it's not already a pointer] to be converted to a
pointer, just as an assignment would.
 
J

Jordan Abel

thing

Sorry. Nomenclature. I (think) meant a pointer which is NULL. Or a
NULLed pointer : is this not a correct term? e.g.

ptr=NULL;

I'd say "null pointer" - "NULL pointer" is not technically correct, but
i knew what you meant. How do you think you can "mathematically
manipulate" it? multiply or divide it by something? take its logarithm
base 10?
you mean if I

if(0==ptr)

then 0 is cast to a pointer of same type as ptr? I would expect that.

Hypothetical situation :

a char * which needs to point to memory address 0. What is the
thoughts on this? In this case the pointer must "hold 0" but is not
necessarily a NULL pointer?

Conversion of an integer (i.e. an integer that is not a constant
expression equal to 0) to a pointer is implementation-defined.

If you really needed this, an implementation would probably go about it
by having the internal representation of a null pointer be some other
value, and you'd do (char *)(int)0 [with the cast to int to make the 0
no longer be a null pointer constant].
 
E

Emmanuel Delahaye

fieldfallow a écrit :
Where is the mistake?

You are just kidding, aren't you ?

Compiling: main.c
main.c: In function `main_':
main.c:6: warning: 'c' might be used uninitialized in this function
main.c:7: warning: 'uc' might be used uninitialized in this function
main.c:8: warning: 's' might be used uninitialized in this function
main.c:9: warning: 'us' might be used uninitialized in this function
main.c:10: warning: 'i' might be used uninitialized in this function
main.c:11: warning: 'ui' might be used uninitialized in this function
main.c:12: warning: 'l' might be used uninitialized in this function
main.c:13: warning: 'ul' might be used uninitialized in this function
main.c:14: warning: 'f' might be used uninitialized in this function
main.c:15: warning: 'd' might be used uninitialized in this function
main.c:16: warning: 'ld' might be used uninitialized in this function
main.c:17: warning: 'v_p' might be used uninitialized in this function
 
E

Emmanuel Delahaye

fieldfallow a écrit :
Where is the mistake?

You are just kidding, aren't you ?

Compiling: main.c
main.c: In function `main_':
main.c:6: warning: 'c' might be used uninitialized in this function
main.c:7: warning: 'uc' might be used uninitialized in this function
main.c:8: warning: 's' might be used uninitialized in this function
main.c:9: warning: 'us' might be used uninitialized in this function
main.c:10: warning: 'i' might be used uninitialized in this function
main.c:11: warning: 'ui' might be used uninitialized in this function
main.c:12: warning: 'l' might be used uninitialized in this function
main.c:13: warning: 'ul' might be used uninitialized in this function
main.c:14: warning: 'f' might be used uninitialized in this function
main.c:15: warning: 'd' might be used uninitialized in this function
main.c:16: warning: 'ld' might be used uninitialized in this function
main.c:17: warning: 'v_p' might be used uninitialized in this function

I'm no sure long double is supported by my implementation. (Code::Blocks)

This code

#include <stdio.h>
#include <limits.h>
#include <float.h>

#define LONG_DOUBLE 0

int main(void)
{
char c=CHAR_MIN;
unsigned char uc=0;
short s=SHRT_MIN;
unsigned short us=0;
int i=INT_MIN;
unsigned int ui=0;
long l=LONG_MIN;
unsigned long ul=0;
float f=FLT_EPSILON;
double d=DBL_EPSILON;
long double ld=LDBL_EPSILON;
void *v_p=0;

printf(" c = '%c' or %d\n"
" uc = '%c' or %u\n"
" s = %hd\n"
" us = %hu\n"
" i = %d\n"
" ui = %u\n"
" l = %ld\n"
" ul = %lu\n"
" f = %f or %g\n"
" d = %f or %g\n"
#if LONG_DOUBLE
" ld = %Lf or %Lg\n"
#endif
"v_p = %p\n"
, (int) c
, (int) c
, (int) uc
, (unsigned) uc
, (short) s
, (unsigned short) us
, (int) i
, (unsigned) ui
, (long) l
, (unsigned long) ul
, (double) f
, (double) f
, (double) d
, (double) d
#if LONG_DOUBLE
, (long double) ld
, (long double) ld
#endif
, (void*) v_p);

puts("Initialising them with their maximum allowed values...");
c = CHAR_MAX;
uc = UCHAR_MAX;
s = SHRT_MAX;
us = USHRT_MAX;
i = INT_MAX;
ui = UINT_MAX;
l = LONG_MAX;
ul = ULONG_MAX;
f = FLT_MAX;
d = DBL_MAX;
ld = LDBL_MAX;
puts("Initialising v_p with NULL...");
v_p = NULL;

printf(" c = '%c' or %d\n"
" uc = '%c' or %u\n"
" s = %hd\n"
" us = %hu\n"
" i = %d\n"
" ui = %u\n"
" l = %ld\n"
" ul = %lu\n"
" f = %f or %g\n"
" d = %f or %g\n"
#if LONG_DOUBLE
" ld = %Lf or %Lg\n"
#endif
"v_p = %p\n"
, (int) c
, (int) c
, (int) uc
, (unsigned) uc
, (short) s
, (unsigned short) us
, (int) i
, (unsigned) ui
, (long) l
, (unsigned long) ul
, (double) f
, (double) f
, (double) d
, (double) d
#if LONG_DOUBLE
, (long double) ld
, (long double) ld
#endif
, (void*) v_p);

return 0;
}


Sounds correct to me:

c = 'Ç' or -128
uc = ' ' or 0
s = -32768
us = 0
i = -2147483648
ui = 0
l = -2147483648
ul = 0
f = 0.000000 or 1.19209e-007
d = 0.000000 or 2.22045e-016
v_p = 00000000
Initialising them with their maximum allowed values...
Initialising v_p with NULL...
c = '?' or 127
uc = ' ' or 255
s = 32767
us = 65535
i = 2147483647
ui = 4294967295
l = 2147483647
ul = 4294967295
f = 340282346638528860000000000000000000000.000000 or 3.40282e+038
d =
17976931348623157000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000.0000
00 or 1.79769e+308
v_p = 00000000
 
F

fieldfallow

Emmanuel said:
fieldfallow a écrit :

You are just kidding, aren't you ?

Compiling: main.c
main.c: In function `main_':
main.c:6: warning: 'c' might be used uninitialized in this function
main.c:7: warning: 'uc' might be used uninitialized in this function
main.c:8: warning: 's' might be used uninitialized in this function
main.c:9: warning: 'us' might be used uninitialized in this function
main.c:10: warning: 'i' might be used uninitialized in this function
main.c:11: warning: 'ui' might be used uninitialized in this function
main.c:12: warning: 'l' might be used uninitialized in this function
main.c:13: warning: 'ul' might be used uninitialized in this function
main.c:14: warning: 'f' might be used uninitialized in this function
main.c:15: warning: 'd' might be used uninitialized in this function
main.c:16: warning: 'ld' might be used uninitialized in this function
main.c:17: warning: 'v_p' might be used uninitialized in this function

Yes. It was soon pointed out to me by others the danger of using
uninitialised variables. However, it was later found that there is a
long double and printf() related bug in my implementation (gcc 3.4.5 and
MinGW 5.0.0).

This turned out to be the actual cause of incorrect output, even though
it could have just as well been the accessing of the uninitialised
variables.

Thanks.
 
M

Micah Cowan

Richard G. Riley said:
Which part?

http://c-faq.com/null/nullor0.html

Clearly says that "C programmers must understand that NULL and 0 are
interchangeable in pointer contexts".

In addition:

"It is only in pointer contexts that NULL and 0 are equivalent"

NULL may even be #defined as 0.

The difference is, that, assuming a 16-bit integer type with no
padding bits,

int foo = 0;

is guaranteed to give foo an all-zeroed-bits representation, whereas

void *bar = 0;

is not. Again, assuming the same conditions above about integer types,
you could do:

int *baz = calloc(sizeof *baz);

and *baz would be guaranteed to have the value zero (but don't use
code like the above, because in general you /can't/ make these
assumptions about padding bits, etc). But

void **quux = calloc(sizeof *quux);

is /not/ guaranteed to make *quux a NULL pointer, or compare equal to
zero.

The short: null pointers must be comparable to zero, but need not be
represented like zero. 0xFFFFFFFF is perfectly reasonable (though,
unlikely on his particular implementation AFAIK).

HTH,
-Micah
 
M

Micah Cowan

Jordan Abel said:
a char * which needs to point to memory address 0. What is the
thoughts on this? In this case the pointer must "hold 0" but is not
necessarily a NULL pointer?

Conversion of an integer (i.e. an integer that is not a constant
expression equal to 0) to a pointer is implementation-defined.

If you really needed this, an implementation would probably go about it
by having the internal representation of a null pointer be some other
value, and you'd do (char *)(int)0 [with the cast to int to make the 0
no longer be a null pointer constant].

This last bit is wrong. It's still an integer constant expression with
the value 0: it still must result in a null pointer.

However:

int foo = 0;
char *bar = foo;

might work. Since it's implementation defined, who knows?

-Micah
 
A

A. Sinan Unur

....
Firstly, I'm not trying to be purposefully counter productive
here. But I am confused as to your answer : especially when the OPs
problem was correctly disgnosed elsewhere as nothing to do with the
pointer value.

OK, I have had time to read the rest of the thread, and I understand the
bug.

The only point I was trying to make was that there is no reason to
expect that printing a null pointer value will yield any specific string
to be emitted.
How would you disagree that the NULL pointer has a value of 0 for the
purposes of comparison and display?

Comparison, yes.

Sinan
 
J

Jordan Abel

Jordan Abel said:
a char * which needs to point to memory address 0. What is the
thoughts on this? In this case the pointer must "hold 0" but is not
necessarily a NULL pointer?

Conversion of an integer (i.e. an integer that is not a constant
expression equal to 0) to a pointer is implementation-defined.

If you really needed this, an implementation would probably go about it
by having the internal representation of a null pointer be some other
value, and you'd do (char *)(int)0 [with the cast to int to make the 0
no longer be a null pointer constant].

This last bit is wrong. It's still an integer constant expression with
the value 0: it still must result in a null pointer.

Casts are not, as far as I can tell, part of constant-expression.
 

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

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,117
Latest member
Matilda564
Top