Go Back   Velocity Reviews > Newsgroups > C Programming
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

Reply

C Programming - void *

 
Thread Tools Search this Thread
Old 11-01-2009, 09:49 PM   #11
Default Re: void *


bandejapaisa <> writes:
>>
>> Its hard to know where to start.
>>
>> Even forgetting the issues with types : have a careful look at your
>> *temp pointer. You dont actually store the temp value pointed at.
>>
>> You are confused with pointers and the values they point to it seems.
>>
>>
>>
>> > void swap(void *source, void *dest) {
>> > Â* Â*void *temp = source;

>>
>> you are storing the POINTER not the VALUE pointed to.
>>

>
> I did this because i was experimenting and it wouldn't compile when i
> did
>
> void *temp = *source;
>
> Its the use of (void *) that i'm not quite getting. It worked fine
> when i declared the types, i.e:
>
> void swap(int *x, int *y) {
> int *t = *x;
> *x = *y;
> *y = t;
> }


When you write

*x = *y;

when x and y are of type int, the compiler knows that it needs to
generate code to copy sizeof(int) bytes.

When x and y are of type void*, how many bytes should be copied?
Assuming you have a specific number of bytes in mind, how is the
compiler to know what it is?

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"


Keith Thompson
  Reply With Quote
Old 11-01-2009, 10:23 PM   #12
Seebs
 
Posts: n/a
Default Re: void *
On 2009-11-01, bandejapaisa <> wrote:
> I did this because i was experimenting and it wouldn't compile when i
> did


> void *temp = *source;


That's because you can't dereference source, because it's a
pointer-to-nothing. It's also the wrong thing.

What you'd want to do, if you could dereference source, would be
to write "void temp = *source;" -- but you can't, because there's no
such thing as a void object.

> Its the use of (void *) that i'm not quite getting.


Imagine that it says "pointer to nothing". Although it's technically
incorrect, I just treat a "void *" as a pointer to a 0-byte object when
trying to figure out how it'll work.


> void swap(int *x, int *y) {
> int *t = *x;
> *x = *y;
> *y = t;
> }


This is wrong, because you're storing the contents of x in a pointer to int.

It should be "int t = *x;"

Pointers summarized: Declaration reflects use. "int *t;" means "there is
an int, *t". So "*t" is an int, so "t" is a pointer-to-int. So you could
do:

int *p = x;
int t = *x;

because x is "int *", so "*x" is an int, but "x" is an "int *".

-s
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet-
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!


Seebs
  Reply With Quote
Old 11-01-2009, 10:52 PM   #13
Thad Smith
 
Posts: n/a
Default Re: void *
bandejapaisa wrote:

> Its the use of (void *) that i'm not quite getting. It worked fine
> when i declared the types, i.e:
>
> void swap(int *x, int *y) {
> int *t = *x;
> *x = *y;
> *y = t;
> }


That is not guaranteed to work, since you are storing an int into an
int* variable, which could change the representation or not be large
enough. That should be
int t = *x;

An essential requirement of using a pointer is guarantee that when you
use (dereference) it, it is pointing to valid storage for the intended
type. A minimum requirement is that the pointer be assigned a value of
a suitable object, such as
int a;
int *p;
p = &a;

or by using a memory allocation routine
p = malloc(sizeof int);

If using the latter, verify that the memory allocation succeeded before
attempting to use the pointer:
#include <stdlib.h> /* outside your code */
...
if (p == NULL) {
/* code for error handling here, such as */
puts("Out of memory");
return EXIT_FAILURE;
}

--
Thad


Thad Smith
  Reply With Quote
Old 11-02-2009, 07:23 PM   #14
frank
 
Posts: n/a
Default Re: void *
On Sun, 01 Nov 2009 21:15:16 +0000, Seebs wrote:

> On 2009-11-01, Keith Thompson <kst-> wrote:
>> A reasonable compromise, if you're concerned about both time and space,
>> would be to declare a fixed-size buffer and use memcpy() in a loop.

>
> Yes.
>
> Interestingly, this might end up being a good place to use Duff's
> Device.
>
> -s


send(to, from, count)
register short *to, *from;
register count;
{
register n=(count+7)/8;
switch(count%{
case 0: do{ *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
}while(--n>0);
}
}


How does the "interlacing" occur?
--
frank


frank
  Reply With Quote
Old 11-03-2009, 05:38 AM   #15
arnuld
 
Posts: n/a
Default Re: void *
> On Sun, 01 Nov 2009 19:40:03 +0000, Richard Heathfield wrote:

> #include <stddef.h>
>
> /* the following function has woefully
> inadequate error checking; the behaviour is undefined if you screw up
> the call */
>
> void swap(void *vleft, void *vright, size_t len) {
> unsigned char *left = vleft;
> unsigned char *right = vright;
> unsigned char tmp;
> while(len--)
> {
> tmp = *left;
> *left++ = *right;
> *right++ = tmp;
> }
> }




If arguments are /double*/ or types with values larger than /unsigned
char/ , we are going to get 2 implicit casts which will result only in
some random values assigned but this works correctly. Some sort of
pointer-magic ?



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

/* the following function has woefully
inadequate error checking; the behaviour
is undefined if you screw up the call */

void swap(void *vleft, void *vright, size_t len);




int main(void)
{
double d1 = 23.999;
double d2 = 999.23;
long u1 = LONG_MAX;
long u2 = LONG_MIN;


printf("d1 = %f, d2 = %f\n", d1, d2);
printf("u1 = %ld, u2 = %ld\n\n", u1, u2);
swap(&d1, &d2, sizeof(d1));
swap(&u1, &u2, sizeof(u1));
printf("Values Swapped\n\n");
printf("d1 = %f, d2 = %f\n", d1, d2);
printf("u1 = %ld, u2 = %ld\n\n", u1, u2);


return 0;
}


void swap(void *vleft, void *vright, size_t len)
{
unsigned char *left = vleft;
unsigned char *right = vright;
unsigned char tmp;
while(len--)
{
tmp = *left;
*left++ = *right;
*right++ = tmp;
}
}
=========================== OUTPUT =====================================
[arnuld@dune programs]$ gcc -ansi -pedantic -Wall -Wextra test.c
[arnuld@dune programs]$ ./a.out
d1 = 23.999000, d2 = 999.230000
u1 = 2147483647, u2 = -2147483648

Values Swapped

d1 = 999.230000, d2 = 23.999000
u1 = -2147483648, u2 = 2147483647

[arnuld@dune programs]$






--
www.lispmachine.wordpress.com
my email is @ the above blog.



arnuld
  Reply With Quote
Old 11-03-2009, 05:54 AM   #16
user923005
 
Posts: n/a
Default Re: void *
On Nov 2, 9:38*pm, arnuld <sunr...@invalid.address> wrote:
> > On Sun, 01 Nov 2009 19:40:03 +0000, Richard Heathfield wrote:
> > #include <stddef.h>

>
> > /* the following function has woefully
> > * *inadequate error checking; the behaviour is undefined if you screw up
> > * *the call */

>
> > void swap(void *vleft, void *vright, size_t len) {
> > * unsigned char *left = vleft;
> > * unsigned char *right = vright;
> > * unsigned char tmp;
> > * while(len--)
> > * {
> > * * tmp = *left;
> > * * *left++ = *right;
> > * * *right++ = tmp;
> > * }
> > }

>
> If arguments are /double*/ or types with values larger than /unsigned
> char/ , we are going to get 2 implicit casts which will result only in
> some random values assigned but this works correctly. Some sort of
> pointer-magic ?
>
> #include <stdio.h>
> #include <stddef.h>
> #include <limits.h>
>
> /* the following function has woefully
> * *inadequate error checking; the behaviour
> * *is undefined if you screw up the call */
>
> void swap(void *vleft, void *vright, size_t len);
>
> int main(void)
> {
> * double d1 = 23.999;
> * double d2 = 999.23;
> * long u1 = LONG_MAX;
> * long u2 = LONG_MIN;
>
> * printf("d1 = %f, d2 = %f\n", d1, d2);
> * printf("u1 = %ld, u2 = %ld\n\n", u1, u2);
> * swap(&d1, &d2, sizeof(d1));
> * swap(&u1, &u2, sizeof(u1));
> * printf("Values Swapped\n\n");
> * printf("d1 = %f, d2 = %f\n", d1, d2);
> * printf("u1 = %ld, u2 = %ld\n\n", u1, u2);
>
> * return 0;
>
> }
>
> void swap(void *vleft, void *vright, size_t len)
> {
> * unsigned char *left = vleft;
> * unsigned char *right = vright;
> * unsigned char tmp;
> * while(len--)
> * {
> * * tmp = *left;
> * * *left++ = *right;
> * * *right++ = tmp;
> * }}
>
> =========================== OUTPUT =====================================
> [arnuld@dune programs]$ gcc -ansi -pedantic -Wall -Wextra test.c
> [arnuld@dune programs]$ ./a.out
> d1 = 23.999000, d2 = 999.230000
> u1 = 2147483647, u2 = -2147483648
>
> Values Swapped
>
> d1 = 999.230000, d2 = 23.999000
> u1 = -2147483648, u2 = 2147483647
>
> [arnuld@dune programs]$


An especially clever swap routine is found in here (I left the entire
code body so you can see how it is used and even test it if you like):

/*
* Modifications from vanilla NetBSD source:
* Add do ... while() macro fix
* Remove __inline, _DIAGASSERTs, __P
*
* $PostgreSQL: pgsql/src/port/qsort.c,v 1.5 2004/10/05 00:12:49
neilc Exp $
*/

/* $NetBSD: qsort.c,v 1.13 2003/08/07 16:43:42 agc Exp $ */

/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
copyright
* notice, this list of conditions and the following disclaimer in
the
* documentation and/or other materials provided with the
distribution.
* 3. Neither the name of the University nor the names of its
contributors
* may be used to endorse or promote products derived from this
software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF
* SUCH DAMAGE.
*/

#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>

#define CROSSOVER_POINT (15)

static char *med3(char *, char *, char *, int (*) (const void *,
const void *));
static void swapfunc(char *, char *, size_t, int);

#undef min
#define min(a, b) ((a) < (b) ? (a) : (b))

/*
* Qsort routine from Bentley & McIlroy's "Engineering a Sort
Function".
*/
#define swapcode(TYPE, parmi, parmj, n) \
do { \
size_t i = (n) / sizeof (TYPE); \
TYPE *pi = (TYPE *)(void *)(parmi); \
TYPE *pj = (TYPE *)(void *)(parmj); \
do { \
TYPE t = *pi; \
*pi++ = *pj; \
*pj++ = t; \
} while (--i > 0); \
} while (0)

#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof
(long) || \
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;

static void swapfunc(char *a, char *b, size_t n, int swaptype)
{
if (swaptype <= 1)
swapcode(long, a, b, n);
else
swapcode(char, a, b, n);
}

#define swap(a, b) \
if (swaptype == 0) { \
long t = *(long *)(void *)(a); \
*(long *)(void *)(a) = *(long *)(void *)(b); \
*(long *)(void *)(b) = t; \
} else \
swapfunc(a, b, es, swaptype)

#define vecswap(a, b, n) if ((n) > 0) swapfunc((a), (b), (size_t)(n),
swaptype)

static char *med3(char *a, char *b, char *c, int (*cmp) (const void
*, const void *))
{
return cmp(a, b) < 0 ?
(cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a))
: (cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c));
}

