如何获取char*(字符数组)的真实和总长度?

79

对于一个char []数组,我可以通过以下方式轻松获取其长度:

char a[] = "aaaaa";
int length = sizeof(a)/sizeof(char); // length=6

然而,我不能像这样获取 char * 的长度:

char *a = new char[10];
int length = sizeof(a)/sizeof(char);

因为我知道这里的 a 是一个指针,所以这里的 length 始终为 4(或其他系统中的某个数字)。

我的问题是,之后如何获取 char * 的长度?我知道有人可能会质疑我已经知道它是 10,因为你刚刚创建了它。但我想知道这是因为获取其长度的步骤可能与其创建的步骤相隔很远,而我不想返回长长的路程来检查这个数字。此外,我还想知道它的真实长度。

具体来说:

  • 如何获取它的真实长度 length=5
  • 如何获取它的总长度 length=10

对于以下示例:

char *a = new char[10]; 
strcpy(a, "hello");

15
strlen函数是用来计算字符串长度的,它接受一个字符串作为参数并返回该字符串中字符的数量,不包括结尾的空字符。 - Kiril Kirov
3
@KirilKirov这并不会给出数组的长度。嗯,特殊情况下会有,但这很少见。 - juanchopanza
2
这个问题以前已经回答过了,指针并不保存它所指向的数据块的大小信息(如果它指向一个数组),只保存它在内存中的起始位置。 - A Person
6
你可以使用 std::vector<char> ,这样你就可以获取大小,并且内存管理已经为你完成。 - Jarod42
2
请问您是在询问哪种编程语言?如果是C语言,那么您不能使用new;如果是C++,则应该使用更高级的抽象,如vector来解决这个问题。 - Mike Seymour
显示剩余15条评论
16个回答

0
你可以创建一个回溯字符,例如,你可以在字符串末尾添加任何特殊字符,比如“%”,然后检查该字符的出现情况。
但这是一种非常危险的方式,因为该字符也可能存在于char*的其他位置。
char* stringVar = new char[4] ; 
stringVar[0] = 'H' ; 
stringVar[1] = 'E' ; 
stringVar[2] = '$' ; // back-tracker character.
int i = 0 ;
while(1)
{
   if (stringVar[i] == '$')
     break ; 
   i++ ; 
}
//  i is the length of the string.
// you need to make sure, that there is no other $ in the char* 

否则,定义一个自定义结构来跟踪长度并分配内存。

2
呃,那个味道真糟糕!最好使用空字符来终止字符串。使用可能出现在实际文本中的字符(比如,“你欠我1美元,因为那个可怕的想法”;-))是一个坏主意。 - DarkDust
@ps06756: 仍然会崩溃stringVar = new char[10],并且没有回答原始问题。 - Jarod42

0

当 new 分配数组时,根据编译器(我使用 GNU C++),数组前面的字包含有关分配的字节数的信息。

测试代码:

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

int
main ()
{
    int arraySz;
    char *a;
    unsigned int *q;

    for (arraySz = 5; arraySz <= 64; arraySz++) {

        printf ("%02d - ", arraySz);

        a = new char[arraySz];
        unsigned char *p = (unsigned char *) a;

        q = (unsigned int *) (a - 4);
        printf ("%02d\n", (*q));

        delete[] (a);

    }
}

在我的电脑上输出如下:

05 - 19
06 - 19
07 - 19
08 - 19
09 - 19
10 - 19
11 - 19
12 - 19
13 - 27
14 - 27
15 - 27
16 - 27
17 - 27
18 - 27
19 - 27
20 - 27
21 - 35
22 - 35
23 - 35
24 - 35
25 - 35
26 - 35
27 - 35
28 - 35
29 - 43
30 - 43
31 - 43
32 - 43
33 - 43
34 - 43
35 - 43
36 - 43
37 - 51
38 - 51
39 - 51
40 - 51
41 - 51
42 - 51
43 - 51
44 - 51
45 - 59
46 - 59
47 - 59
48 - 59
49 - 59
50 - 59
51 - 59
52 - 59
53 - 67
54 - 67
55 - 67
56 - 67
57 - 67
58 - 67
59 - 67
60 - 67
61 - 75
62 - 75
63 - 75
64 - 75

我不建议使用这种方法(向量更好),但如果你真的很绝望,你可以找到一个关系并能够推断从堆中分配的字节数。

0

合理的问题。我个人认为,人们会将指针与数组混淆,这是由于字符指针(char*)造成的,它们几乎与字符数组(char __[X])具有相同的作用。这意味着指针和数组不同,因此指针当然不包含特定的大小,只包含地址,如果我这样说的话。但是,你仍然可以尝试类似于strlen的东西。

int ssize(const char* s)
{
    for (int i = 0; ; i++)
        if (s[i] == 0)
            return i;

    return 0;
}

-1
你可以像这样找到 char* 字符串的长度:
char* mystring = "Hello World";
int length = sprintf(mystring, "%s", mystring);

sprintf() 将 mystring 打印到自身,并返回打印的字符数。


1
所以它与 strlen 完全等价,只有在数组中的最后一个字符是 NUL,并且在那之前没有任何 NULs 时才有效。 - Toby Speight

-2
你可以尝试这个:
int lengthChar(const char* chararray) {
   int n = 0;
   while(chararray[n] != '\0')
     n ++;
   return n;  
}

这只是 strlen() 的一个糟糕实现,带有它所有的限制。 - Toby Speight

-4

strlen命令对我有效。你可以尝试以下代码。

// char *s

unsigned int  strLength=strlen(s);

取决于s.. 它是C字符串吗? - Maroun
你的代码甚至无法编译。没有 return 语句,没有 },并且将对 strlen 的调用包装在一个带有未使用参数、未使用变量和误导性名称的函数中是绝对可怕的。此外,你试图将 char ** 作为参数传递到你的注释中。 - DarkDust
你好。我提供一个示例代码来帮助你理解,但这只是其中的一部分代码。 - ragip
如果你想的话,可以使用这段代码... int WriteString(char *s){ return strlen(s);} - ragip
2
你为什么要坚持将 strlen 包装在一个名为 WriteString 的函数中?你的函数并没有写入字符串,它只返回字符串的长度。 - DarkDust
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接