How to get array size from a pointer?

C

CBFalconer

Nate said:
CBFalconer said:
It's part of a test and I'm stumped. There is a function

void foo(char **x)

The function signature is given and cannot be changed, so no passing
of other values. The test case involves defining this variable:

char *y[] = { /* bunch of stuff */ }

and calling

foo(y)

In the above, "bunch of stuff" is a series of triplets, two
strings followed by a null string (""). However, the last
triplet ends with an integer 0. This seems that it's supposed
to signify the end of the array. However, it appears to me that
0 is the same binary value as for the empty string (NUL, \0,
whatever). So in effect, one cannot test for it as a sentry
value because it's actually the same as the preceding triplets.

Maybe "bunch of stuff" is that, but y is not. y is an array of
pointers to char, and those pointers also point to char arrays
that are not writeable. The arrays are strings, with a '\0'
terminal char. The last string is an empty string, and is used
to mark the end of the array.

Now consider what foo is. It appears, from your definition, to
be a function that returns void (i.e. nothing). It also
requires a parameter, x, which is a pointer to a char pointer.

Combining those things, the call to foo(y) cannot possibly do
anything.

Um? Here are some possible definitions for foo that do things.

void foo(char **x) { x[3] = "Hi mom!"; }
void foo(char **x) { while (*x) puts(*x++); }
void foo(char **x) { errno = EDOOFUS; }
void foo(char **x) { longjmp(somewhere); }
void foo(char **x) { abort(); }

In other words you want to use globals and side-effects. I should
have specified further.
 
V

vippstar

Um? Here are some possible definitions for foo that do things.

void foo(char **x) { x[3] = "Hi mom!"; }
void foo(char **x) { while (*x) puts(*x++); }
void foo(char **x) { errno = EDOOFUS; }
void foo(char **x) { longjmp(somewhere); }

Well, longjmp takes two arguments...
 
V

vippstar

Um? Here are some possible definitions for foo that do things.
void foo(char **x) { x[3] = "Hi mom!"; }
void foo(char **x) { while (*x) puts(*x++); }
void foo(char **x) { errno = EDOOFUS; }
void foo(char **x) { longjmp(somewhere); }

Well, longjmp takes two arguments...


Also, foo belongs in the programmers namespace, but EDOOFUS in the
implementations namespace, so the penultimate function can't work.
 
B

Ben Bacarisse

CBFalconer said:
Nate said:
CBFalconer <[email protected]> writes:
Now consider what foo is. It appears, from your definition, to
be a function that returns void (i.e. nothing). It also
requires a parameter, x, which is a pointer to a char pointer.

Combining those things, the call to foo(y) cannot possibly do
anything.

Um? Here are some possible definitions for foo that do things.

void foo(char **x) { x[3] = "Hi mom!"; }
void foo(char **x) { while (*x) puts(*x++); }
void foo(char **x) { errno = EDOOFUS; }
void foo(char **x) { longjmp(somewhere); }
void foo(char **x) { abort(); }

In other words you want to use globals and side-effects. I should
have specified further.

Programming in C without side effects is almost impossible. Even if
we add the extra condition that all the x point to unmodifiable
arrays (a restriction that Nate Eldredge's examples comply with) then
foo can still be useful. A clearer example might be

void sort_strings(char **x)
{
qsort(x, count_strings(x), sizeof *x, sptr_cmp);
}

where count_strings is the function the OP was originally asking
about and sptr_cmp compares strings when passed void *s that point at
pointers to these strings.

There are lots of useful functions with the same prototype as foo.
 
D

David Resnick

Um?  Here are some possible definitions for foo that do things.
void foo(char **x) { x[3] = "Hi mom!"; }
void foo(char **x) { while (*x) puts(*x++); }
void foo(char **x) { errno = EDOOFUS; }
void foo(char **x) { longjmp(somewhere); }
Well, longjmp takes two arguments...

Also, foo belongs in the programmers namespace, but EDOOFUS in the
implementations namespace, so the penultimate function can't work.

I think this is wrong. It can work. Either the implementation can
define EDOOFUS, which is just fine, or user code can define it if it
is not defined, also fine. It is generally a good idea NOT to start
your macros E[digit|uppercase] as it conflicts with a "future
direction" of a header. But the standard doesn't have language like
"reserved for any use", like leading __. But it is as far as I can
see legal and portable to put this in your code...

#include <errno.h>
#ifndef EDOOFUS
#define EDOOFUS 42
#endif

-David
 
L

lawrence.jones

Richard Bos said:
No, it needs a situation where there is no difference between "doesn't
exist" and "is blank". Those situations are rarer than most people, even
most programmers with no database experience, believe.

Even programmers *with* database experience. Oracle, for example,
continues to treat empty string values and nulls identically, although
they have warned (forever) that that could change some time in the
future. I've run into way too much code that depends on that
equivalence and doesn't work when ported to a different db that does
distinguish.
 
M

Martien Verbruggen

[snip]
Also, foo belongs in the programmers namespace, but EDOOFUS in the
implementations namespace, so the penultimate function can't work.

I think this is wrong. It can work. Either the implementation can
define EDOOFUS, which is just fine,

And, in fact, there are implementations that do exactly that.

Martien
 
R

Richard Bos

Even programmers *with* database experience. Oracle, for example,
continues to treat empty string values and nulls identically, although
they have warned (forever) that that could change some time in the
future.

Now, I'm not much of an SQL expert, certainly not compared to the people
at Oracle, but... isn't that illegal?

Richard
 
C

CBFalconer

Richard said:
(e-mail address removed) wrote:
.... snip ...


Now, I'm not much of an SQL expert, certainly not compared to
the people at Oracle, but... isn't that illegal?

No, it isn't. First, they can certainly design their own functions
in any fashion they wish. Second, even if implementing C standard
functions, this is simply imposing a definition for 'undefined
behavior' on THEIR system.
 
K

Keith Thompson

CBFalconer said:
No, it isn't. First, they can certainly design their own functions
in any fashion they wish. Second, even if implementing C standard
functions, this is simply imposing a definition for 'undefined
behavior' on THEIR system.

I think Richard's question was about SQL, not about C.

In the interest of redirecting the question to a more appropriate
place, <http://en.wikipedia.org/wiki/Sql_null> seems to provide an
answer; see 9.1, "Common mistakes".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top