Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Accessing void * buffer/array through char * pointer

Reply
Thread Tools

Accessing void * buffer/array through char * pointer

 
 
s0suk3@gmail.com
Guest
Posts: n/a
 
      09-06-2008
This code

#include <stdio.h>

int main(void)
{
int hello[] = {'h', 'e', 'l', 'l', 'o'};
char *p = (void *) hello;

for (size_t i = 0; i < sizeof(hello); ++i) {
printf("byte %2zu: <%c>", i, p[i]);
if (!p[i])
printf(" (null char)");
printf("\n");
}

return 0;
}

produces this output

byte 0: <h>
byte 1: <> (null char)
byte 2: <> (null char)
byte 3: <> (null char)
byte 4: <e>
byte 5: <> (null char)
byte 6: <> (null char)
byte 7: <> (null char)
byte 8: <l>
byte 9: <> (null char)
byte 10: <> (null char)
byte 11: <> (null char)
byte 12: <l>
byte 13: <> (null char)
byte 14: <> (null char)
byte 15: <> (null char)
byte 16: <o>
byte 17: <> (null char)
byte 18: <> (null char)
byte 19: <> (null char)

I'm confused about the int *-to-void *-to char * conversion. The
output shows that ints are four bytes on my machine, and the values in
the initializer 'h', 'e', 'l', 'l', 'o' have the values 104, 101, 108,
108, and 111, respectively, so they're able to be represented as chars
(duh...). But if I'd change the initializer to something like

int hello[] = {1000, 43676, 362, 6364, 2575};

I'd get this output

byte 0: <�>
byte 1: <>
byte 2: <> (null char)
byte 3: <> (null char)
byte 4: <�>
byte 5: <�>
byte 6: <> (null char)
byte 7: <> (null char)
byte 8: <j>
byte 9: <>
byte 10: <> (null char)
byte 11: <> (null char)
byte 12: <�>
byte 13: <▒>
byte 14: <> (null char)
byte 15: <> (null char)
byte 16: <>
byte 17: <
>

byte 18: <> (null char)
byte 19: <> (null char)

(In other words, non-printable characters.)

Is some kind of overflow happening when I subscript the char pointer?
Or am I simply getting meaningless values because of accessing a char
pointer that points to something that wasn't a char object?

Sebastian

 
Reply With Quote
 
 
 
 
Ben Bacarisse
Guest
Posts: n/a
 
      09-06-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) writes:

> #include <stdio.h>
>
> int main(void)
> {
> int hello[] = {'h', 'e', 'l', 'l', 'o'};
> char *p = (void *) hello;
>
> for (size_t i = 0; i < sizeof(hello); ++i) {
> printf("byte %2zu: <%c>", i, p[i]);
> if (!p[i])
> printf(" (null char)");
> printf("\n");
> }
>
> return 0;
> }

<snip>
> I'm confused about the int *-to-void *-to char * conversion. The
> output shows that ints are four bytes on my machine, and the values in
> the initializer 'h', 'e', 'l', 'l', 'o' have the values 104, 101, 108,
> 108, and 111, respectively, so they're able to be represented as chars
> (duh...). But if I'd change the initializer to something like
>
> int hello[] = {1000, 43676, 362, 6364, 2575};
>
> I'd get this output
>
> byte 0: <�>
> byte 1: <>
> byte 2: <> (null char)
> byte 3: <> (null char)
> byte 4: <�>
> byte 5: <�>
> byte 6: <> (null char)
> byte 7: <> (null char)

<snip>
> (In other words, non-printable characters.)
>
> Is some kind of overflow happening when I subscript the char
> pointer?


No, no overflow is happening on access.

> Or am I simply getting meaningless values because of accessing a char
> pointer that points to something that wasn't a char object?


First, they are not meaningless. Some process governs exactly what
you see but since it may involve things like the terminal setting it
can be a very complex one.

Secondly, a char pointer always points at a char object. C does not
mandate the value but any object of any type can be accessed as if it
is a sequence of char objects. In your case the first two characters
are almost certainly 1000 % 256 and 1000 / 256, i.e. the least and
second least significant bytes of the binary representation of 1000.

I know this is not an actual answer, but your either/or questions
don't give me much room!

--
Ben.
 
Reply With Quote
 
 
 
 
raashid bhatt
Guest
Posts: n/a
 
      09-06-2008
