473,386 Members | 1,741 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

FAQ 13.8, comparing strings

On Mon, 28 Apr 2008 07:25:53 +0000, Richard Heathfield wrote:

#include <string.h>
int p_strcmp(const void *pv1, const void *pv2)
{
char * const * v1 = pv1;
char * const * v2 = pv2;
return strcmp(*v1, *v2);
}

Either you are not understanding me or I am not able to understand this
<p_strcmpthing. This is your code:

compare these 2 paragraphs:

In theory, you get a <pointer to const voidand you use it to initialize
a <pointer to a const pointer to char. In practice, you get a <pointer
to a pointer to charand you are using it to initialize a <pointer to a
const pointer to charand then dereference it to a <const pointer to
char>.
Because you already know that the input argument will be <char**so we
can simply dereference it and get a <char*which could be used for
<strcmpsince <strcmpdoes not require a <const pointer>. Hence It
could be simply this:
int p_strcmp(const void *pv1, const void *pv2)
{
return strcmp(*pv1, *pv2);
}
I need explanation on this as it<p_strcmpcode is biting me
from the very 1st day I saw it in section 13.8 of the FAQ and I still
can't seem to comprehend the WHY of it.

--
http://lispmachine.wordpress.com/
my email ID is at the above address
--
http://lispmachine.wordpress.com/
my email ID is at the above address

Jun 27 '08 #1
7 1404
On Apr 28, 7:00 pm, arnuld <NoS...@NoPain.comwrote:
On Mon, 28 Apr 2008 07:25:53 +0000, Richard Heathfield wrote:
#include <string.h>
int p_strcmp(const void *pv1, const void *pv2)
{
char * const * v1 = pv1;
char * const * v2 = pv2;
return strcmp(*v1, *v2);
}

Either you are not understanding me or I am not able to understand this
<p_strcmpthing. This is your code:

compare these 2 paragraphs:

In theory, you get a <pointer to const voidand you use it to initialize
a <pointer to a const pointer to char. In practice, you get a <pointer
to a pointer to charand you are using it to initialize a <pointer to a
const pointer to charand then dereference it to a <const pointer to
char>.

Because you already know that the input argument will be <char**so we
/You/ do know that. The compiler doesn't. In your code you dereference
a void * pointer and then use its value, which is not possible in ISO
C.
can simply dereference it and get a <char*which could be used for
How do you get a char * if you dereference a void *?
<strcmpsince <strcmpdoes not require a <const pointer>. Hence It
could be simply this:

int p_strcmp(const void *pv1, const void *pv2)
{
return strcmp(*pv1, *pv2);
Here, you dereference a void pointer as I said before. This void *
pointer is given the value of a char ** pointer. That's why RH assigns
it to such pointer, and then dereferences it. Consider this:

#include <stdio.h>
int f(void *p);
int main(void) {
int i = 10;
int *k = &i;
printf("%d\n", f(&k)); // pass address of int *, type is int **
return 0;
}
int f(void *p) {
int **i = p; // p points to an int **
return **i + 10;
}

It's the same thing.

P.S. Your signature appeared twice.
Jun 27 '08 #2
On Mon, 28 Apr 2008 04:11:11 -0700, vippstar wrote:
#include <stdio.h>
int f(void *p);
int main(void) {
int i = 10;
int *k = &i;
printf("%d\n", f(&k)); // pass address of int *, type is int **
return 0;
}
int f(void *p) {
int **i = p; // p points to an int **
return **i + 10;
}

It's the same thing.
O...K..A..Y....

Now I got it. <void*is a compile-time phenomenon which , actually,
helps a lot as run-time phenomenon because in many cases we could know
the types only at run-time.
Right ?
still one questions remains:
#include <string.h>
int p_strcmp(const void *pv1, const void *pv2)
{
char * const * v1 = pv1;
char * const * v2 = pv2;
return strcmp(*v1, *v2);
}
I can use <char** v1 = pv1or <const char** v1 = pv1>

why use <char *const *v1 = pv1?


--
http://lispmachine.wordpress.com/
my email ID is at the above address

Jun 27 '08 #3
arnuld said:
>On Mon, 28 Apr 2008 04:11:11 -0700, vippstar wrote:
>#include <stdio.h>
int f(void *p);
int main(void) {
int i = 10;
int *k = &i;
printf("%d\n", f(&k)); // pass address of int *, type is int **
return 0;
}
int f(void *p) {
int **i = p; // p points to an int **
return **i + 10;
}

It's the same thing.

O...K..A..Y....

Now I got it. <void*is a compile-time phenomenon which , actually,
helps a lot as run-time phenomenon because in many cases we could know
the types only at run-time.
Right ?
still one questions remains:
#include <string.h>
int p_strcmp(const void *pv1, const void *pv2)
{
char * const * v1 = pv1;
char * const * v2 = pv2;
return strcmp(*v1, *v2);
}
I can use <char** v1 = pv1or <const char** v1 = pv1>
Not correctly. Neither of those forms is compatible with const void *.
why use <char *const *v1 = pv1?
Think abstractly.

Let's say you have an array of objects of type T that you wish to qsort:

T foo[N] = {0};

populate(foo, N); /* get some values */

qsort(foo, N, sizeof foo[0], foocmp);

Whenever qsort needs to compare two objects, it will call foocmp, passing
it pointers to two elements in the foo array. Since these elements will be
of type T, the pointers will be of type T *. Since qsort's fourth
parameter is of type int (*)(const void *, const void *), foocmp must be
the name of (or at least a pointer to) a function of type int(const void
*, const void *) - so the parameters are required to be const-qualified.

We can convert the parameters back into the proper type like this:

const T *p1 = vp1;
const T *p2 = vp2;

or like this:

T const *p1 = vp1;
T const *p2 = vp2;

The two type forms are equivalent, and both mean "pointer to const T".

Plugging in char * in place of T, however, is complicated by the * in "char
*". We need "pointer to const pointer to char". So we can't do this:

const char * *p1 = vp1;

because that means "pointer to pointer to const char".

But we /can/ plug in directly to the second form:

char * const *p1 = vp1;

because /that/ means "pointer to const pointer to char", which is exactly
what we need.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 27 '08 #4
arnuld wrote:

<snip>
Now I got it. <void*is a compile-time phenomenon which , actually,
helps a lot as run-time phenomenon because in many cases we could
know the types only at run-time.
<snip>

Can you clarify this? What do you mean by "compile-time phenomenon"
and "run-time phenomenon"?

Jun 27 '08 #5
santosh wrote:
arnuld wrote:
Now I got it. <void*is a compile-time phenomenon which,
actually, helps a lot as run-time phenomenon because in
many cases we could know the types only at run-time.

<snip>

Can you clarify this? What do you mean by "compile-time
phenomenon" and "run-time phenomenon"?
Sounds like the OP is drawing the distinction between object
type, which is known at compile time since C is statically
typed, and an object's effective type which need only be
known at runtime.

--
Peter
Jun 27 '08 #6
On Mon, 28 Apr 2008 17:44:53 +0530, santosh wrote:
Can you clarify this? What do you mean by "compile-time phenomenon"
and "run-time phenomenon"?

of course :) . This is just what I came to think of about types in C. If
am wrong, poke me in the eye ;)

