434,637 Members | 1,967 Online + Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,637 IT Pros & Developers. It's quick & easy.

K&R chapter 6.3 Question 'how to calculate the number of array elements'

 P: n/a in K&R Chapter 6.3 it mentions two methods to calculate NKEYS. and points out the first one which is to terminate the list of initializers with a null pointer, then loop along keytab until the end is found is less efficient than using sizeof operator , since size of the array is completely determined at compile time. i don't quite understand this. Could anyone explain to me in detail ? Thanks in advance.. Nov 14 '05 #1
6 Replies

 P: n/a Herrcho wrote: in K&R Chapter 6.3 it mentions two methods to calculate NKEYS. and points out the first one which is to terminate the list of initializers with a null pointer, then loop along keytab until the end is found is less efficient Yes, the first method would need to be performed at runtime, with initialization code such as: #include unsigned int nkeys; for (nkeys = 0; keytab[nkeys].word != NULL; nkeys++) ; than using sizeof operator , since size of the array is completely determined at compile time. The second method requires no runtime code, and leaves all the work up to the compiler: #define NKEYS (sizeof keytab / sizeof keytab) The latter is much simpler, n'est-ce pas? Mark Nov 14 '05 #2

 P: n/a "Herrcho" wrote in message news:76**************************@posting.google.c om... in K&R Chapter 6.3 it mentions two methods to calculate NKEYS. and points out the first one which is to terminate the list of initializers with a null pointer, Or more generally, a value which has been specified to mean 'terminator'. E.g. an array of integer values which are defined as 'valid' data if nonnegative. A 'terminator' value for this could be e.g. -1. then loop along keytab until the end is found This would be 'manual' counting. It happens at run time, so it consumes processor time. It also is 'fragile' since it depends upon the array's elements being properly initialized. It's also not very flexible, since it disallows storing (in any array element, intentionally or inadvertently) any possible value the array's element type could represent (a 'terminator' value would belong to this set.) is less efficient Because 'sizeof' provides the value at compile-time. Thus the value is already known at program startup. No need for the program to consume processor time to calculate it. than using sizeof operator , since size of the array is completely determined at compile time. i don't quite understand this. Could anyone explain to me in detail ? I hope I did. A caveat: 'sizeof' will only correctly report the size of an array if that array is in the same scope where the 'sizeof' operator is used. Passed as an argument to a function, an array's type is 'demoted' to a pointer type (the value is the address of the array's first element). #include int g_array[] = {1,2,3,-1}; /* using -1 as 'terminator' for */ /* array of non-negative value */ size_t size(int arg) /* the  is ignored, 'arg's type is really */ /* 'int*' ('pointer to int') */ { return sizeof arg; } void other_stuff(int *arg) /* note that we can pass either a 'real' */ /* pointer, or an array of ints as the */ /* parameter */ { --arg; /* decrement element 2 (imagine this is part of a */ /* larger algorithm, e.g. where the 2 is replaced */ /* by the value of some other variable. IOW we */ /* don't know by looking at this statment what */ /* that value is) */ } void more_stuff(void) { ++g_array; /* increment element 3 (imagine this is part of a */ /* larger algorithm, e.g. where the 3 is replaced */ /* by the value of some other variable. IOW we */ /* don't know by looking at this statment what */ /* that value is) */ } /* 'Manually' counts array elements, */ /* uses -1 as terminator value */ size_t count_em(int arg[]) /* yet another possible syntax for */ /* a pointer or array argument */ { size_t count = 0; size_t i = 0; while(arg[i++] >= 0) count += sizeof *arg; /* '*arg' means same thing as 'arg' */ return count; } int main() { int m_array[] = { 2, 6, 0, 7, 5, -1}; /* using -1 as 'terminator' for */ /* array of non-negative value */ printf("size of g_array as reported by sizeof operator :" " %2lu bytes\n", (unsigned long)sizeof g_array); /* prints sizeof(int) * 4, */ /* e.g. 16 on a Win32 platform */ printf("size of g_array as reported by size() function :" " %2lu bytes\n", (unsigned long)size(g_array)); /* prints the size of type 'int*' */ /* e.g. 4 on a Win32 platform */ putchar('\n'); printf("size of m_array as reported by sizeof operator :" " %2lu bytes\n", (unsigned long)sizeof m_array); /* prints sizeof(int) * 5, */ /* e.g. 24 on a Win32 platform */ printf("size of m_array as reported by size() function :" " %2lu bytes\n", (unsigned long)size(m_array)); /* prints the size of type 'int*' */ /* e.g. 4 on a Win32 platform */ putchar('\n'); /* Hereafter, size values stated in comments are those obtained on Win32 platform */ printf("size of g_array as reported by count_em() function :" " %2lu bytes\n", (unsigned long)count_em(g_array)); /* prints size of the portion */ /* of array preceding element */ /* with value -1 (here, 12) */ printf("size of m_array as reported by count_em() function :" " %2lu bytes\n", (unsigned long)count_em(m_array)); /* prints size of the portion */ /* of array preceding element */ /* with value -1 (here, 20) */ putchar('\n'); other_stuff(m_array); /* do some stuff with 'm_array' */ printf("%s\n\n", "other_stuff(m_array) called"); printf("size of m_array as reported by count_em() function :" " %2lu bytes\n", (unsigned long)count_em(m_array)); /* prints the number of array */ /* of array preceding element */ /* with value -1 (here, 8) */ /* -- because m_array was */ /* 'accidentally' set to -1. */ /* OOPS! :-) */ putchar('\n'); more_stuff(); printf("%s\n\n", "more_stuff() called (touches g_array)"); puts("Better not call count_em(g_array) !!!"); #if 0 printf("size of g_array as reported by count_em() function :" " %2lu bytes\n", (unsigned long)count_em(g_array)); /* prints the number of array */ /* of array preceding element */ /* with value -1. But WAIT!! */ /* there's no element with a */ /* value of -1!! (due to what */ /* 'more_stuff()' did) */ /* execution of this statment */ /* would produce 'undefined' */ /* behavior (wich is why I */ /* "#if-d" it out */ /* this last issue is why we should always provide an array's size */ /* (typically expressed as number of elements) as an extra paramter */ /* to functions to which arrays are passed. It provides a 'hard limit */ /* on how many elements can be accessed, regardless of their values. */ /* And again, remember that sizeof will only report correct size for */ /* arrays in same scope (of course some other mechanism for determining */ /* size might be used instead, e.g. a #define for the size of the array) */ /* recommended syntax for calcuating count of array elements using sizeof: */ /* /* sizeof array_name / sizeof *array_name */ #endif return 0; } Output: ------------------------------------------------------------- size of g_array as reported by sizeof operator : 16 bytes size of g_array as reported by size() function : 4 bytes size of m_array as reported by sizeof operator : 24 bytes size of m_array as reported by size() function : 4 bytes size of g_array as reported by count_em() function : 12 bytes size of m_array as reported by count_em() function : 20 bytes other_stuff(m_array) called size of m_array as reported by count_em() function : 8 bytes more_stuff() called (touches g_array) Better not call count_em(g_array) !!! ------------------------------------------------------------- Hope I didn't foul all that up. If I did, we'll hear about it soon enough! :-) Thanks in advance.. You're welcome after the fact. :-) -Mike Nov 14 '05 #3

 P: n/a On Mon, 09 Feb 2004 22:38:19 -0800, Herrcho wrote: in K&R Chapter 6.3 it mentions two methods to calculate NKEYS. and points out the first one which is to terminate the list of initializers with a null pointer, then loop along keytab until the end is found is less efficient than using sizeof operator , since size of the array is completely determined at compile time. i don't quite understand this. Could anyone explain to me in detail ? Thanks in advance.. Don't have the book handy, but it seems simpl enough. Here's the first case: char *array = { val1, val2, ... NULL }; Now you can loop through the array until you reach the NULL; if you've filled in all the values array ... array with values and array with NULL, you'll get your count. Like so: int i; for ( i = 1; i <= 100; i++ ) if ( array[i-1] == NULL ) break; Thing is, that requires 100 loops and comparisons. Now try this: char *array; size_t n = sizeof(array)/sizeof(array); Assuming a char * takes, say, 4 bytes, then the size of the array will be 400 bytes, the size of array will be 4 bytes, and 400/4 == 100, which is the number of elements. Better yet, since sizeof is a compile-time thing, this works out to a simple assignment: size_t n = 100; Nov 14 '05 #4

 P: n/a Kelsey Bjarnason wrote: On Mon, 09 Feb 2004 22:38:19 -0800, Herrcho wrote: in K&R Chapter 6.3 it mentions two methods to calculate NKEYS. and points out the first one which is to terminate the list of initializers with a null pointer, then loop along keytab until the end is found is less efficient than using sizeof operator , since size of the array is completely determined at compile time. i don't quite understand this. Could anyone explain to me in detail ? Thanks in advance.. Don't have the book handy, but it seems simpl enough. Here's the first case: char *array = { val1, val2, ... NULL }; Now you can loop through the array until you reach the NULL; if you've filled in all the values array ... array with values and array with NULL, you'll get your count. Like so: int i; for ( i = 1; i <= 100; i++ ) if ( array[i-1] == NULL ) break; Thing is, that requires 100 loops and comparisons. char *ptr; for (ptr = array; ptr != NULL; ++ptr); -- pete Nov 14 '05 #5

 P: n/a pete wrote: Kelsey Bjarnason wrote: char *array = { val1, val2, ... NULL }; char *ptr; char **ptr; for (ptr = array; ptr != NULL; ++ptr); -- pete Nov 14 '05 #6

 P: n/a "pete" wrote in message news:40***********@mindspring.com... Kelsey Bjarnason wrote: char *array = { val1, val2, ... NULL }; .... int i; for ( i = 1; i <= 100; i++ ) if ( array[i-1] == NULL ) break; Thing is, that requires 100 loops and comparisons. char *ptr; for (ptr = array; ptr != NULL; ++ptr); Two questions: 1. How many loops would this execute in your opinion, given the initialization above? (I admit, I assume the NULL is the *last* element in the array.) 2. How does it calculate the number of elements? ;-) Nov 14 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.
{"ft_lang_label":"__label__en","ft_lang_prob":0.8416978,"math_prob":0.9538372,"size":10823,"snap":"2019-43-2019-47","text_gpt3_token_len":2880,"char_repetition_ratio":0.14742583,"word_repetition_ratio":0.4727945,"special_character_ratio":0.32661924,"punctuation_ratio":0.160019,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.96237797,"pos_list":[0,1,2,3,4],"im_url_duplicate_count":[null,null,null,null,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2019-10-14T12:05:37Z\",\"WARC-Record-ID\":\"<urn:uuid:08163894-5a1d-4925-8981-10968d8a0e3d>\",\"Content-Length\":\"45284\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:cd30fa76-de87-403e-b805-04dcb88c7976>\",\"WARC-Concurrent-To\":\"<urn:uuid:861849b7-07ea-47a4-8c7e-ebc75f80176b>\",\"WARC-IP-Address\":\"104.197.32.212\",\"WARC-Target-URI\":\"https://bytes.com/topic/c/answers/216122-k-r-chapter-6-3-question-how-calculate-number-array-elements\",\"WARC-Payload-Digest\":\"sha1:Q36M33LV4N5VCQLNUZVUKILTIFSUXKWB\",\"WARC-Block-Digest\":\"sha1:X4RB4QXZPG6CK7PJLKS25OPRUDXDSJT2\",\"WARC-Identified-Payload-Type\":\"application/xhtml+xml\",\"warc_filename\":\"/cc_download/warc_2019/CC-MAIN-2019-43/CC-MAIN-2019-43_segments_1570986653216.3_warc_CC-MAIN-20191014101303-20191014124303-00462.warc.gz\"}"}