On Sep 6, 4:26 pm, (E-Mail Removed) wrote:
> This code
>
> #include <stdio.h>
>
> int main(void)
> {
> int hello[] = {'h', 'e', 'l', 'l', 'o'};
> char *p = (void *) hello;
>
> for (size_t i = 0; i < sizeof(hello); ++i) {
> printf("byte %2zu: <%c>", i, p[i]);
> if (!p[i])
> printf(" (null char)");
> printf("\n");
> }
>
> return 0;
>
> }
>
> produces this output
>
> byte 0: <h>
> byte 1: <> (null char)
> byte 2: <> (null char)
> byte 3: <> (null char)
> byte 4: <e>
> byte 5: <> (null char)
> byte 6: <> (null char)
> byte 7: <> (null char)
> byte 8: <l>
> byte 9: <> (null char)
> byte 10: <> (null char)
> byte 11: <> (null char)
> byte 12: <l>
> byte 13: <> (null char)
> byte 14: <> (null char)
> byte 15: <> (null char)
> byte 16: <o>
> byte 17: <> (null char)
> byte 18: <> (null char)
> byte 19: <> (null char)
>
> I'm confused about the int *-to-void *-to char * conversion. The
> output shows that ints are four bytes on my machine, and the values in
> the initializer 'h', 'e', 'l', 'l', 'o' have the values 104, 101, 108,
> 108, and 111, respectively, so they're able to be represented as chars
> (duh...). But if I'd change the initializer to something like
>
> int hello[] = {1000, 43676, 362, 6364, 2575};
>
> I'd get this output
>
> byte 0: < >
> byte 1: <>
> byte 2: <> (null char)
> byte 3: <> (null char)
> byte 4: < >
> byte 5: < >
> byte 6: <> (null char)
> byte 7: <> (null char)
> byte 8: <j>
> byte 9: <>
> byte 10: <> (null char)
> byte 11: <> (null char)
> byte 12: < >
> byte 13: <>
> byte 14: <> (null char)
> byte 15: <> (null char)
> byte 16: <>
> byte 17: <
>
> byte 18: <> (null char)
> byte 19: <> (null char)
>
> (In other words, non-printable characters.)
>
> Is some kind of overflow happening when I subscript the char pointer?
> Or am I simply getting meaningless values because of accessing a char
> pointer that points to something that wasn't a char object?
>
> Sebastian


your question is same as i asked here before acutally acutally when we
have array of chars or int the linker allocates bytes of initialized
values plus 4 BYTES MORE which also include a NuLL char '\0'
 
Reply With Quote
 
raashid bhatt
Guest
Posts: n/a
 
      09-06-2008
On Sep 6, 4:26 pm, (E-Mail Removed) wrote:
> This code
>
> #include <stdio.h>
>
> int main(void)
> {
> int hello[] = {'h', 'e', 'l', 'l', 'o'};
> char *p = (void *) hello;
>
> for (size_t i = 0; i < sizeof(hello); ++i) {
> printf("byte %2zu: <%c>", i, p[i]);
> if (!p[i])
> printf(" (null char)");
> printf("\n");
> }
>
> return 0;
>
> }
>
> produces this output
>
> byte 0: <h>
> byte 1: <> (null char)
> byte 2: <> (null char)
> byte 3: <> (null char)
> byte 4: <e>
> byte 5: <> (null char)
> byte 6: <> (null char)
> byte 7: <> (null char)
> byte 8: <l>
> byte 9: <> (null char)
> byte 10: <> (null char)
> byte 11: <> (null char)
> byte 12: <l>
> byte 13: <> (null char)
> byte 14: <> (null char)
> byte 15: <> (null char)
> byte 16: <o>
> byte 17: <> (null char)
> byte 18: <> (null char)
> byte 19: <> (null char)
>
> I'm confused about the int *-to-void *-to char * conversion. The
> output shows that ints are four bytes on my machine, and the values in
> the initializer 'h', 'e', 'l', 'l', 'o' have the values 104, 101, 108,
> 108, and 111, respectively, so they're able to be represented as chars
> (duh...). But if I'd change the initializer to something like
>
> int hello[] = {1000, 43676, 362, 6364, 2575};
>
> I'd get this output
>
> byte 0: < >
> byte 1: <>
> byte 2: <> (null char)
> byte 3: <> (null char)
> byte 4: < >
> byte 5: < >
> byte 6: <> (null char)
> byte 7: <> (null char)
> byte 8: <j>
> byte 9: <>
> byte 10: <> (null char)
> byte 11: <> (null char)
> byte 12: < >
> byte 13: <>
> byte 14: <> (null char)
> byte 15: <> (null char)
> byte 16: <>
> byte 17: <
>
> byte 18: <> (null char)
> byte 19: <> (null char)
>
> (In other words, non-printable characters.)
>
> Is some kind of overflow happening when I subscript the char pointer?
> Or am I simply getting meaningless values because of accessing a char
> pointer that points to something that wasn't a char object?
>
> Sebastian


