Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Is there an easier way to work with pointers (sample code included)

Reply
Thread Tools

Is there an easier way to work with pointers (sample code included)

 
 
Al Balmer
Guest
Posts: n/a
 
      03-09-2006
On Wed, 08 Mar 2006 19:28:13 +0000, Flash Gordon
<(E-Mail Removed)> wrote:

>Al Balmer wrote:
>> On 8 Mar 2006 10:22:53 -0800, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
>>
>>> Is there an easier way to code the cmp procedure without going thru all
>>> the pointer manipulations?
>>>
>>> #include <stdlib.h>
>>> #include <string.h>
>>>
>>> int cmp(const void *i, const void *j)
>>> {
>>> void *p1, *p2;
>>> char **s1, **s2;
>>> p1=(void *) i;
>>> p2=(void *) j;
>>> s1=(void *) p1;
>>> s2=(void *) p2;
>>> return strcmp(*s1,*s2);
>>> }

>>
>> int cmp(const void *i, const void *j)
>> {
>> char *s1 = i;
>> char *s2 = p;

>
>Don't you mean:
> const char *s1 = i;
> const char *s2 = j;
>

Yup. <g> You can tell how often I use const. The compiler would have
reminded me.

>> return strcmp(s1, s2);
>> }
>> Is that what you're trying to do?
>>
>> BTW, please properly indent code you post. Your compiler may not care,
>> but people reading it do.

>
>Definitely.


--
Al Balmer
Sun City, AZ
 
Reply With Quote
 
 
 
 
Default User
Guest
Posts: n/a
 
      03-09-2006
Micah Cowan wrote:

> "Default User" <(E-Mail Removed)> writes:


> > In addition to what all the others have said, you should almost
> > NEVER cast away const from a pointer. That's a major indicator that
> > there's a design flaw.

>
> The exception would be when you're implementing something like
> strchr(); where you want your parameter list to indicate a guarantee
> that you won't change the string, but you don't want to force the
> caller to make that same guarantee (or do the cast there).


I guess I'm not following. You can always pass a non-const pointer
through a const parameter. The caller wouldn't need to cast, nor would
the implementer.

In the previous code, the OP had const parameters and then blithely
cast the const away inside the function.



Brian
 
Reply With Quote
 
 
 
 
Richard Heathfield
Guest
Posts: n/a
 
      03-09-2006
Default User said:

> Micah Cowan wrote:
>
>> "Default User" <(E-Mail Removed)> writes:

>
>> > In addition to what all the others have said, you should almost
>> > NEVER cast away const from a pointer. That's a major indicator that
>> > there's a design flaw.

>>
>> The exception would be when you're implementing something like
>> strchr(); where you want your parameter list to indicate a guarantee
>> that you won't change the string, but you don't want to force the
>> caller to make that same guarantee (or do the cast there).

>
> I guess I'm not following. You can always pass a non-const pointer
> through a const parameter. The caller wouldn't need to cast, nor would
> the implementer.


No, think about strchr for a second (and don't worry too much about whether
I've got the implementation right - focus on the types):

char *strchr(const char *s, int ch)
{
char *p = (char *)s; /* either you cast it here... */
while(*p != '\0' && *p != ch)
{
++p;
}
if(*p == '\0')
{
p = NULL;
}
return p;
}

char *strchr(const char *s, int ch)
{
while(*s != '\0' && *s != ch)
{
++s;
}
if(*s == '\0')
{
s = NULL;
}
return (char *)s; /*... or you cast it here */
}

> In the previous code, the OP had const parameters and then blithely
> cast the const away inside the function.


Sure, and your point was perfectly valid. I think we're moving on a bit from
there now.


--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
 
Reply With Quote
 
pete
Guest
Posts: n/a
 
      03-09-2006
(E-Mail Removed) wrote:
>
> Is there an easier way to code the cmp procedure without going thru all
> the pointer manipulations?
>
> #include <stdlib.h>
> #include <string.h>
>
> int cmp(const void *i, const void *j)
> {
> void *p1, *p2;
> char **s1, **s2;
> p1=(void *) i;
> p2=(void *) j;
> s1=(void *) p1;
> s2=(void *) p2;
> return strcmp(*s1,*s2);
> }
>
> int main(void)
> {
> char string0[]="zebra";
> char string1[]="hello";
> char string2[]="goodbye";
>
> char *base[3];
>
> base[0]=(char *)string0;
> base[1]=(char *)string1;
> base[2]=(char *)string2;
>
> printf("\nbase[0] %s",base[0]);
> printf("\nbase[1] %s",base[1]);
> printf("\nbase[2] %s\n",base[2]);
>
> qsort(&base,3,sizeof(base[0]),(void *)cmp);
>
> printf("\nbase[0] %s",base[0]);
> printf("\nbase[1] %s",base[1]);
> printf("\nbase[2] %s\n",base[2]);
> }


/* BEGIN new.c */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int cmp(const void *i, const void *j)
{
return strcmp(i, j);
}

int main(void)
{
char string0[] = "zebra";
char string1[] = "hello";
char string2[] = "goodbye";
char *base[3];

base[0] = string0;
base[1] = string1;
base[2] = string2;
printf("base[0] %s\n", base[0]);
printf("base[1] %s\n", base[1]);
printf("base[2] %s\n", base[2]);
putchar('\n');
qsort(base, sizeof base / sizeof*base, sizeof*base, cmp);
printf("base[0] %s\n",base[0]);
printf("base[1] %s\n",base[1]);
printf("base[2] %s\n",base[2]);
return 0;
}

/* END new.c */


--
pete
 
Reply With Quote
 
August Karlstrom
Guest
Posts: n/a
 
      03-09-2006
(E-Mail Removed) wrote:
> Is there an easier way to code the cmp procedure without going thru all
> the pointer manipulations?
>
> #include <stdlib.h>
> #include <string.h>
>
> int cmp(const void *i, const void *j)
> {
> void *p1, *p2;
> char **s1, **s2;
> p1=(void *) i;
> p2=(void *) j;
> s1=(void *) p1;
> s2=(void *) p2;
> return strcmp(*s1,*s2);
> }
>
> int main(void)
> {
> char string0[]="zebra";
> char string1[]="hello";
> char string2[]="goodbye";
>
> char *base[3];
>
> base[0]=(char *)string0;
> base[1]=(char *)string1;
> base[2]=(char *)string2;
>
> printf("\nbase[0] %s",base[0]);
> printf("\nbase[1] %s",base[1]);
> printf("\nbase[2] %s\n",base[2]);
>
> qsort(&base,3,sizeof(base[0]),(void *)cmp);
>
> printf("\nbase[0] %s",base[0]);
> printf("\nbase[1] %s",base[1]);
> printf("\nbase[2] %s\n",base[2]);
> }


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define COUNT 3
#define MAX_LEN 32

char strings[COUNT][MAX_LEN] = {"zebra", "hello", "goodbye"};

void show(char strings[][MAX_LEN])
{
int k;

for (k = 0; k < COUNT; k++) printf("%s, ", strings[k]);
printf("\n");
}


int main(void)
{
show(strings);
qsort(strings, COUNT, MAX_LEN,
(int (*)(const void *, const void *)) strncmp);
show(strings);
return 0;
}


August

--
I am the "ILOVEGNU" signature virus. Just copy me to your
signature. This email was infected under the terms of the GNU
General Public License.
 
Reply With Quote
 
Peter Nilsson
Guest
Posts: n/a
 
      03-09-2006
pete wrote:
>
> /* BEGIN new.c */
>
> #include <stdlib.h>
> #include <string.h>
> #include <stdio.h>
>
> int cmp(const void *i, const void *j)
> {
> return strcmp(i, j);
> }
>
> int main(void)
> {
> char string0[] = "zebra";
> char string1[] = "hello";
> char string2[] = "goodbye";
> char *base[3];
>
> base[0] = string0;
> base[1] = string1;
> base[2] = string2;
> printf("base[0] %s\n", base[0]);
> printf("base[1] %s\n", base[1]);
> printf("base[2] %s\n", base[2]);
> putchar('\n');
> qsort(base, sizeof base / sizeof*base, sizeof*base, cmp);
> printf("base[0] %s\n",base[0]);
> printf("base[1] %s\n",base[1]);
> printf("base[2] %s\n",base[2]);
> return 0;
> }
>
> /* END new.c */


One thing that AFAIK hasn't been pointed out in the thread is there is
no language guarantee that this will sort the strings into the order:

goodbye
hello
zebra

--
Peter

 
Reply With Quote
 
Default User
Guest
Posts: n/a
 
      03-09-2006
Richard Heathfield wrote:

> Default User said:


> > I guess I'm not following. You can always pass a non-const pointer
> > through a const parameter. The caller wouldn't need to cast, nor
> > would the implementer.


> return (char *)s; /*... or you cast it here */


Bah, I didn't think it through to the return. Never mind.




Brian
 
Reply With Quote
 
Malcolm
Guest
Posts: n/a
 
      03-09-2006
"Richard Heathfield" <(E-Mail Removed)> wrote
> No, think about strchr for a second (and don't worry too much about
> whether
> I've got the implementation right - focus on the types):
>
> char *strchr(const char *s, int ch)
>

This is where the hacked in status of const as a late addition to the
language beocmes apparent.
const should taint everything it points to, and all pointers derived from
it. But that would be a major reengineering exercise.
--
Buy my book 12 Common Atheist Arguments (refuted)
$1.25 download or $6.90 paper, available www.lulu.com


 
Reply With Quote
 
Jordan Abel
Guest
Posts: n/a
 
      03-09-2006
On 2006-03-09, Malcolm <(E-Mail Removed)> wrote:
> "Richard Heathfield" <(E-Mail Removed)> wrote
>> No, think about strchr for a second (and don't worry too much about
>> whether
>> I've got the implementation right - focus on the types):
>>
>> char *strchr(const char *s, int ch)
>>

> This is where the hacked in status of const as a late addition to the
> language beocmes apparent.
> const should taint everything it points to, and all pointers derived from
> it. But that would be a major reengineering exercise.


typeof would allow this, after a fashion:

#define strchr(x,c) (typeof x)strchr(x,c)
 
Reply With Quote
 
David Holland
Guest
Posts: n/a
 
      03-09-2006
On 2006-03-09, pete <(E-Mail Removed)> wrote:
> [...]
> int cmp(const void *i, const void *j)
> {
> return strcmp(i, j);
> }
>
> [...]
> char *base[3];
> base[0] = string0;
> base[1] = string1;
> base[2] = string2;
> [...]
> qsort(base, sizeof base / sizeof*base, sizeof*base, cmp);


Several people have posted code like this now, all apparently without
noticing that it's wrong.

base is an array of pointers to char. This is passed to qsort. qsort
calls cmp with two pointers, each of which points *to an element of
the array*.

Those void *'s in the argument of cmp are "really" char **, not char *,
and passing them to strcmp produces undefined behavior.

It so happens that you (and the OP) have laid out the program so that
on most platforms strcmp will reach a zero byte somewhere before
faulting, and the conventional layout of automatic storage is such
that strcmp interpreting the addresses as strings will generate the
expected output sort order, so just running the program once to check
it is misleading.

cmp needs to be

int cmp(const void *i0, const void *j0) {
const char *const *i = i0;
const char *const *j = j0;
return strcmp(*i, *j);
}

HTH.

--
- David A. Holland
(the above address works if unscrambled but isn't checked often)
 
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
There must be an easier way Jim S HTML 3 02-15-2007 02:39 AM
Is there an easier way to express this list slicing? John Henry Python 19 12-01-2006 08:30 AM
Hash of Structs in a Package, is there an easier way? Norman Ackroyd Perl 1 07-28-2004 11:54 AM
Is there an easier way to break a list into sub groups MetalOne Python 4 02-22-2004 09:58 PM
Defrag XP There must be an easier way. ChrisTOE@address.invalid Computer Support 4 01-19-2004 03:41 AM



Advertisments