简体   繁体   English

const char * 数组中的元素数

[英]Number of elements in const char * array

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.我在 C 中写了一个 function 作为参数const char *p我想检查该数组中的元素数量,但效果不佳。

#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.但是上面的代码给出了 8, 12, 16 output 我不知道为什么。

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

This loop ends when the element of the array is equal to the null terminator character.当数组的元素等于 null 终止符时,此循环结束。

 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.您的 arrays 都不包含 null 终止符。 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:如果将 null 终止符添加到 arrays,则 function 将成功计算第一个空终止符之前的非空终止符字符数:

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 .请注意,无需编写此arrSize ,因为它由标准库以名称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.当您将指向数组元素的指针传递给 function 时,没有通用的方法可以使用该指针确定数组的大小而不依赖于终止符值,例如 null 终止字符串的情况。

When a function needs to access a non-terminated array of arbitrary length, a common C idiom is to pass that size into the function as an argument.当 function 需要访问任意长度的非终止数组时,常见的 C 习惯用法是将该大小作为参数传递给 function。 Modern C++ idiom is to use std::span or equivalent which is essentially same except the compiler can deduce the size of an array.现代 C++ 习惯用法是使用std::span或等效的,除了编译器可以推断数组的大小外,它们本质上是相同的。

You can determine the size of an array variable within the scope where the array is declared.您可以在声明数组的 scope 中确定数组变量的大小。 A common C idiom is to divide sizeof the array with sizeof the element type.一个常见的sizeof习惯用法是将数组的sizeof除以元素类型的大小。 Modern C++ idiom is to use std::size .现代 C++ 成语是使用std::size Example:例子:

const char a[5] = {'a', 'b', 'b', 'v', 's'};,
void operate_on_array(const char *arr, size_t size);

// C
operate_on_array(a, sizeof a / sizeof *a);

// C++ with std::size
operate_on_array(a, std::size(a));

// C++ with std::span
operate_on_array(std::span<const char> arr);
operate_on_array(a);

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.如果没有字符串结尾字符0x0 (或'\0' ,您的 function 将一直持续到零值 memory 字节,这是不安全和越界访问。

Fix:使固定:

main.cpp 1:主.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));
}

You need to put '\0' to the end of array explicitly or initialize it as string:您需要将 '\0' 明确地放在数组的末尾或将其初始化为字符串:

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.在这种情况下,编译器会自动将 '\0' 放在数组的末尾。

You cannot assume that there is a 0 at the end of the array unless you explicitly set that as an element.除非明确将其设置为元素,否则不能假定数组末尾有 0。 (The notation "abbvs" - which is a const char[6] literal - does that for you.) (符号"abbvs" ——它是一个const char[6]文字——为你做到了。)

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;改用std::string ,或将大小作为参数传递; probably as a std::size_t type.可能是std::size_t类型。

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(a)代替arrSize(a)等,尽管您需要将格式说明符更改为%zu std::size uses some clever template trickery to obviate pointer decay. std::size使用一些巧妙的模板技巧来避免指针衰减。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM