[英]How to get the real and total length of char * (char array)?
對於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");
你不能。 無論如何,不是 100% 准確。 指針沒有長度/大小,只有它自己的. 它所做的只是指向內存中保存字符的特定位置。 如果該字符是字符串的一部分,那么您可以使用strlen
來確定當前指向的字符strlen
是什么字符,但這並不意味着您的情況下的數組有那么大。
基本上:
指針不是數組,因此不需要知道數組的大小。 指針可以指向單個值,因此指針可以存在,甚至沒有數組。 它甚至不關心它所指向的內存位於何處(只讀、堆或堆棧......無關緊要)。 指針除了自身之外沒有其他長度。 一個指針就是...
考慮一下:
char beep = '\a';
void alert_user(const char *msg, char *signal); //for some reason
alert_user("Hear my super-awsome noise!", &beep); //passing pointer to single char!
void alert_user(const char *msg, char *signal)
{
printf("%s%c\n", msg, *signal);
}
指針可以是單個字符,也可以是數組的開頭、結尾或中間...
將字符視為結構。 您有時會在堆上分配單個結構。 這也創建了一個沒有數組的指針。
僅使用一個指針來確定它指向的數組有多大是不可能的。 最接近它的是使用calloc
並計算可以通過指針找到的連續 \\0 字符的數量。 當然,一旦您將內容分配/重新分配給該數組的鍵,這將不起作用,並且如果數組外的內存恰好也包含\\0
,它也會失敗。 所以使用這種方法是不可靠的,危險的,而且通常很愚蠢。 別。 做。 它。
另一個比喻:
把指針想象成一個路標,它指向X 鎮。 標志不知道那個城鎮是什么樣子,也不知道或關心(或可以關心)住在那里的人。 它的工作是告訴你在哪里可以找到城鎮 X。 它只能告訴你那個城鎮有多遠,而不能告訴你它有多大。 該信息被認為與道路標志無關。 這是你只能通過查看城鎮本身才能找到的東西,而不是指向它方向的路標
所以,使用指針你唯一能做的就是:
char a_str[] = "hello";//{h,e,l,l,o,\0}
char *arr_ptr = &a_str[0];
printf("Get length of string -> %d\n", strlen(arr_ptr));
但是,當然,這僅在數組/字符串以 \\0 結尾時才有效。
作為旁白:
int length = sizeof(a)/sizeof(char);//sizeof char is guaranteed 1, so sizeof(a) is enough
實際上是將size_t
( sizeof
的返回類型)分配給int
,最好寫:
size_t length = sizeof(a)/sizeof(*a);//best use ptr's type -> good habit
由於size_t
是無符號類型,如果sizeof
返回更大的值,則length
的值可能是您沒想到的......
如果char *
以 0 結尾,則可以使用strlen
否則,無法確定該信息
只有兩種方式:
如果您的char *
指向的內存指針表示一個 C 字符串(即,它包含以 0 字節標記其結尾的字符),您可以使用strlen(a)
。
否則,您需要將長度存儲在某處。 實際上,指針只指向一個char
。 但是我們可以把它當作指向數組的第一個元素來對待。 由於該數組的“長度”未知,因此您需要將該信息存儲在某處。
只需使用std::vector<char>
為您保留(動態)大小。 (獎金,免費的內存管理)。
或std::array<char, 10>
保持(靜態)大小。
創建一個結構來保存信息,例如:
typedef struct {
char* ptr;
int size;
} my_array;
my_array malloc_array(int size)
{
my_array res;
res.ptr = (char*) malloc(size);
res.size = size;
return res;
}
void free_array(my_array array)
{
free(array.ptr);
}
只給指針,你不能。 您必須保持傳遞給new[]
的長度,或者更好地使用std::vector
來跟蹤長度,並在完成后釋放內存。
注意:這個答案只針對 C++,而不是 C。
字符 *a = 新字符 [10];
我的問題是我怎樣才能得到一個字符的長度 *
很簡單。:) 只加一個語句就夠了
size_t N = 10;
char *a = new char[N];
現在你可以得到分配數組的大小
std::cout << "The size is " << N << std::endl;
許多人在這里提到了 C 標准函數 std::strlen。 但它不返回字符數組的實際大小。 它只返回存儲的字符串文字的大小。
區別如下。 如果以您的代碼片段為例
char a[] = "aaaaa";
int length = sizeof(a)/sizeof(char); // length=6
然后 std::strlen( a ) 將返回 5 而不是您的代碼中的 6 。
所以結論很簡單:如果您需要動態分配字符數組,請考慮使用類std::string
。 它有 methof size 和它的同義詞長度,允許隨時獲取數組的大小。
例如
std::string s( "aaaaa" );
std::cout << s.length() << std::endl;
或者
std::string s;
s.resize( 10 );
std::cout << s.length() << std::endl;
所以sizeof運算符的作用是返回存儲操作數所需的存儲量(以字節為單位)。
存儲字符所需的存儲量始終為 1 個字節。 所以sizeof(char)
將始終返回 1。
char a[] = "aaaaa";
int len1 = sizeof(a)/sizeof(char); // length = 6
int len2 = sizeof(a); // length = 6;
這對於len1
和len2
都是相同的,因為除以 1 不會影響方程。
len1
和len2
攜帶值 6 的原因與字符串終止符'\\0'
。 這也是一個向長度添加另一個字符的字符。 因此,您的長度將是 6 而不是您期望的 5。
char *a = new char[10];
int length = sizeof(a)/sizeof(char);
您已經提到這里的長度結果是 4,這是正確的。 同樣, sizeof運算符返回操作數的存儲量,在您的情況下,它是一個指針a
。 一個指針需要 4 個字節的存儲空間,因此在這種情況下長度為 4。 因為您可能將其編譯為 32 位二進制文件。 如果您創建了 64 位二進制文件,則結果將為 8。
這個解釋可能已經在這里了。 只想分享我的兩分錢。
您可以實現自己的new
和delete
函數,以及一個額外的get-size
函數:
#define CEIL_DIV(x,y) (((x)-1)/(y)+1)
void* my_new(int size)
{
if (size > 0)
{
int* ptr = new int[1+CEIL_DIV(size,sizeof(int))];
if (ptr)
{
ptr[0] = size;
return ptr+1;
}
}
return 0;
}
void my_delete(void* mem)
{
int* ptr = (int*)mem-1;
delete ptr;
}
int my_size(void* mem)
{
int* ptr = (int*)mem-1;
return ptr[0];
}
或者,您可以以類似的方式覆蓋new
和delete
運算符。
這聽起來可能是 Evil™,我還沒有測試過,但是如何在分配到'\\0'
初始化數組中的所有值,然后使用strlen()
呢? 這將為您提供所謂的實際價值,因為它會在遇到的第一個'\\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*
否則定義一個自定義結構來跟蹤長度並分配內存。
當 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
我不會推薦這個解決方案(向量更好),但如果你真的很絕望,你可以找到一個關系並能夠得出從堆分配的字節數。
在C++17
(或更新版本)中,您可以使用std::string_view
作為字符串文字的零開銷包裝器。
合法的問題。 我個人認為,由於字符指針 (char*) 的作用,人們將指針與數組混淆,它們的用途與字符數組 (char __[X])幾乎相同。 這意味着指針和數組是不一樣的,所以指針當然不包含特定的大小,如果我可以這么說,只包含一個地址。 但是,您仍然可以嘗試類似於 strlen 的東西。
int ssize(const char* s)
{
for (int i = 0; ; i++)
if (s[i] == 0)
return i;
return 0;
}
您可以像這樣找到 char* 字符串的長度:
char* mystring = "Hello World";
int length = sprintf(mystring, "%s", mystring);
sprintf() 將 mystring 打印到自身上,並返回打印的字符數。
你可以試試這個:
int lengthChar(const char* chararray) {
int n = 0;
while(chararray[n] != '\0')
n ++;
return n;
}
Strlen 命令對我有用。 您可以嘗試以下代碼。
// 字符 *s
unsigned int strLength=strlen(s);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.