here is the post
http://groups.google.co.in/group/com...42714e7b3e6c17
 
Reply With Quote
 
vippstar@gmail.com
Guest
Posts: n/a
 
      09-06-2008
On Sep 6, 2:26 pm, (E-Mail Removed) wrote:
> This code


Is broken.

> #include <stdio.h>
>
> int main(void)
> {
> int hello[] = {'h', 'e', 'l', 'l', 'o'};
> char *p = (void *) hello;


Change p to `unsigned char'. And the cast can be (void *) or (unsigned
char *).

> for (size_t i = 0; i < sizeof(hello); ++i) {
> printf("byte %2zu: <%c>", i, p[i]);


Remove the 2 in %2zu, else the output might not be meaningful.
Evaluating p[i] can invoke undefined behavior. Changing p to type
`unsigned char *' as I have suggested previously fixes this.

> if (!p[i])
> printf(" (null char)");
> printf("\n");
> }
>
> return 0;
>
> }
>
> produces this output


<snip output>


> I'm confused about the int *-to-void *-to char * conversion. The
> output shows that ints are four bytes on my machine, and the values in
> the initializer 'h', 'e', 'l', 'l', 'o' have the values 104, 101, 108,
> 108, and 111, respectively, so they're able to be represented as chars
> (duh...). But if I'd change the initializer to something like


You can convert any pointer to object to unsigned char * to inspect
its object representation.

> int hello[] = {1000, 43676, 362, 6364, 2575};
>
> I'd get this output


<snip>

> (In other words, non-printable characters.)


So what?

> Is some kind of overflow happening when I subscript the char pointer?
> Or am I simply getting meaningless values because of accessing a char
> pointer that points to something that wasn't a char object?


*ASSUMING* you change p to unsigned char *, you split the objects
representation in CHAR_BIT chunks, and you treat those bits as value
bits, even though in the original object they might be padding bits or
a sign bit.

Change your program to this for more meaningful output:

#include <stdio.h>

typedef int object_type;
#define SIZE 10

int main(void) {

object_type object[SIZE];
unsigned char *p;
size_t i;

p = (unsigned char *)object;

for(i = 0; i < sizeof object; i++)
if(isprint(p[i])) printf("p[%zu] = '%c'\n", i, p[i]);
else printf("p[%zu] = not printable\n", i);

return 0;
}
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      09-06-2008
raashid bhatt <(E-Mail Removed)> writes:

> On Sep 6, 4:26 pm, (E-Mail Removed) wrote:

<snip>
>> int main(void)
>> {
>> int hello[] = {'h', 'e', 'l', 'l', 'o'};
>> char *p = (void *) hello;

<snip>
>> }

<snip>
> here is the post
> http://groups.google.co.in/group/com...42714e7b3e6c17


In case you are confused by this reply, there is no connection between
your code and the thread cited by raashid bhatt.

--
Ben.
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      09-06-2008
(E-Mail Removed) writes:

> On Sep 6, 2:26 pm, (E-Mail Removed) wrote:

<snip>
>> for (size_t i = 0; i < sizeof(hello); ++i) {
>> printf("byte %2zu: <%c>", i, p[i]);

>
> Remove the 2 in %2zu, else the output might not be meaningful.


What on earth is wrong with the 2?

> Evaluating p[i] can invoke undefined behavior.


I think it is better to say "may invoke undefined behaviour". I
accept that you don't agree (there's been a long thread about this
already) but just for the benefit of the OP there are systems on which
the code posted can't go wrong in any way. Using a potentially signed
char pointer merely limits the portability to a very specific class of
implementations and you, as the programmer, can know (with absolute
certainty) if the code's behaviour is defined or not beforehand. This
is quite unlike some other kinds of UB.

However, one should always used unsigned char for this purpose since
there is no advantage to be gained by using char *.

--
Ben.
 
Reply With Quote
 
s0suk3@gmail.com
Guest
Posts: n/a
 
      09-06-2008
On Sep 6, 7:02*am, Ben Bacarisse <(E-Mail Removed)> wrote:
> (E-Mail Removed) writes:

<snip>
>> Or am I simply getting meaningless values because of accessing a char
>> pointer that points to something that wasn't a char object?

