你能解释一下下面的代码吗?
str = (char *) malloc (sizeof(char) * (num+1));
- 在这里做什么
malloc
? - 为什么
num + 1
使用?
malloc
是一个在堆上分配一块内存并返回指向它的指针的函数。它类似于new
许多语言中的运算符。在这种情况下,它创建的内存块可以存在任意长度并具有任意大小。这本身就是相当深入的东西,这有点难以解释,需要一个单独的问题。
num + 1
补偿字符串末尾的空终止符。字符串通常需要知道它们有多长,而 C 的传统是在字符串的末尾为额外的字符分配空间,该字符始终是特殊字符\0
。这允许处理字符串的函数自动确定字符串的大小。例如,如果你想对字符串的每个字符做一些事情而不知道字符串有多长,你可以这样做:
const char *ptr = str;
while (*ptr != '\0') {
process(*ptr);
ptr++;
}
malloc
用于内存分配。
num + 1
是允许空终止符 - \0
。
前言:我不敢相信!当我学习 C 基础知识时(不是双关语),我对这种表达方式感到困惑。这就是为什么我在“解析代码”部分中详细介绍的原因。
第一个问题是解析代码
str = (char *) malloc (sizeof(char) * (num+1));
在使用 C/C++ 时,解析这种表达式是强制性的,所以我们将把它分解成它的组件。我们在这里看到的第一件事是:
variable = (expression) function (expression) ;
第一次看到它时,我只是“嘿,我不敢相信有一种编程语言可以通过将函数的参数放在函数调用的左侧和右侧来调用函数!”。
事实上,这一行应该读作如下:
variable = function_a (function_b (expression)) ;
在哪里 :
expression is sizeof(char) * (num+1)
function_b is malloc
function_a is a cast operator
正如在别处已经解释的那样,C 风格的演员表操作符更像
(function_a) expression
比更自然
function_a(expression)
这解释了整行代码的奇怪之处。
请注意,在 C++ 中,您可以使用这两种表示法,但您应该使用 static_cast、const_cast、reinterpret_cast 或 dynamic_cast 而不是上述表示法。使用 C++ 转换,上面的代码行将是:
str = static_cast<char *> ( malloc (sizeof(char) * (num+1)) ) ;
sizeof 是一个运算符。您可以将其视为处理类型的函数。您将类型作为参数传递,它将以字节为单位为您提供其大小。
所以,如果你写:
size_t i = sizeof(char) ;
size_t j = sizeof(int) ;
您可能(在 32 位 Linux 上)i 的值为 1,j 的值为 4。它在 malloc 中的使用就像说“我想要足够的空间来放置 25 辆 4 米长的汽车”而不是“我想要至少 100 米”。
Malloc的参数是一个size_t,也就是一个无符号整数。你给它以字节为单位的大小,如果成功,它会返回分配内存的地址,该地址足够大,可以用作数组。例如:
int * p = (int *) malloc (25 * sizeof(int)) ;
然后 p 指向一个内存,您可以在其中并排放置 25 个整数,就好像在一个索引从零到大小为一的数组中一样。例如:
p[0] = 42 ; // Ok, because it's the 1st item of the array
p[24] = 42 ; // Ok, because it's the 25th item of the array
p[25] = 42 ; // CORRUPTION ERROR, because you are trying to
// use the 26th item of a 25 items array !
注意:您也有指针算术,但这超出了问题的范围。
C 风格的字符串与其他语言的字符串有些不同。字符串的每个字符都可以是任何值,但不能为零。因为零(也称为 \0)标志着 ac 字符串的结尾。
换一种说法:你永远不知道 c 字符串的大小,但是通过搜索 \0 字符,你可以知道它在哪里结束(顺便说一句,这是缓冲区溢出和堆栈损坏的原因之一)。
例如,字符串“Hello”似乎有 5 个字符:
"Hello" seems to be an array containing 'H', 'e', 'l', 'l' and 'o'.
但实际上,它有 6 个字符,最后一个是字符 ZERO,使用转义字符 \0 表示。因此:
"Hello" is an array containing 'H', 'e', 'l', 'l', 'o' and 0.
这解释了当您想为“num”个字符的字符串分配足够的空间时,您分配的是“num + 1”个字符。
malloc分配内存。
num+1因为 num 是字符串中的字符数,+1 表示空终止符
在这种情况下,Malloc 分配了 num+1 倍 sizeof(char) 个字节。当您要分配元素数组时,这是标准做法。sizeof(char) 中的 char 通常替换为正在分配的数组类型。
严格来说,在这个例子中虽然 sizeof(char) 不是必需的。C 标准保证它的大小为 1,因此只需乘以 1。
malloc 在堆上分配一个 char 数组(在这种情况下)。
数组将是 num+1 长,但它可能保存的最长字符串是 'num' 长,因为 C 中的字符串需要一个结束的空字节。
Malloc 分配内存,在本例中为长度为 num 的字符串 str。(char *) 是 str 的类型 sizeof(char) 是每个字符所需的字节数。+1 用于字符串中的尾随空字符,通常为零。
malloc 是分配内存的调用。
上面的代码将为 num + 1 个字符分配空间。可能有一个包含 num 个字符的字符串,并且代码的作者为空终止符添加了空间。
调用后 str 将指向已分配的内存块的开始。
这段代码尝试分配一块可以容纳 num + 1 个 char 类型值的内存。因此,如果聊天等于 1 个字节且 num 为 10,它将尝试分配 11 个字节的内存并返回指向该内存的指针。
可能使用 +1 是因为程序员想要存储 num 个字符的字符串(字符数组),并且需要一个额外的 char 来存储终止 '\0'(空)字符。在 C/C++ 中。按照惯例,字符字符串以空字符结尾。
malloc 从堆中分配内存并返回一个指向它的指针。当您不知道编译时需要多少内存时,它很有用。
至于为什么(num+1),这真的取决于代码在做什么......也许num是字符串中的字符数,而+1是最后的NUL终止符字节。不过,我不知道在这种情况下 sizeof(char) 会是什么。
sizeof(char)
是安全的。不应假设每个字符只有一个字节。
我的问题是,如果你不知道 malloc 做什么,你在做什么编程?
man malloc
在 Linux 系统上。在 Windows 上。谁知道?大概 17 次鼠标点击。