Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #101737 > unrolled thread

sizeof(x) / sizeof(x[0])

Started byAlla _ <modelling.data@gmail.com>
First post2017-01-14 04:16 -0800
Last post2017-01-15 12:55 -0800
Articles 20 on this page of 27 — 10 participants

Back to article view | Back to comp.lang.c


Contents

  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

Page 1 of 2  [1] 2  Next page →


#101737 — sizeof(x) / sizeof(x[0])

FromAlla _ <modelling.data@gmail.com>
Date2017-01-14 04:16 -0800
Subjectsizeof(x) / sizeof(x[0])
Message-ID<1420cd8f-e5cb-4a8f-93e6-d80a8b050650@googlegroups.com>
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. 

Thank you!

[toc] | [next] | [standalone]


#101740

From"Fernando D. Bozzo" <fdbozzo@gmail.com>
Date2017-01-14 04:27 -0800
Message-ID<ae7bd432-5100-43df-8501-ae4f8e4f8f5e@googlegroups.com>
In reply to#101737
El sábado, 14 de enero de 2017, 13:16:37 (UTC+1), Alla _  escribió:
> 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. 
> 
> Thank you!

Hi:

How is related "x" to "array"? Can you post how are you assigning x?

[toc] | [prev] | [next] | [standalone]


#101743

FromAlla _ <modelling.data@gmail.com>
Date2017-01-14 04:43 -0800
Message-ID<388bc5e2-01fd-49a3-8814-9e438d1ae07c@googlegroups.com>
In reply to#101740
On Saturday, January 14, 2017 at 3:27:34 PM UTC+3, Fernando D. Bozzo wrote:
> El sábado, 14 de enero de 2017, 13:16:37 (UTC+1), Alla _  escribió:
> > 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. 
> > 
> > Thank you!
> 
> Hi:
> 
> How is related "x" to "array"? Can you post how are you assigning x?

Here is the macro (I have not posted it assuming people know it, sorry):
#define ARRAY_SIZE(x) ( sizeof(x) / sizeof(x[0]) )

[toc] | [prev] | [next] | [standalone]


#101745

From"Fernando D. Bozzo" <fdbozzo@gmail.com>
Date2017-01-14 04:52 -0800
Message-ID<201446a6-fb70-4e5a-b5ed-fca27d9c8551@googlegroups.com>
In reply to#101743
El sábado, 14 de enero de 2017, 13:43:16 (UTC+1), Alla _  escribió:
<snip> 
> Here is the macro (I have not posted it assuming people know it, sorry):
> #define ARRAY_SIZE(x) ( sizeof(x) / sizeof(x[0]) )

Oh, surely all people here knows this, but I'm new :)

[toc] | [prev] | [next] | [standalone]


#101755

FromAlla _ <modelling.data@gmail.com>
Date2017-01-14 06:10 -0800
Message-ID<ae27a11c-ba52-4aba-ae71-cf57b3ff5928@googlegroups.com>
In reply to#101745
On Saturday, January 14, 2017 at 3:52:21 PM UTC+3, Fernando D. Bozzo wrote:
> El sábado, 14 de enero de 2017, 13:43:16 (UTC+1), Alla _  escribió:
> <snip> 
> > Here is the macro (I have not posted it assuming people know it, sorry):
> > #define ARRAY_SIZE(x) ( sizeof(x) / sizeof(x[0]) )
> 
> Oh, surely all people here knows this, but I'm new :)

oops ) Sorry ) But, anyway, I assume you know much more than I do;
my messages are considered sort of an eyesore here, and I am grateful
for a lot of people who still help me ) I am sure you will enjoy this group.

[toc] | [prev] | [next] | [standalone]


#101828

FromKeith Thompson <kst-u@mib.org>
Date2017-01-14 15:55 -0800
Message-ID<ln4m11i4d4.fsf@kst-u.example.com>
In reply to#101745
"Fernando D. Bozzo" <fdbozzo@gmail.com> writes:
> El sábado, 14 de enero de 2017, 13:43:16 (UTC+1), Alla _  escribió:
> <snip> 
>> Here is the macro (I have not posted it assuming people know it, sorry):
>> #define ARRAY_SIZE(x) ( sizeof(x) / sizeof(x[0]) )
>
> Oh, surely all people here knows this, but I'm new :)

That's certainly a reasonable definition for that macro, but since
there's no such macro in the standard it is important to be explicit.
Minor variations in how it's defined could be significant.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#101748

Fromjt@toerring.de (Jens Thoms Toerring)
Date2017-01-14 13:13 +0000
Message-ID<edumfuF7genU1@mid.uni-berlin.de>
In reply to#101737
Alla _ <modelling.data@gmail.com> wrote:
> 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. 

The whole thing works for all kinds of arrays, not
just for "arrays of strings" (which is a name that
is a bit problemtic, see below). So better start of
with something simpler, e.g. an array of ints:

int x[] = {1, 2, 3, 4};

As you write, sizeof(x) is the number of bytes this
array occupies. And sizeof(x[0]) (or sizeof(x[1])
as well) gives you the size in bytes of one of the
elements of the array. Dividing them gives you the
number of elements of the array 'x', obviously.

What you call an "array of strings"

char *x[] = {"abc", "defg", "hijklmop", NULL};

is actually an array of char pointers. Due to the
initialization its first three elements are set to
point to "string literals" (i.e. strings that you
can't modify and for which the compiler reserved
memory somewhere in the data part of the program),
and the last element isn't even anything like a
string, but a NULL pointer (remember, a string is
nothing but a char array that contains a '\0' cha-
racter somewhere).

Now sizeof(x[0]) is the size of one of these ele-
ments, i.e. the size of a char pointer. And if you
divide sizeof(x) by sizeof(x[0]) you again get the
number of elements of this array, i.e. how many
char pointers you can store in that array. If all
the pointers point to strings you could loosely
say that it's the number of strings stored in that
array. But better always keep in mind that there are
no strings stored in it butmerely char pointers. And
these pointers not necessarily point to strings, with
e.g.

char c1 = 'a', c2 = 'b', c3 = 'c';
char *x[] = {&c1, &c2, &c3, NULL};

'x' is also an array of char pointers, but non of
its elements point to strings. So calling it an
array of strings would be extremely misleading.

Also: make sure that you only try to use this
"trick" in cases where the array is defined in
the scope where you use it! E.g. this

static void foo(int *y) {
      printf("%d", (int) (sizeof(y) / sizeof(y[0])));
}

int main(void) {
    int x[] = {1, 2, 3, 4};
    foo(x);
    return 0;
}

will fail! The reason is that nothing in function
foo() "knows" that the argument 'y' it received
is pointing to an array, so in that function
sizeof(y) is just the size of an int pointer, not
the size of the array 'x' you defined in main().
And thus the result of dividing it by the size of
an int is nothing that would make much sense.

                         Regards, Jens
-- 
  \   Jens Thoms Toerring  ___      jt@toerring.de
   \__________________________      http://toerring.de

[toc] | [prev] | [next] | [standalone]


#101921

FromAlla _ <modelling.data@gmail.com>
Date2017-01-15 22:23 -0800
Message-ID<c17aad24-fddc-4ef9-a0e2-16d5f7716292@googlegroups.com>
In reply to#101748
On Saturday, January 14, 2017 at 4:13:43 PM UTC+3, Jens Thoms Toerring wrote:
> Alla _ <modelling.data@gmail.com> wrote:
> > 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. 
> 
> The whole thing works for all kinds of arrays, not
> just for "arrays of strings" (which is a name that
> is a bit problemtic, see below). So better start of
> with something simpler, e.g. an array of ints:
> 
> int x[] = {1, 2, 3, 4};
> 
> As you write, sizeof(x) is the number of bytes this
> array occupies. And sizeof(x[0]) (or sizeof(x[1])
> as well) gives you the size in bytes of one of the
> elements of the array. Dividing them gives you the
> number of elements of the array 'x', obviously.
> 
> What you call an "array of strings"
> 
> char *x[] = {"abc", "defg", "hijklmop", NULL};
> 
> is actually an array of char pointers. Due to the
> initialization its first three elements are set to
> point to "string literals" (i.e. strings that you
> can't modify and for which the compiler reserved
> memory somewhere in the data part of the program),
> and the last element isn't even anything like a
> string, but a NULL pointer (remember, a string is
> nothing but a char array that contains a '\0' cha-
> racter somewhere).
> 
> Now sizeof(x[0]) is the size of one of these ele-
> ments, i.e. the size of a char pointer. And if you
> divide sizeof(x) by sizeof(x[0]) you again get the
> number of elements of this array, i.e. how many
> char pointers you can store in that array. If all
> the pointers point to strings you could loosely
> say that it's the number of strings stored in that
> array. But better always keep in mind that there are
> no strings stored in it butmerely char pointers. And
> these pointers not necessarily point to strings, with
> e.g.
> 
> char c1 = 'a', c2 = 'b', c3 = 'c';
> char *x[] = {&c1, &c2, &c3, NULL};
> 
> 'x' is also an array of char pointers, but non of
> its elements point to strings. So calling it an
> array of strings would be extremely misleading.
> 
> Also: make sure that you only try to use this
> "trick" in cases where the array is defined in
> the scope where you use it! E.g. this
> 
> static void foo(int *y) {
>       printf("%d", (int) (sizeof(y) / sizeof(y[0])));
> }
> 
> int main(void) {
>     int x[] = {1, 2, 3, 4};
>     foo(x);
>     return 0;
> }
> 
> will fail! The reason is that nothing in function
> foo() "knows" that the argument 'y' it received
> is pointing to an array, so in that function
> sizeof(y) is just the size of an int pointer, not
> the size of the array 'x' you defined in main().
> And thus the result of dividing it by the size of
> an int is nothing that would make much sense.
> 
Thank you very much for this explanation. It is very 
clear. Unfortunately, as I have not used this macro
for quite a while, I have completely forgotten (as I have
mentioned in my reply to Ben) that the denominator
has a pointer as its arguments. Thank you. 

[toc] | [prev] | [next] | [standalone]


#101981

FromKeith Thompson <kst-u@mib.org>
Date2017-01-16 08:58 -0800
Message-ID<ln8tqbeycl.fsf@kst-u.example.com>
In reply to#101921
Alla _ <modelling.data@gmail.com> writes:
[...]
>> Alla _ <modelling.data@gmail.com> wrote:
>> > For example:
>> > char *array[] = {"abc", "defg", "hijklmop", NULL};
[...]
> Thank you very much for this explanation. It is very 
> clear. Unfortunately, as I have not used this macro
> for quite a while, I have completely forgotten (as I have
> mentioned in my reply to Ben) that the denominator
> has a pointer as its arguments. Thank you. 

In the macro

    #define ARRAY_LEN(x) (sizeof (x) / sizeof (x)[0])

the denominator is a pointer *if and only if* x happens to be an array
of pointers.  The numerator is the size of the array as a whole; the
denominator is the size of a single element of the array.  It's a
general-purpose macro for determining the length in elements of an array
*of any type*.  (And of course it works only if the declaration of the
array object itself is visible and specifies the length.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#101765

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-01-14 14:47 +0000
Message-ID<87o9z9n1ey.fsf@bsb.me.uk>
In reply to#101737
Alla _ <modelling.data@gmail.com> writes:

> 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]),

Small point: the brackets are in the wrong place.  It is usual in macros
to put the parameter name in parentheses to prevent any possible
interaction with the surrounding symbols.  The classic example being

  #define square(x) x*x

which goes wrong when used like this:

 square(a+1) => a+1*a+1

Similarly, one should put the whole expression in parentheses:

  #define square(x) ((x)*(x))

Because of the high priority of the sizeof and [] operators, it is
likely that your expression will be fine, but the bets advice is to put
the parentheses in every time just to stop people wondering if it really
is OK or not:

  #define ARRAY_SIZE(a) (sizeof (a) / sizeof (a)[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.

