const char *数组中的元素数量

发布于 2025-01-26 10:13:53 字数 561 浏览 3 评论 0原文

我在C中写了一个函数,该函数作为参数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));
}

但是上面的代码给出了8、12、16输出,我不知道为什么。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

思念绕指尖 2025-02-02 10:13:54
  while(a [it]!='\ 0'){
 

当数组的元素等于零终端字符时,此循环结束。

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

您的数组都不包含零终端字符。循环不会在元素上停止,它将在数组范围之外访问不存在的元素,并且程序的行为不确定。这是不好的。不要这样做。

如果将null终结器添加到数组中,则该函数将成功计算第一个null-terminator先前的非零件末端字符的数量:

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

请注意,无需编写此arrsize,因为它由标准库以名称strlen提供。


当您将数组元素的指针传递到函数中时,没有一般的方法可以使用该指针来确定数组的大小,而不依赖终结器值,例如NULL终止字符串。

当函数需要访问任意长度的非终止阵列时,一个常见的c习惯是将该大小作为参数传递到函数中。现代的C ++成语是使用std :: Span或等效的,除非编译器可以推断出数组的大小,否则基本相同。

您可以在声明数组的范围内确定数组变量的大小。一个常见的c是将sizeofsizeof元素类型的数组分配。现代的C ++成语是使用std ::大小。例子:

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);
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 a non-terminated array of arbitrary length, a common C idiom is to pass that size into the function as an argument. Modern C++ idiom is to use std::span or equivalent which is essentially same except the compiler can deduce the size of an array.

You can determine the size of an array variable within the scope where the array is declared. A common C idiom is to divide sizeof the array with sizeof the element type. Modern C++ idiom is to use 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);
请别遗忘我 2025-02-02 10:13:54

如果没有字符串结束char 0x0(或'\ 0',您的功能将继续运行,直到零值的内存字节为止,该字节不安全,并且不安全且外部访问修复

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

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));
}
一桥轻雨一伞开 2025-02-02 10:13:54

您需要将“ \ 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;
}

在这种情况下,编译器将自动将'\ 0'自动放在数组的末尾。

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.

┊风居住的梦幻卍 2025-02-02 10:13:54

您不能假设数组末端有一个0,除非您将其明确设置为元素。 (符号“ abbvs” - 是const char [6]字面 - 为您做到这一点。)

访问数组范围之外元素的行为是不明确的。不要做。

使用std :: String代替,或将大小作为参数传递;可能是std :: size_t类型。

这一切都说,您可以使用std :: size(a)代替arrsize(a)等。 %zu 。 std :: size使用一些巧妙的模板技巧来消除指针衰减。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文