static int sorted(void *arr, size_t count, size_t stride, int
(*cmp) (const void *, const void *))
{
size_t i;
char *p = arr;
char *thisp = p;
char *nextp = p + stride;
for (i = 0; i < count-1; i++)
{
if (cmp(thisp, nextp) > 0) {
return 0;
}
thisp = nextp;
nextp += stride;
}
return 1;
}

void qsb(void *a, size_t n, size_t es, int (*cmp) (const
void *, const void *))
{
char *pa,
*pb,
*pc,
*pd,
*pl,
*pm,
*pn;
int d,
r,
swaptype,
swap_cnt;

SWAPINIT(a, es);
loop:
swap_cnt = 0;
if (n < CROSSOVER_POINT) {
for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; pl -
= es)
swap(pl, pl - es);
return;
}
if (sorted(a, n, es, cmp)) return;
pm = (char *) a + (n / 2) * es;
pl = (char *) a;
pn = (char *) a + (n - 1) * es;
if (n > 40) {
d = (n / * es;
pl = med3(pl, pl + d, pl + 2 * d, cmp);
pm = med3(pm - d, pm, pm + d, cmp);
pn = med3(pn - 2 * d, pn - d, pn, cmp);
}
pm = med3(pl, pm, pn, cmp);
swap(a, pm);
pa = pb = (char *) a + es;

pc = pd = (char *) a + (n - 1) * es;
for (; {
while (pb <= pc && (r = cmp(pb, a)) <= 0) {
if (r == 0) {
swap_cnt = 1;
swap(pa, pb);
pa += es;
}
pb += es;
}
while (pb <= pc && (r = cmp(pc, a)) >= 0) {
if (r == 0) {
swap_cnt = 1;
swap(pc, pd);
pd -= es;
}
pc -= es;
}
if (pb > pc)
break;
swap(pb, pc);
swap_cnt = 1;
pb += es;
pc -= es;
}
if (swap_cnt == 0) { /* Switch to insertion sort */
for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
pn = (char *) a + n * es;
r = min(pa - (char *) a, pb - pa);
vecswap(a, pb - r, r);
r = min(pd - pc, pn - pd - es);
vecswap(pb, pn - r, r);
if ((r = pb - pa) > es)
qsb(a, r / es, es, cmp);
if ((r = pd - pc) > es) {
/* Iterate rather than recurse to save stack space */
a = pn - r;
n = r / es;
goto loop;
}
}


user923005
  Reply With Quote
Old 11-03-2009, 07:54 AM   #17
Seebs
 
Posts: n/a
Default Re: void *
On 2009-11-03, arnuld <> wrote:
> If arguments are /double*/ or types with values larger than /unsigned
> char/ , we are going to get 2 implicit casts which will result only in
> some random values assigned but this works correctly. Some sort of
> pointer-magic ?


No magic at all. When you convert a pointer to an object to a pointer to
unsigned char, you can iterate over its length copying individual bytes.
You can treat any object foo as an array of sizeof(foo) unsigned chars.

-s
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet-
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!


Seebs
  Reply With Quote
Old 11-03-2009, 09:59 AM   #18
Nick Keighley
 
Posts: n/a
Default Re: void *
On 3 Nov, 07:01, Richard Heathfield <r...@see.sig.invalid> wrote:

<snip>

> Our swap algorithm focused entirely on bytes, and ignored the fact -
> never even /knew/ the fact - that it was working on doubles. Let's
> look at the result:
>
> We started with: *Float1 = 87 4B 3C 9F and Float2 = 21 55 A0 D6
> We ended up with: Float1 = 25 55 A0 D6 and Float1 = 87 4B 3C 9F
>
> The values have been swapped correctly, byte by byte.


really?

> This algorithm
> will work for any kind of object, not just floats. Not because of
> compiler magic, but because the function is data-type-blind, and
> needs only object representations to do its work.



Nick Keighley
  Reply With Quote
Old 11-03-2009, 10:27 AM   #19
Seebs
 
Posts: n/a
Default Re: void *
On 2009-11-03, Nick Keighley <> wrote:
> On 3 Nov, 07:01, Richard Heathfield <r...@see.sig.invalid> wrote:
>
><snip>
>
>> Our swap algorithm focused entirely on bytes, and ignored the fact -
>> never even /knew/ the fact - that it was working on doubles. Let's
>> look at the result:
>>
>> We started with: *Float1 = 87 4B 3C 9F and Float2 = 21 55 A0 D6
>> We ended up with: Float1 = 25 55 A0 D6 and Float1 = 87 4B 3C 9F
>>
>> The values have been swapped correctly, byte by byte.

>
> really?


I'd guess that's a typo, rather than an accurate description of an algorithm
that inexplicably flipped a bit.

-s
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet-
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!


Seebs
  Reply With Quote
Old 11-04-2009, 05:20 AM   #20
arnuld
 
Posts: n/a
Default Re: void *
> On Tue, 03 Nov 2009 07:01:50 +0000, Richard Heathfield wrote:


> No, a cast is an explicit conversion, so "implicit cast" is an oxymoron.


Wait a minute:

int i = 2.03;

that i will be assigned a value of 2. 2.03 was casted (converted ?)
implicitly to 2.



> I hope this analogy (which, being an analogy, cannot be a perfect
> parallel) will help you to understand. Here's a picture for you:


>
> .....BBBBBB.....
> ...BB......BB...
> ..BB........BB..
> .BB..........BB.
> .B...BB..BB...B.
> B...B.B..B.B...B
> B...BB....BB...B
> B..............B
> B..B........B..B
> B..B........B..B
> B...B......B...B
> .B...BBBBBB...B.
> .BB...BBBB...BB.
> ..BB........BB..
> ...BB......BB...
> .....BBBBBB.....


> .....SNIP...


That was brilliant. I understood 100% of it. Many thanks





--
www.lispmachine.wordpress.com
my email is @ the above blog.



arnuld
  Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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

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




SEO by vBSEO 3.3.2 ©2009, Crawlability, Inc.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46