Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #101780
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Newsgroups | comp.lang.c |
| Subject | Re: sizeof(x) / sizeof(x[0]) |
| Date | 2017-01-14 11:43 -0500 |
| Organization | A noiseless patient Spider |
| Message-ID | <o5dkc2$gf1$1@dont-email.me> (permalink) |
| References | <1420cd8f-e5cb-4a8f-93e6-d80a8b050650@googlegroups.com> |
On 01/14/2017 07:16 AM, Alla _ wrote:
> Hello!
>
> Please, read my explanation before answering, to show
> my mistake.
> Honestly, for some time now I was sure I have no problems
> with the statement sizeof(x) / sizeof(x[0]), usually used as
> the macro to compute the size of an array of strings. I was
> positive that I know how it works, and didn't doubt.
> Somehow today when I used this macro again I've experienced
> a confusion - how does it work, and what have I completely
> forgotten? Although shameful, I have decided to come here again
> for help on this matter.
>
> For example:
> char *array[] = {"abc", "defg", "hijklmop", NULL};
> The pointer points to an array that has 4 strings.
> sizeof(x) here will be sizeof(array) thus indicating
> the size in bytes of the whole array of strings,
> because 'array' here is used as the address of the
> first sub-element, which is 'a' (array is the same as
> array[0][0]);
>
> so sizeof(array) will give the number of bytes occupied
> by the whole array of strings, i.e. number
> of characters x 1 (which is the size of a char);
>
> the denominator sizeof(x[0]) gives the size of the
> first element of the array, i.e. the size of the first
> string, which is here "abc", so it it is 3 (3 characters,
> each 1 byte); and all other strings have different
> number of characters in them, and hence different
> number of bytes;
>
> how then sizeof(x) / sizeof(x[0]) gives a correct number
> of strings in the array (it actually does, I have tested it
> on different strings)? Please, show me my mistake.
Other people had already answered before I could find the time to
respond. However, part of what I wanted to say has not yet been
explicitly said by anyone else:
In C, a string is not a data type, it is a data format. You cannot
declare a string. There's two things that people often think of then
they think they're declaring a string:
char char_array[] = "Hello ";
char *char_ptr = "world!\n";
"Hello " and "world!\n" are string literals. They cause the creation of
an unnamed char array of sufficient length to be initialized with the
specified characters, including a terminating null character. As a
result, those arrays do contain strings. In most contexts, a string
literal is automatically converted into a pointer to the first element
of that array. The initialization of an array of character type (such as
char_array above) is NOT one of those contexts. What the standard
actually says about such things makes those definitions equivalent (if
char_array has automatic storage duration) to the following code:
char __unnamed1[] = {'H', 'e', 'l', 'l', 'o', ' ', '\0'};
char char_array[sizeof __unnamed1];
memcpy(char_array, _unnamed1, sizeof __unnamed1);
char __unnamed2[] = {'W', 'o', 'r', 'l', 'd', '!', '\n', '\0'};
char *char_ptr = unnamed2;
The equivalence breaks down for arrays with file scope, which provides
no location for the memcpy() call, or for local arrays with static
storage duration, where the memcpy() call should only occur once, before
the start of the program. As described by the standard, the copy still
occurs in those cases, there's just no strictly conforming C code that
has exactly equivalent behavior.
Note that there is no way for a strictly conforming program to determine
whether or not __unnamed1 even exists. As a result, if char_array has
static storage duration, removing __unnamed1 and just initializing
char_array directly is a common optimization:
char char_array[] = {'H', 'e', 'l', 'l', 'o', ' ', '\0'};
So, char_array is an array of char which can (but doesn't have to)
contain a string, while char_ptr is a pointer to char which can (but
doesn't have to) point at a string. Neither of those is a string itself.
You can create an array of char that does not contain a string, and a
char * pointer which points at something that is not a string, using the
following code:
char hello[6] = "Hello ";
char *greeting = hello;
That first declaration has the same net result as
char hello[6] = {'H', 'e', 'l', 'l', 'o', ' '};
which does NOT contain a terminating null character, and is therefore
not a C string. Code that is intended to read strings will start
searching for a null character, and when it doesn't find any, it will
keep searching past the end of the string. As far as the standard is
concerned, such code has undefined behavior. On real-world
implementations, the search is likely to find a terminating null
character somewhere, sooner or later, unless it first wanders into
memory that it has no permission to read.
Now let's move up to two dimensions. Your "array" is an array of char *
pointers, initialized to point at the strings contained in the unnamed
arrays corresponding to those string literals. "sizeof array" gives the
size of those pointers, but not of the strings that they point at. The
following declaration, on the other hand:
char array2d[][9] = {"abc", "defg", "hijklmop", ""};
Is equivalent to
char array2d[][9] = {
{'a', 'b', 'c', '\0'},
{'d', 'e', 'f', 'g', '\0'},
{'h', 'i', 'j', 'k', 'l', 'm', 'o', 'p', '\0'},
{'\0'}
};
Note that with this definition, "sizeof array2d" has the value of 36,
because it's got four elements, each of which contains 9 chars. This
also is NOT the total length of the strings.
char segmented_string[] = "abc\0defg\0hijklmop\0";
The array segmented_string contains all four of the strings that the
elements of your "array" pointed at, starting at segmented_string,
segmented_string+4, segmented_string+9, and segmented_string+18,
respectively. The expression "sizeof segmented_string" has a value of
19, which is the total length of those strings, including their
terminating null characters. That array also contains 15 other strings,
such as "bc", which starts at segmented_string+1, and "p", which starts
at segmented_string+16.
Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
sizeof(x) / sizeof(x[0]) Alla _ <modelling.data@gmail.com> - 2017-01-14 04:16 -0800
Re: sizeof(x) / sizeof(x[0]) "Fernando D. Bozzo" <fdbozzo@gmail.com> - 2017-01-14 04:27 -0800
Re: sizeof(x) / sizeof(x[0]) Alla _ <modelling.data@gmail.com> - 2017-01-14 04:43 -0800
Re: sizeof(x) / sizeof(x[0]) "Fernando D. Bozzo" <fdbozzo@gmail.com> - 2017-01-14 04:52 -0800
Re: sizeof(x) / sizeof(x[0]) Alla _ <modelling.data@gmail.com> - 2017-01-14 06:10 -0800
Re: sizeof(x) / sizeof(x[0]) Keith Thompson <kst-u@mib.org> - 2017-01-14 15:55 -0800
Re: sizeof(x) / sizeof(x[0]) jt@toerring.de (Jens Thoms Toerring) - 2017-01-14 13:13 +0000
Re: sizeof(x) / sizeof(x[0]) Alla _ <modelling.data@gmail.com> - 2017-01-15 22:23 -0800
Re: sizeof(x) / sizeof(x[0]) Keith Thompson <kst-u@mib.org> - 2017-01-16 08:58 -0800
Re: sizeof(x) / sizeof(x[0]) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-14 14:47 +0000
Re: sizeof(x) / sizeof(x[0]) Alla _ <modelling.data@gmail.com> - 2017-01-14 07:17 -0800
Re: sizeof(x) / sizeof(x[0]) Manfred <noname@invalid.add> - 2017-01-14 16:22 +0100
Re: sizeof(x) / sizeof(x[0]) Barry Schwarz <schwarzb@dqel.com> - 2017-01-14 08:35 -0800
Re: sizeof(x) / sizeof(x[0]) Alla _ <modelling.data@gmail.com> - 2017-01-15 22:53 -0800
Re: sizeof(x) / sizeof(x[0]) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-16 15:58 +0000
Re: sizeof(x) / sizeof(x[0]) Alla _ <modelling.data@gmail.com> - 2017-01-16 22:38 -0800
Re: sizeof(x) / sizeof(x[0]) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-17 10:11 +0000
Re: sizeof(x) / sizeof(x[0]) James Kuyper <jameskuyper@verizon.net> - 2017-01-14 11:43 -0500
Re: sizeof(x) / sizeof(x[0]) Keith Thompson <kst-u@mib.org> - 2017-01-14 16:01 -0800
Re: sizeof(x) / sizeof(x[0]) Alla _ <modelling.data@gmail.com> - 2017-01-16 01:36 -0800
Re: sizeof(x) / sizeof(x[0]) Barry Schwarz <schwarzb@dqel.com> - 2017-01-16 09:47 -0800
Re: sizeof(x) / sizeof(x[0]) James Kuyper <jameskuyper@verizon.net> - 2017-01-16 21:12 -0500
Re: sizeof(x) / sizeof(x[0]) Alla _ <modelling.data@gmail.com> - 2017-01-16 22:29 -0800
Re: sizeof(x) / sizeof(x[0]) Les Cargill <lcargill99@comcast.com> - 2017-01-14 14:27 -0600
Re: sizeof(x) / sizeof(x[0]) Keith Thompson <kst-u@mib.org> - 2017-01-14 15:52 -0800
Re: sizeof(x) / sizeof(x[0]) Lőrinczy Zsigmond <nospam@for.me> - 2017-01-15 20:20 +0100
Re: sizeof(x) / sizeof(x[0]) Keith Thompson <kst-u@mib.org> - 2017-01-15 12:55 -0800
csiph-web