Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Printing a NULL pointer

Reply
Thread Tools

Printing a NULL pointer

 
 
Michael Mair
Guest
Posts: n/a
 
      06-20-2005
Tim Rentsch wrote:
> Keith Thompson <(E-Mail Removed)> writes:
>
>
>>Tim Rentsch <(E-Mail Removed)> writes:
>>[...]
>>
>>>I'll grant you that most developers use pointers to arrays only
>>>rarely, if at all. To some extent though that's self-reinforcing
>>>behavior - people don't use them because they aren't used to
>>>them, and they aren't used to them because they don't use them.
>>>The code above wasn't natural for me when I wrote it; but I
>>>think it's good to stretch a bit at times to get out of the
>>>local ruts that seem only too easy to fall into.

>>
>>Agreed.
>>
>>I'd also speculate that pointers to arrays are used accidentally
>>nearly as often as they're used deliberately (by programmers who don't
>>quite understand the interactions between arrays and pointers). Such
>>code often works by accident if a pointer-to-char and a
>>pointer-to-array-of-char happen to have the same representation.

>
> Interesting idea. Have you ever actually seen it? I'd expect
> that normally the distinction would be caught by during type
> checking.


People who get this wrong probably have no scruples inserting the
"necessary" type casts to shut up the oh-so-noisy compiler... :-/

[snip]


Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
 
Reply With Quote
 
 
 
 
Lawrence Kirby
Guest
Posts: n/a
 
      06-21-2005
On Sun, 19 Jun 2005 09:43:34 -0700, Tim Rentsch wrote:

....

>> Yes, you're writing outside the bounds of the array. The array in
>> question is out[i] which is (in the specified conditions) a 2 element
>> array. What you are passing as the first argument to sprintf() is a
>> pointer to the first element of this 2 element array. When the call to
>> sprintf() writes to out[i][2] it invokes undefined behaviour.

>
> If you look at the actual language I think you'll find
> that it's not as simple as that. So I need to ask you
> to cite "chapter and verse", as they say. I've looked
> at the actual language quite carefully.


I know what you mean but I believe what I wrote is the intent.

6.5.6p8 says

"... If both the pointer operand and the result point to elements of the
same array object, or one past the last element of the array object, the
evaluation shall not produce an overflow; otherwise, the behavior is
undefined. If the result points one past the last element of the array
object, it shall not be used as the operand of a unary * operator that is
evaluated."

So given

char (*out)[NIBBLES_PER_CHAR] = malloc( NIBBLES_PER_CHAR*len + 1 );

out[N] is an array of NIBBLES_PER_CHAR characters and if I write

char *p = out[N];

then p is a pointer to the first element of an array of NIBBLES_PER_CHAR
chars. p+NIBBLES_PER_CHAR is a pointer to one past the last element of
this array so *(p+NIBBLES_PER_CHAR) violates the "shall" requirement above
resulting in undefined behaviour.

Granted the original example uses sprintf() rather than + and *, snd it is
less clear how the one last the end rules apply to standard library
functions.

Lawrence



 
Reply With Quote
 
 
 
 
Tim Rentsch
Guest
Posts: n/a
 
      07-11-2005
Lawrence Kirby <(E-Mail Removed)> writes:

> On Sun, 19 Jun 2005 09:43:34 -0700, Tim Rentsch wrote:
>
> ...
>
> >> Yes, you're writing outside the bounds of the array. The array in
> >> question is out[i] which is (in the specified conditions) a 2 element
> >> array. What you are passing as the first argument to sprintf() is a
> >> pointer to the first element of this 2 element array. When the call to
> >> sprintf() writes to out[i][2] it invokes undefined behaviour.

> >
> > If you look at the actual language I think you'll find
> > that it's not as simple as that. So I need to ask you
> > to cite "chapter and verse", as they say. I've looked
> > at the actual language quite carefully.

>
> I know what you mean but I believe what I wrote is the intent.


ITYM you believe you know what I mean.

It isn't obvious even that there is a single intent, let alone
what "the" intent is. And, as Dennis Ritchie said:

"The intentions of the committee are irrelevant;
only their document matters."


> 6.5.6p8 says
>
> "... If both the pointer operand and the result point to elements of the
> same array object, or one past the last element of the array object, the
> evaluation shall not produce an overflow; otherwise, the behavior is
> undefined. If the result points one past the last element of the array
> object, it shall not be used as the operand of a unary * operator that is
> evaluated."


Clarifying context - 6.5.6 p8 earlier says:

"... If the pointer operand points to an element of an array
object, and the array is large enough, the result points to
an element offset from the original element such that the
difference of the of the subscripts of the resulting and
original array elements equals the integer expression. ..."


> So given
>
> char (*out)[NIBBLES_PER_CHAR] = malloc( NIBBLES_PER_CHAR*len + 1 );
>
> out[N] is an array of NIBBLES_PER_CHAR characters


What you mean is that 'out[N]' has type 'char [NIBBLES_PER_CHAR]'.
That doesn't change the storage that '&out[N][0]' points at. If
we have

char buf[1000];
char (*x)[2] = (char (*)[2])buf;

then the pointer value of 'x[0]' (ie, '&x[0][0]') still points
at an array object of 1000 characters.


> and if I write
>
> char *p = out[N];
>
> then p is a pointer to the first element of an array of NIBBLES_PER_CHAR
> chars.


You've confusing the term 'array object' with the notion of array
type. The variable 'p' is only a pointer; the type doesn't know
anything about the array object it points into. The array object that
'p' points into is an array starting at the address returned by malloc
and extending for NIBBLES_PER_CHAR*len + 1 characters. There must be
such an array object, because of how malloc works.


> p+NIBBLES_PER_CHAR is a pointer to one past the last element of
> this array so *(p+NIBBLES_PER_CHAR) violates the "shall" requirement above
> resulting in undefined behaviour.


Converting a pointer (ie, assigning the pointer returned by malloc)
doesn't change the underlying storage. If we had written

char *p = ((char (*)[1000000000]) out[N])[0];

the value of 'p' is just the same as previously; the cast doesn't
magically make an array object of a billion characters spring into
being. Similarly if the cast had been to (char(*)[1]) that doesn't
suddenly reduce the amount of space available; 'p' still points into
the same array object as before, namely the array object returned by
malloc.


> Granted the original example uses sprintf() rather than + and *, snd it is
> less clear how the one last the end rules apply to standard library
> functions.


I believe that doesn't affect the result one way or the other. Once
the expression 'out[N]' gets turned into a character pointer the
result should be the same whether sprintf() is used or not.


[Sorry for the belated reply; I've been busy.]
 
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
pointer to pointer intialize to NULL but still point to NULL Christopher C++ 4 07-09-2011 12:35 AM
Null pointer (NULL array pointer is passed) aneuryzma C++ 3 06-16-2008 05:48 AM
"stringObj == null" vs "stringObj.equals(null)", for null check?? qazmlp1209@rediffmail.com Java 5 03-29-2006 10:37 PM
NULL macro vs. 0 as null pointer? Ken C++ 69 07-31-2004 04:45 AM
Followup: NULL macro vs. 0 as null pointer? Ken C++ 5 07-24-2004 04:05 PM



Advertisments