Home > OS >  Number of elements in const char * array
Number of elements in const char * array

Time:05-05

I have written a function in C which takes as an argument const char *p and I would like to check the number of elements in that array, but it doesn't work well.

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

int arrSize(const char *a){
    int it = 0;
    int size = 0;
    while(a[it] != '\0'){
          size;
          it;
    }
    return size;
}

int main(){
        const char a[5] = {'a', 'b', 'b', 'v', 's'};
        const char b[4] = {'c', 'b', 'b', 'v'};
        const char c[4] = {'c', 'b', 'b', 'v'};
        printf("%d %d %d", arrSize(a), arrSize(b), arrSize(c));
}

But the code above gives 8, 12, 16 output and I don't know why.

CodePudding user response:

while(a[it] != '\0'){

This loop ends when the element of the array is equal to the null terminator character.

const char a[5] = {'a', 'b', 'b', 'v', 's'};
const char b[4] = {'c', 'b', 'b', 'v'};
const char c[4] = {'c', 'b', 'b', 'v'};

None of your arrays contain a null terminator character. The loop won't stop on the elements, and it will access non-existing elements outside of the bounds of the array and the behaviour of the program is undefined. This is bad. Don't do this.

If you add null terminator to the arrays, then the function will successfully count the number of non-null-terminator characters that precede the first null-terminator:

const char a[6] = {'a', 'b', 'b', 'v', 's', '\0'};
//const char a[] = "abbvs"; // equivalent
printf("%d", arrSize(a)); // 5

Note that there is no need to write this arrSize because it's provided by the standard library under the name strlen.


When you pass a pointer to element of an array into a function, there is no general way to determine the size of the array using that pointer without relying on a terminator value such as in the case of null terminated strings. When a function needs to access an array of arbitrary length, a common C idiom is to pass that size into the function as an argument.

CodePudding user response:

Without a string end char 0x0 (or '\0',your function will keep going until a zero-valued memory byte, which is unsafe and out-of-bounds access.

Fix:

main.cpp 1:

#include <stdio.h>

int arrSize(const char *a) {
  int it = 0;
  int size = 0;
  while (a[it] != '\0') {
      size;
      it;
  }
  return size;
}

int main() {
  const char a[5   1] = {'a', 'b', 'b', 'v', 's', '\0'};
  const char b[4   1] = {'c', 'b', 'b', 'v', '\0'};
  const char c[4   1] = {'c', 'b', 'b', 'v', '\0'};
  printf("%d %d %d", arrSize(a), arrSize(b), arrSize(c));
}

CodePudding user response:

You need to put '\0' to the end of array explicitly or initialize it as string:

int main(){
    const char a[] = "abbvs";
    const char b[] = "cbbv";
    const char c[] = "cbbv";
    printf("%d %d %d", arrSize(a), arrSize(b), arrSize(c));
    return 0;
}

In this case compiler will put '\0' automatically to the end of array.

CodePudding user response:

You cannot assume that there is a 0 at the end of the array unless you explicitly set that as an element. (The notation "abbvs" - which is a const char[6] literal - does that for you.)

The behaviour of accessing an element outside the bounds of the array is undefined. Don't do it.

Use std::string instead, or pass the size as a parameter; probably as a std::size_t type.

This all said, you could use std::size(a) in place of arrSize(a) etc. although you will need to change your format specifier to %zu. std::size uses some clever template trickery to obviate pointer decay.

  • Related