The array has four pointers.  These pointers point to the start of
strings.

> sizeof(x) here will be sizeof(array) thus indicating 
> the size in bytes of the whole array of strings,

It will be the size of the whole array of pointers: 4 times however many
bytes are in a char * on your machine (8 I think you once said).

> because 'array' here is used as the address of the
> first sub-element, which is 'a' (array is the same as
> array[0][0]);

No.  'array' in most contexts converts to a pointer to the first element
of that array -- i.e. it will have type char **.  array is the same as
&array[0] (again in most contexts) and that is very much not the same as
array[0][0].

But remember, sizeof is one of the contexts where this conversion does
not occur.  sizeof array gives the number of byte on the object called
array, even though in other contexts the expression array is converted
to a pointer.

> 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);

No, it gives the size of the the whole array of pointers because that's
what array is -- an array of pointers.

> 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);

No.  sizeof(array[0]) is the size of one of the pointers.

> 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.

It gives you the number of elements in the array so, yes, your tests
will work.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#101769

FromAlla _ <modelling.data@gmail.com>
Date2017-01-14 07:17 -0800
Message-ID<3b0be4f0-5ef5-47fb-abb3-e6b4da367cd0@googlegroups.com>
In reply to#101765
On Saturday, January 14, 2017 at 5:47:59 PM UTC+3, Ben Bacarisse wrote:
> Alla _ <modelling.data@gmail.com> writes:
> 
> > 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]),
> 
> Small point: the brackets are in the wrong place.  It is usual in macros
> to put the parameter name in parentheses to prevent any possible
> interaction with the surrounding symbols.  The classic example being
> 
>   #define square(x) x*x
> 
> which goes wrong when used like this:
> 
>  square(a+1) => a+1*a+1
> 
> Similarly, one should put the whole expression in parentheses:
> 
>   #define square(x) ((x)*(x))
> 
> Because of the high priority of the sizeof and [] operators, it is
> likely that your expression will be fine, but the bets advice is to put
> the parentheses in every time just to stop people wondering if it really
> is OK or not:
> 
>   #define ARRAY_SIZE(a) (sizeof (a) / sizeof (a)[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.
> 
> The array has four pointers.  These pointers point to the start of
> strings.
> 
> > sizeof(x) here will be sizeof(array) thus indicating 
> > the size in bytes of the whole array of strings,
> 
> It will be the size of the whole array of pointers: 4 times however many
> bytes are in a char * on your machine (8 I think you once said).
> 
> > because 'array' here is used as the address of the
> > first sub-element, which is 'a' (array is the same as
> > array[0][0]);
> 
> No.  'array' in most contexts converts to a pointer to the first element
> of that array -- i.e. it will have type char **.  array is the same as
> &array[0] (again in most contexts) and that is very much not the same as
> array[0][0].
> 
> But remember, sizeof is one of the contexts where this conversion does
> not occur.  sizeof array gives the number of byte on the object called
> array, even though in other contexts the expression array is converted
> to a pointer.
> 
> > 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);
> 
> No, it gives the size of the the whole array of pointers because that's
> what array is -- an array of pointers.
> 
> > 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);
> 
> No.  sizeof(array[0]) is the size of one of the pointers.
> 
> > 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.
> 
> It gives you the number of elements in the array so, yes, your tests
> will work.
Thank you very much for this explanation. Of course! I see.
How could I forget this. 

[toc] | [prev] | [next] | [standalone]


#101771

FromManfred <noname@invalid.add>
Date2017-01-14 16:22 +0100
Message-ID<o5dfn9$6qt$1@gioia.aioe.org>
In reply to#101737
On 1/14/2017 1:16 PM, 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]), ...
<snip>
> char *array[] = {"abc", "defg", "hijklmop", NULL};
> The pointer points to an array that has 4 strings.
<snip>
> 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;
Others have already explained that your array is an array of (4) char*, 
so this is how it works - by the way the fact that your last element is 
NULL requires that your array be an array of char*.
I only add here that from your explanation you probably confused this 
array with what you could have declared as
char array[][9] = {"abc", "defg", "hijklmop", ""};
(note the final "" instead of NULL)
in this case you would have a 2-dimensional array of 4 rows where each 
row (the strings "abc", "defg", "hijklmop", "") is 9 char long, and 36 
bytes total size.
> 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.
>
> Thank you!
>

[toc] | [prev] | [next] | [standalone]


#101779

FromBarry Schwarz <schwarzb@dqel.com>
Date2017-01-14 08:35 -0800
Message-ID<tmjk7cppga86gcc0022rvsrb8c84au0e0n@4ax.com>
In reply to#101737
On Sat, 14 Jan 2017 04:16:30 -0800 (PST), Alla _
<modelling.data@gmail.com> wrote:

<snip>

>For example:
>char *array[] = {"abc", "defg", "hijklmop", NULL};
>The pointer points to an array that has 4 strings. 

There is not "the pointer".  There is only one named object.  That
object is "the array" whose name is "array".  The array consists of 4
elements.  None of the elements is a string.  All the elements are
pointers, pointers to char to be precise.  Three of those elements are
in fact initialized to point to a string ( a different string for each
one).  The fourth element is initialized to indicate it points
nowhere.

>sizeof(x) here will be sizeof(array) thus indicating 
>the size in bytes of the whole array of strings, 

There is no array of strings, only an array of pointers.

>because 'array' here is used as the address of the
>first sub-element, which is 'a' (array is the same as
>array[0][0]); 

NO!  The sizeof operator is an exception to the rule that an array
name is converted to a pointer to the first element.

In the non-exceptional case, the conversion would be equivalent to
&array[0] which would be the address of (not the address contained in)
the first pointer.  The byte (not char) at that address would be
either the high order or low order byte of the address contained in
the pointer and most likely would not correspond to any printable
character.  &array[0] would not point to the 'a' in "abc".

>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);

It will give the number of bytes occupied by the array of pointers
which is completely independent of the length of the strings.  Replace
"abc" in your initialization with
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" and
sizeof(array) yields the same value as yours.  It will never count
characters.

>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;

No, it gives the size of the pointer.

>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. 

You do not have an array of strings.  You have an array of pointers.
Except for the last, each of the pointers points to another array (of
char).  The pointers are independent and in this case each points to a
different array.  Those arrays have different sizes.  The pointers
themselves are all the same size.

-- 
Remove del for email

[toc] | [prev] | [next] | [standalone]


#101924

FromAlla _ <modelling.data@gmail.com>
Date2017-01-15 22:53 -0800
Message-ID<d96856b2-263a-45a4-a0ab-41d7ed5c9655@googlegroups.com>
In reply to#101779
On Saturday, January 14, 2017 at 7:35:56 PM UTC+3, Barry Schwarz wrote:
> On Sat, 14 Jan 2017 04:16:30 -0800 (PST), Alla _
> <modelling.data@gmail.com> wrote:
> 
> <snip>
> >because 'array' here is used as the address of the
> >first sub-element, which is 'a' (array is the same as
> >array[0][0]); 
> 
> NO!  The sizeof operator is an exception to the rule that an array
> name is converted to a pointer to the first element.
> 
> In the non-exceptional case, the conversion would be equivalent to
> &array[0] which would be the address of (not the address contained in)
> the first pointer.  The byte (not char) at that address would be
> either the high order or low order byte of the address contained in
> the pointer and most likely would not correspond to any printable
> character.  &array[0] would not point to the 'a' in "abc".
I am not sure I understood this correctly. You say that in normal,
non-exceptional case, &array[0] doesn't guarantee to point to the 
first element in the first string? &array[0] does point to the first string,
correct? Where else can it point to given the index?
Could you, please, give an example with hexadecimal addresses, so 
I can see what can happen. Please.
> 
<snip>

[toc] | [prev] | [next] | [standalone]


#101970

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-01-16 15:58 +0000
Message-ID<87eg03hu82.fsf@bsb.me.uk>
In reply to#101924
Alla _ <modelling.data@gmail.com> writes:

> On Saturday, January 14, 2017 at 7:35:56 PM UTC+3, Barry Schwarz wrote:
>> On Sat, 14 Jan 2017 04:16:30 -0800 (PST), Alla _
>> <modelling.data@gmail.com> wrote:
>> 
>> <snip>
>> >because 'array' here is used as the address of the
>> >first sub-element, which is 'a' (array is the same as
>> >array[0][0]); 
>> 
>> NO!  The sizeof operator is an exception to the rule that an array
>> name is converted to a pointer to the first element.

I think the context here is

  char *array[] = { "abc", "def", "..." };

>> In the non-exceptional case, the conversion would be equivalent to
>> &array[0] which would be the address of (not the address contained in)
>> the first pointer.  The byte (not char) at that address would be
>> either the high order or low order byte of the address contained in
>> the pointer and most likely would not correspond to any printable
>> character.  &array[0] would not point to the 'a' in "abc".
>
> I am not sure I understood this correctly. You say that in normal,
> non-exceptional case, &array[0] doesn't guarantee to point to the 
> first element in the first string?

Yes, that's what he's saying.  array is an array of pointers, so
array[0] is the first pointer and &array[0] is a pointer to that first
pointer.

> &array[0] does point to the first string,
> correct? Where else can it point to given the index?

It points to the first element of the array.

> Could you, please, give an example with hexadecimal addresses, so 
> I can see what can happen. Please.

The compiler will make this structure:

0x100: 'a' 'b' 'c'  0
0x104: 'd' 'e' 'f'  0
0x108: '.' '.' '.'  0
0x10c: 0x100
0x110: 0x104
0x114: 0x108

The name `array` will be associated with the address 0x10c.  The
following expressions have the values and types show:

  expression   value    type
  array        0x10c    char **
  array[0]     0x104    char *
  array[0][0]  'a'      char
  &array       0x10c    char (*)[4]
  &array[0]    0x10c    char **
  &array[0][0] 0x104    char *

The types are important because a C pointer is an address with a
specific type.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#102021

FromAlla _ <modelling.data@gmail.com>
Date2017-01-16 22:38 -0800
Message-ID<c1bc6814-89a0-4645-87e0-a94d55aae73c@googlegroups.com>
In reply to#101970
On Monday, January 16, 2017 at 6:59:00 PM UTC+3, Ben Bacarisse wrote:
> Alla _ <modelling.data@gmail.com> writes:
> 
> > On Saturday, January 14, 2017 at 7:35:56 PM UTC+3, Barry Schwarz wrote:
> >> On Sat, 14 Jan 2017 04:16:30 -0800 (PST), Alla _
> >> <modelling.data@gmail.com> wrote:
> >> 
> >> <snip>
> >> >because 'array' here is used as the address of the
> >> >first sub-element, which is 'a' (array is the same as
> >> >array[0][0]); 
> >> 
> >> NO!  The sizeof operator is an exception to the rule that an array
> >> name is converted to a pointer to the first element.
> 
> I think the context here is
> 
>   char *array[] = { "abc", "def", "..." };
> 
> >> In the non-exceptional case, the conversion would be equivalent to
> >> &array[0] which would be the address of (not the address contained in)
> >> the first pointer.  The byte (not char) at that address would be
> >> either the high order or low order byte of the address contained in
> >> the pointer and most likely would not correspond to any printable
> >> character.  &array[0] would not point to the 'a' in "abc".
> >
> > I am not sure I understood this correctly. You say that in normal,
> > non-exceptional case, &array[0] doesn't guarantee to point to the 
> > first element in the first string?
> 
> Yes, that's what he's saying.  array is an array of pointers, so
> array[0] is the first pointer and &array[0] is a pointer to that first
> pointer.
> 
> > &array[0] does point to the first string,
> > correct? Where else can it point to given the index?
> 
> It points to the first element of the array.
> 
> > Could you, please, give an example with hexadecimal addresses, so 
> > I can see what can happen. Please.
> 
> The compiler will make this structure:
> 
> 0x100: 'a' 'b' 'c'  0
> 0x104: 'd' 'e' 'f'  0
> 0x108: '.' '.' '.'  0
> 0x10c: 0x100
> 0x110: 0x104
> 0x114: 0x108
> 
> The name `array` will be associated with the address 0x10c.  The
> following expressions have the values and types show:
> 
>   expression   value    type
>   array        0x10c    char **
>   array[0]     0x104    char *
>   array[0][0]  'a'      char
>   &array       0x10c    char (*)[4]
>   &array[0]    0x10c    char **
>   &array[0][0] 0x104    char *
> 
> The types are important because a C pointer is an address with a
> specific type.
Thank you very much. Did you mean to write 0x100 in examples above?
0x104 is the address of the array[1], correct?
> 
> -- 
> Ben.

[toc] | [prev] | [next] | [standalone]


#102031

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-01-17 10:11 +0000
Message-ID<87o9z6gfnb.fsf@bsb.me.uk>
In reply to#102021
Alla _ <modelling.data@gmail.com> writes:

> On Monday, January 16, 2017 at 6:59:00 PM UTC+3, Ben Bacarisse wrote:
<snip>
>>   char *array[] = { "abc", "def", "..." };
<snip>

Corrected:

>> The compiler will make this structure:
>> 
>> 0x100: 'a' 'b' 'c'  0
>> 0x104: 'd' 'e' 'f'  0
>> 0x108: '.' '.' '.'  0
>> 0x10c: 0x100
>> 0x110: 0x104
>> 0x114: 0x108
>> 
>> The name `array` will be associated with the address 0x10c.  The
>> following expressions have the values and types shown:
>> 
>>   expression   value    type
>>   array        0x10c    char **
>>   array[0]     0x100    char *
>>   array[0][0]  'a'      char
>>   &array       0x10c    char (*)[4]
>>   &array[0]    0x10c    char **
>>   &array[0][0] 0x100    char *
>> 
>> The types are important because a C pointer is an address with a
>> specific type.
>
> Thank you very much. Did you mean to write 0x100 in examples above?
> 0x104 is the address of the array[1], correct?

Yes.  I was sure there would be some error in it, but I'm glad it did
not throw you off course.  (I've edited my quote.)

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#101780

FromJames Kuyper <jameskuyper@verizon.net>
Date2017-01-14 11:43 -0500
Message-ID<o5dkc2$gf1$1@dont-email.me>
In reply to#101737
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.

[toc] | [prev] | [next] | [standalone]


#101829

FromKeith Thompson <kst-u@mib.org>
Date2017-01-14 16:01 -0800
Message-ID<lnziitgpib.fsf@kst-u.example.com>
In reply to#101780
James Kuyper <jameskuyper@verizon.net> writes:
[...]
>      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.

True, but I'd place a different emphasis.

The "length" of a string by definition excludes the terminating null
character (which is part of the string but does not contribute to its
"length").

`sizeof segmented_string` does happen to be "the total length of those
strings, including their terminating null characters", but it's simpler
and more correct to say that it's the size of the array object,
regardless of its contents.  For example, if you had written:

    char segmented_string[42] = "abc\0defg\0hijklmop\0";

then `sizeof segmented_string` would be 42.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#101941

FromAlla _ <modelling.data@gmail.com>
Date2017-01-16 01:36 -0800
Message-ID<e3c1e893-77f1-41b9-92c7-452e02c193a1@googlegroups.com>
In reply to#101780
On Saturday, January 14, 2017 at 7:43:21 PM UTC+3, James Kuyper wrote:
> 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.
> 
Thank you for this interesting explanation. I would like to ask for a bit
clarification, if I may: 
char __unnamed1[] = {'H', 'e', 'l', 'l', 'o', ' ', '\0'};
char char_array[sizeof __unnamed1];
 char char_array[] = {'H', 'e', 'l', 'l', 'o', ' ', '\0'};
Do I understand correctly that you can say the same thing about 
char _unnamed1[]? I don't see how it differs from char _char_array[],
when same literals are assigned to them, like in this case  {'H', 'e', 'l', 'l', 'o', ' ', '\0'}?

> 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.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web