<void*points to no type, practically.

Lets us say that a C program asks the user for input, I can not enter some
words at standard input and make them of type <void>, they can be stored
in <array of charbut not in <array of void>. Section 13.8 of FAQ has a
function for comparing strings called <p_strcmpwhich compiles fine
and takes 2 <const void*as arguments. At run-time, for example, either
a <char*or even a <char**can be given as input and <void*will
handle them gracefully but I can not give a <void* to it as argument at
run-time. The input has to be of some type, to be useful to be processed
by the program.
Hence, <voidtype exists at compile-time for the kind of input we do not
know the type of yet but at run-time I can not make any input as of
<voidtype.

--
http://lispmachine.wordpress.com/
my email ID is at the above address

Jun 27 '08 #7
arnuld wrote:
int p_strcmp(const void *pv1, const void *pv2)
{
char * const * v1 = pv1;
char * const * v2 = pv2;
return strcmp(*v1, *v2);
}
I can use <char** v1 = pv1or <const char** v1 = pv1>

why use <char *const *v1 = pv1?
The const or volatile qualifier applies to the left, with the exception of
when it is at the leftmost part of a declaration, then it applies to the
right. For consistency, I would therefore suggest that you drop the habit
of writing things like this:

const char* p;

in favour of this:

char const* p;

Now, you can read this from right to left, i.e. 'p' is a pointer to a
constant 'char'. Getting back to the above example, you then have

const void *pv1

which I would rather write as

void const* pv1

Then, you simply replace the placeholder type 'void' with the real type of
the array (I guess it's about sorting with qsort()), and that is 'char*'
(note: without any const!):

char* const* pv1

This then reads 'pv1' is a pointer to a const pointer to a 'char'. This
basically means that you can not redirect the pointer to anywhere else,
i.e. an expression like this will fail to compile:

*pv1 = "foo";

Note that I personally would have added another const:

char const* const* pv1

This then also prevents accidental modification of the string it points to,
but for the general principle of converting between typed and typeless
pointers and back this isn't necessary.
BTW:
Some really paranoid people would even have added another const there:

char const* const* const pv1

I wouldn't do so here, but in general it helps in other situations like
this:

float const pi2 = acosf(0.0f);
... // LOTS of code
... // use pi2 here

The point is that from the declaration you already _know_ that pi2 isn't
changed anywhere in between. Not only that, even if you tried to change it
accidentally, you would get a compiler error. The problem with this is that
many C compilers don't allow you (according to C89) to define variables in
the middle of a block, only at the beginning.

cheers

Uli

Jun 27 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: beliavsky | last post by:
By mistake I coded something like print ("1" > 1) and got the result "True". Comparing an integer and a string seems meaningless to me, and I would prefer to have an exception thrown. Can...
6
by: BrianJones | last post by:
I have a problem with the int strcmp(str1,str2) function: When I do: char *pass; char *passv; pass = getpass("Please enter....."); passv = getpass("Please verify.....");
3
by: Robert Dell | last post by:
I have a problem comparing strings in an order form i'm writing. I want to give a running total at the bottom of the page and it appears to be working except it doesn't compare correctly (it...
1
by: Reg Rat | last post by:
Hello all, I'm led to believe that the .Net framework offers intelligent string comparison such that é follows e in an alphabetic sort rather than appearing after z, for example. Does this mean...
4
by: rossum | last post by:
I was comparing strings, as one does: stringA.CompareTo(stringB) == -1 Then I thought that this was not as easy to read as it could be, wouldn't it be clearer to write: stringA < stringB ...
1
by: Jetboy555 | last post by:
Sample input: 2000 Georgia Tech 30 Virginia 20 1999 Virginia 20 Virginia tech My Problem is in taking the input in correctly. I take the year in correctly, but i'm having trouble with the...
6
by: cutlass | last post by:
Need help in thus script. Trying to create the script that uses comparison operators and functions to compare two strings entered by user. When I add in the info in the script section everything...
5
by: =?Utf-8?B?UElFQkFMRA==?= | last post by:
Not really a C#-specific comment, more general .net observations. 1) A while back I found the need to determine whether or not a particular StringComparer was case-insensitive. The best way I...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.