How to take the size of a pointer to array.

K

Keith Thompson

jaysome said:
On 29 Aug 2006 19:06:09 -0700, "(e-mail address removed)" <[email protected]>
wrote in comp.lang.c:


Chad wrote:
Given the following code

string_len = strlen(msg_list[0]);
(void)printf("1st element is %ld char long", string_len);

This of course produces undefined behavior, unless of course size_t is
typedef'ed to unsigned long on your platform.
^^^^^^^^^^^^^
Don't you mean "signed long" or just plain old "long"? The conversion
specifier for "unsigned long" is "%lu", not "%ld".

size_t is guaranteed to be an unsigned type. The most portable way to
print a size_t value is to cast it to unsigned long and use "%lu". By
"most portable", I mean that it works in C90, which doesn't have
"%zu".
I did not cast it knowing that size_t is defined on my box as unsigned
long.
And since I could just see the size of the object, I didn't bother. I
knew it wasn't going to exceed the size of signed long. I was lazy.

But if size_t is *smaller* than unsigned long, it still invokes
undefined behavior.
The two correct ways to cast this thing would have been:

pre-c99:

printf("%lu", (unsigned long)string_len);

c99:

printf("%zu", string_len);

Right. But it's not uncommon to have a compiler that supports most of
C99, but a runtime library whose printf() implementation doesn't
recognize "%zu". (The compiler and the C library are sometimes
provided by different vendors.)
The odd thing about the pre-c99 cast is that we have to assume a type
for size_t. This is where this argument gets odd. The compiler I use
isn't completely c99 compliant, so I cannot use the c99 example above.
However, it's difficult to argue that size_t will not all ways be
unsigned long because you would have to change your printf typecasts to
make your code portable between architectures.

This:

printf("%lu", (unsigned long)string_len);

doesn't actually assume anything about the underlying type for size_t.
It's guaranteed to work if size_t is no bigger than unsigned long.
For example, if unsigned int and unsigned long are 32 and 64 bits,
respectively, and size_t is unsigned int, the above will still work.

In C90, unsigned long is the largest unsigned integer type, so the
printf above cannot fail. In C99, it's possible that size_t could be
unsigned long long (which *might* be bigger than unsigned long), or it
could be some extended integer type (though implementers are *advised*
to make size_t no bigger than unsigned long). Even in that unusual
case, the above will cause problems only if the value of string_len
happens to exceed ULONG_MAX (which is at least 4294967295), and even
then the conversion from size_t to unsigned long yields a well-defined
(but numerically incorrect) result.
 
K

Keith Thompson

Chad said:
Given the following code

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

int main(void) {

char *msg_list[] = {" apple", " orange", " grape" };

printf("name: %s \n", msg_list[0]);
printf("size: %d \n", sizeof(msg_list));

return 0;
}

I thought taking sizeof(msg_list) would give me the size of the string
"apple" (ie 6). Instead, I get
the following:

name: apple
size: 12

What I'm missing here?

You're missing the fact that a pointer doesn't store the size of what
it points to.

If a pointer of type foo* points to a single object of type foo, then
you can obviously get the size of the single pointed-to object with
"sizeof *ptr". But if the pointer points to the first element of an
array of foo, there's no direct way to determine the size of the array
given the pointer.

If the array somehow encodes its own size, you can use that. For
example, if it's a string you can use strlen() (and add 1 to account
for the trailing '\0'). But that's not *necessarily* the allocated
size. For example:

char s[100] = "apple";
char *p = s;

"strlen(p) + 1" gives you 6, but the actually allocated size of the
array is 100 bytes.

In general, you just have to keep track of it yourself. If you
allocated the array with malloc(), for example, you knew the size when
you allocated it; just don't forget that information.
 

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
474,434
Messages
2,571,691
Members
48,796
Latest member
Greg L.

Latest Threads

Top