方法1:静态内存
这里有一个方法来实现帮助函数:
这个方法的好处是比较简单,但是它也有很多严重的缺点。
返回的字符串可能比你期望的要长。无论你指定buf什么样的长度,它仍然可能太小。如果实际的字符串太长,你或者超出数组的范围最终导致代码悲惨的失败,或者必须擅自截断那个字符串。
对于较短的字符串,这个函数因为buf数组的大部分没有用到而浪费了内存。每一次get_string调用覆盖了前一次调用的结果。如果调用者想保留前一次调用的字符串,在再一次调用这个函数之前,他必须把上一次的字符串做一份拷贝。
这个函数不是可重入的。如果多个线程同时调用get_string,一个线程会覆盖另一个线程的结果。
方法2:静态指针指向的动态内存
这是第二种实现get_string函数的方法:
这个方法使用指向动态内存的一个静态指针,不断地增长缓冲区用来容纳数据。使用动态内存除去了字符串任意长度的限制,当然另一方面它
仍然有前一个方法的问题:每一次调用仍然覆盖前一次调用的结果,函数不是可重入的。这个版本也浪费了相当大数量的内存,因为它永远消
耗最坏情况下的内存数量(它曾经读取的最长字符串的长度)。
方法3:调用者分配的内存
在这个方法中,我们让调用者负责提供容纳字符串的内存。
这个就是被UNIX操作系统的read系统调用所采纳的方法。它解决了大部分的问题。包括它是可重入的,不会内存溢出,不会擅自的截断数据。
(潜在的浪费内存的数量在调用者的控制之下。)
弊端在于如果字符串比提供的缓冲区更长,调用者必需保持调用直到所有的数据被读取。(如果我们假定数据源隐含在调用的线程中,那么多
个线程的重复调用是可重入的。)
方法4:返回指针指向的动态内存
在这个方法中,get_string动态的分配一个足够大的缓冲区来容纳结果,并返回一个指向缓冲区的指针。
这个几乎和第二个方法一样(它们之间的区别是get_string没有使用静态数据)。它几乎解决了所有的问题:函数是可重入的,对于结果字符
串没有一个隐含的大小限制。对于长字符串并不要求多次的函数调用(但是动态分配增加了一些开销)。
这个方法的主要缺点是它让调用者负责释放分配的内存:
这里有一个方法来实现帮助函数:
这个方法的好处是比较简单,但是它也有很多严重的缺点。
返回的字符串可能比你期望的要长。无论你指定buf什么样的长度,它仍然可能太小。如果实际的字符串太长,你或者超出数组的范围最终导致代码悲惨的失败,或者必须擅自截断那个字符串。
对于较短的字符串,这个函数因为buf数组的大部分没有用到而浪费了内存。每一次get_string调用覆盖了前一次调用的结果。如果调用者想保留前一次调用的字符串,在再一次调用这个函数之前,他必须把上一次的字符串做一份拷贝。
这个函数不是可重入的。如果多个线程同时调用get_string,一个线程会覆盖另一个线程的结果。
方法2:静态指针指向的动态内存
这是第二种实现get_string函数的方法:
这个方法使用指向动态内存的一个静态指针,不断地增长缓冲区用来容纳数据。使用动态内存除去了字符串任意长度的限制,当然另一方面它
仍然有前一个方法的问题:每一次调用仍然覆盖前一次调用的结果,函数不是可重入的。这个版本也浪费了相当大数量的内存,因为它永远消
耗最坏情况下的内存数量(它曾经读取的最长字符串的长度)。
方法3:调用者分配的内存
在这个方法中,我们让调用者负责提供容纳字符串的内存。
这个就是被UNIX操作系统的read系统调用所采纳的方法。它解决了大部分的问题。包括它是可重入的,不会内存溢出,不会擅自的截断数据。
(潜在的浪费内存的数量在调用者的控制之下。)
弊端在于如果字符串比提供的缓冲区更长,调用者必需保持调用直到所有的数据被读取。(如果我们假定数据源隐含在调用的线程中,那么多
个线程的重复调用是可重入的。)
方法4:返回指针指向的动态内存
在这个方法中,get_string动态的分配一个足够大的缓冲区来容纳结果,并返回一个指向缓冲区的指针。
这个几乎和第二个方法一样(它们之间的区别是get_string没有使用静态数据)。它几乎解决了所有的问题:函数是可重入的,对于结果字符
串没有一个隐含的大小限制。对于长字符串并不要求多次的函数调用(但是动态分配增加了一些开销)。
这个方法的主要缺点是它让调用者负责释放分配的内存: