31

I have a char* array as follows:

char *tbl[] = { "1", "2", "3" };

How do I use the sizeof operator to get the number of elements of the array, here 3?

The below did work, but is it correct?

int n = sizeof(tbl) / sizeof(tbl[0]) 
Ayman
  • 11,265
  • 16
  • 66
  • 92
  • 3
    Not if the array was received as a parameter. Check [my answer to a similar question](http://stackoverflow.com/a/10349610/481534). – Elideb Apr 27 '12 at 11:16
  • Possible duplicate of [How do I determine the size of my array in C?](http://stackoverflow.com/questions/37538/how-do-i-determine-the-size-of-my-array-in-c) – Peter Mortensen Feb 28 '13 at 16:14
  • This was actually answered [here](http://stackoverflow.com/questions/37538/c-how-do-i-determine-the-size-of-my-array) And that was the correct way of doing it. – Ayman Oct 13 '09 at 12:34
  • @Elideb: Strictly speaking, an array can't be a parameter. A parameter defined as `char *tbl[]` is really of type `char**`; the type is adjusted at compile time. – Keith Thompson Aug 07 '13 at 14:57
  • @KeithThompson Yeah, I know, but I still find code around with arrays as parameters, and people expect them to behave as such. I'll try to be more correct when talking about them. – Elideb Aug 28 '13 at 17:37
  • @Elideb: No, you don't find C code with arrays as parameters, since that's impossible. You commonly find code with parameters defined with an array-like syntax, but those parameters really are pointers. – Keith Thompson Aug 28 '13 at 17:38

3 Answers3

40

Yes,

size_t n = sizeof(tbl) / sizeof(tbl[0])

is the most typical way to do this.

Please note that using int for array sizes is not the best idea.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 11
    Anything wrong with using a `size_t` for sizes? Or at least something unsigned? – Chris Lutz Oct 13 '09 at 16:53
  • `#define countof(a) ((sizeof(a)/sizeof((a)[0])))` - I wonder if it is a safe way to declare such a macro. Especially for multi-dimensional arrays and such stuff... – leemes Mar 19 '11 at 22:10
  • I believe sizeof is always calculated at compile time. I can't think of a way to get a meaningful sizeof of something which is not known at compile time. – aragaer Aug 07 '13 at 14:13
  • 5
    `sizeof(char)` doesn't save you a dereferencing operation. The compiler calculates size of `tbl[0]` by understanding its type, and doesn't actually generate code for it. The only thing `sizeof(char)` instead of `sizeof(tbl[0])` would achieve for you is problem in the future if the array changes its type from `char` to something else. – Shahbaz Aug 07 '13 at 14:30
  • @aragaer, for variable length arrays, that is not true. If you have `unsigned int n; scanf("%u", &n); int array[n];` (with added error checking), then `sizeof(array)` is calculated at run-time. – Shahbaz Aug 07 '13 at 14:31
  • 1
    @Shahbaz I believe once compiler sees `sizeof` being called for a variable size array, it might optimize it to "multiply array length by element size" which will result in "almost compile time" sizeof. There is no thing called "array" in run time and thus there is nowhere to store its size. – aragaer Aug 07 '13 at 14:37
  • @aragaer, it most certainly will. The actual multiplication is done at run-time and its value unknown at compile-time. – Shahbaz Aug 07 '13 at 14:38
  • 1
    @Shahbaz but if we know at compile time that `int array[n]; length = sizeof(array) / sizeof(*array);` we can assume that `length = n;` and avoid any computations at all. – aragaer Aug 07 '13 at 14:41
  • 1
    Replacing `sizeof(tbl[0])` by `sizeof(char)` is not an optimization -- **nor is it correct**. `tbl[0]` is a `char*`, not a `char` (and `sizeof(char)` is 1 by definition), so your "optimized" version simply yields the size in bytes of the array. `sizeof` is always evaluated at compile time unless the argument is a variable-length array. – Keith Thompson Aug 07 '13 at 14:51
  • @aragaer: `sizeof arr` where `arr` is a variable-length array is likely to be computed without a multiplication. The compiler can store the size in an anonymous object, so the multiplication needs to be done only when the type is defined. – Keith Thompson Aug 07 '13 at 14:55
  • @aragaer: We can't assume the length is `n` if `n` might change: `int n = 10; int array[n]; n = 20;`; modifying `n` doesn't affect the length of `array`. But that would be poor style. – Keith Thompson Aug 07 '13 at 14:56
  • @KeithThompson For personal reference, could you please elaborate on what was incorrect? `sizeof(NATIVE_TYPE)` is handled at compile time, and pointer decay does indeed cause `sizeof()` to provide differing results depending on the scope of the pointer (ie: local vs function scope). – Cloud Aug 07 '13 at 15:35
  • 1
    @Dogbert: See my comment above, posted about an hour ago, starting with the word "Replacing". – Keith Thompson Aug 07 '13 at 16:02
  • I stand corrected. I didn't notice it was a `char*` array and not a `char` array. +1 on comments/answers. Cheers! – Cloud Aug 07 '13 at 16:30
  • @aragaer, that's true. I was responding to your sentence that said: _I believe sizeof is always calculated at compile time._ – Shahbaz Aug 07 '13 at 16:53
  • @Shahbaz I didn't think about variable size arrays thinking it's a GCC extension. At least I've learned something today. – aragaer Aug 07 '13 at 17:15
  • @aragaer, it used to be. It was standardized in C99. – Shahbaz Aug 08 '13 at 09:49
  • error: division 'sizeof (char *) / sizeof (char)' does not compute the number of array elements [-Werror=sizeof-pointer-div] – lilalinux Jan 29 '20 at 08:44
  • @lilalinux That's a rather new (introduced about a year earlier) warning promoted to error. – sharptooth Jan 29 '20 at 11:27
19

The shorter and, arguably, cleaner version would look as

sizeof tbl / sizeof *tbl

:)

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
4

Yes, it will give you the number of elements in the array tb1.

int n = sizeof(tbl) / sizeof(tbl[0])

Interpretation:

sizeof(tb1) will gives the size of the entire array i.e, tb1 = 3 bytes

sizeof(tb1[0]) gives the size of the character as tb1[0] gives a character value(value at address tb1+0) = 1 byte

Division of those two will give you 3 elements

Raju
  • 1,149
  • 1
  • 6
  • 19
  • `tbl` is an array of `char*`, not an array of `char`. If `sizeof (char*) == 4`, then you're dividing 12 bytes by 4 bytes, yield 3 *array elements*, not 3 bytes. – Keith Thompson Aug 07 '13 at 15:01
  • sorry its a typoo, it should be 3 elements not bytes..:) – Raju Aug 07 '13 at 15:04
  • @tbl still isn't a character array. – Keith Thompson Aug 07 '13 at 15:08
  • No, still incorrect. `tbl` is an array of `char*`, *not* an array of `char`. The size of `tbl[0]` isn't 1 byte unless you're on a weird system with 1-byte pointers. – Keith Thompson Aug 07 '13 at 15:14
  • but sizeof tb1[0] gives us the size of the value present at address tb1[0] which must be a character right?... – Raju Aug 07 '13 at 15:16
  • It would if `tbl` were an array of `char` (`char tbl[]`). `tbl` is an array of `char*` (`char *tbl[]`). If a `char*` (a pointer) is 4 bytes, then the whole array is 12 bytes, not 3. – Keith Thompson Aug 07 '13 at 15:59
  • This really needs fixing, because it's wrong--the sizeof(tb1) is most typically going to be 24, and the sizeof(tb1[0]) is most typically going to be 8 (12 and 4 on 32-bit systems). This is not an array of characters, it's an array of pointers. – AHelps Oct 27 '16 at 19:58