>
> First, they are not meaningless. *Some process governs exactly what
> you see but since it may involve things like the terminal setting it
> can be a very complex one.
>


Well, I meant meaningless in the sense that the values were produced
in an unnatural way. For example, with the second initializer, the
bits that make up for the 1000 in the first element of the int array
are then broken when accessed through the char pointer and everything
becomes a mess! (I got -24 when trying to see the numerical value of
the first element that the char pointer was pointing to.)

> Secondly, a char pointer always points at a char object. *C does not
> mandate the value but any object of any type can be accessed as if it
> is a sequence of char objects. *In your case the first two characters
> are almost certainly 1000 % 256 and 1000 / 256, i.e. the least and
> second least significant bytes of the binary representation of 1000.
>


Changing the printf format string to "byte %2zu: <%d>" (i.e., to print
a number instead of a character) yields -24 (which is not 1000 % 256)
for the first character and 3 (which is indeed 1000 / 256) for the
second.

> I know this is not an actual answer, but your either/or questions
> don't give me much room!
>


No, it was indeed useful. Anyway, I was just unsure whether accessing
the char pointer in that way was safe. Thanks.

Sebastian

 
Reply With Quote
 
vippstar@gmail.com
Guest
Posts: n/a
 
      09-06-2008
On Sep 6, 4:09 pm, Ben Bacarisse <(E-Mail Removed)> wrote:
> (E-Mail Removed) writes:
> > On Sep 6, 2:26 pm, (E-Mail Removed) wrote:

> <snip>
> >> for (size_t i = 0; i < sizeof(hello); ++i) {
> >> printf("byte %2zu: <%c>", i, p[i]);

>
> > Remove the 2 in %2zu, else the output might not be meaningful.

>
> What on earth is wrong with the 2?


Nothing, I got confused with the meaning of `2' in scanf. (I thought
only the first two digits would be printed, like only the first two
digits are matched in scanf)
I apologize for this.
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      09-06-2008
(E-Mail Removed) writes:

> On Sep 6, 7:02*am, Ben Bacarisse <(E-Mail Removed)> wrote:
>> (E-Mail Removed) writes:

> <snip>
>>> Or am I simply getting meaningless values because of accessing a char
>>> pointer that points to something that wasn't a char object?

<snip>
>> Secondly, a char pointer always points at a char object. *C does not
>> mandate the value but any object of any type can be accessed as if it
>> is a sequence of char objects. *In your case the first two characters
>> are almost certainly 1000 % 256 and 1000 / 256, i.e. the least and
>> second least significant bytes of the binary representation of 1000.
>>

>
> Changing the printf format string to "byte %2zu: <%d>" (i.e., to print
> a number instead of a character) yields -24 (which is not 1000 % 256)
> for the first character and 3 (which is indeed 1000 / 256) for the
> second.


OK, fair cop. 1000 % 256 = 232 = 256-24. I.e. -24 is 1000 % 256 when
that bit pattern is interpreted as signed using the most common
representation of signed values (2s complement). Also -24 = 232 (mod
256) i.e. -24 is a value of 1000 mod 256 so the result is
understandable in terms of div and mod. I did not know your char was
signed (though in true that is common).

>> I know this is not an actual answer, but your either/or questions
>> don't give me much room!
>>

>
> No, it was indeed useful. Anyway, I was just unsure whether accessing
> the char pointer in that way was safe. Thanks.


Now that is another question altogether. It is safe unless your
implementation has signed chars and has trap representations for some
bit patters in signed char (-0 being the most likely on non 2s
complement machines).

In one sense (maximum portability) using char is not safe, but since
any given implementation must tell you if it is not safe, I feel it is
a bit broad to say "undefined". However (and this is a big however)
since there is nothing at all to be gained at all from using char
(rather than unsigned char) you should always use unsigned char when
inspecting the representation of an object.

--
Ben.
 
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
What is the difference between void proba(); and void proba(void); ??? PencoOdStip@gmail.com C++ 1 05-23-2007 07:12 PM
Conversion from 'void*' to pointer to non-'void' requires an explicit cast Hakirato C++ 4 10-05-2006 04:02 PM
what is the difference, void func(void) and void fucn() noblesantosh@yahoo.com C Programming 5 07-22-2005 04:38 PM
"void Method()" vs "void Method(void)" Ollej Reemt C++ 7 04-22-2005 03:47 AM
`void **' revisited: void *pop(void **root) Stig Brautaset C Programming 15 10-28-2003 09:03 AM



Advertisments