![](/img/trans.png)
[英]How to return a const char* from a function after modifying it in c++?
[英]How to return a const char * from a C/C++ function?
我有以下 C++ 函數,它從閃存中讀取一個字符串並返回它。 我想避免使用String類,因為這是一個Arduino,我已經被告知,為Arduino的String類是越野車。
const char* readFromFlashMemory()
{
char s[FLASH_STOP_ADDR-FLASH_START_ADDR+2];
memset(s, (byte)'\0', FLASH_STOP_ADDR-FLASH_START_ADDR+2);
unsigned short int numChars = 0;
for (int i = FLASH_START_ADDRESS; i <= FLASH_STOP_ADDRESS; i++)
{
byte b = EEPROM.read(i);
if (b == (byte)'\0')
return s;
else
s[numChars++] = (char)b;
}
}
這個功能似乎有效。 但是調用方法返回一個空字符串。 我是否不允許返回指向此函數堆棧上的字符數組的指針? 我應該如何編寫此函數以便調用函數接收我想傳遞給它的值的最佳/最慣用的方法?
這些評論可能會讓您誤入歧途,或者充其量會使您感到困惑。 讓我用一些選項來分解它。
首先,問題正如你所說:當函數從堆棧中彈出給調用者時,你返回的地址的數組不再存在。 忽略這一點會導致未定義行為。
以下是一些選項以及一些討論:
調用者擁有緩沖區
void readFromFlashMemory(char *s, size_t len)
優點是調用者可以選擇如何分配這塊內存,這在嵌入式環境中很有用。
請注意,為了方便起見,您也可以選擇從此函數返回s
,或傳達一些額外的含義。
對我來說,如果我在 Arduino 等嵌入式環境中工作,這將是我 100% 的偏好。
使用std::string
、 std::vector
或類似的
std::string readFromFlashMemory()
如果您不關心分配開銷和其他潛在問題(例如隨着時間的推移出現碎片),這可能是您執行此操作的方式。
自己分配內存
char* readFromFlashMemory()
如果您想確保分配的內存大小正好合適,那么您可能會先讀入本地緩沖區,然后分配內存並進行復制。 與std::string
或其他處理堆內存的解決方案相同的內存注意事項。
這種形式還具有調用者的噩夢般的屬性,負責管理返回的指針並最終調用delete[]
。 這是非常不可取的。 這也很常見。 :(
如果絕對必須,返回動態分配的內存的更好方法
std::unique_ptr<char[]> readFromFlashMemory()
與#3 相同,但指針是安全管理的。 需要 C++11 或更高版本。
使用靜態緩沖區
const char* readFromFlashMemory() { static char s[FLASH_STOP_ADDR-FLASH_START_ADDR+2]; // ... return s; }
一般不以為然。 特別是因為這種類型的模式會在多線程環境中導致令人討厭的問題。
人們大多選擇這種方法是因為他們很懶惰並且想要一個簡單的界面。 我想一個好處是調用者不必知道什么大小的緩沖區是可以接受的。
使用內部緩沖區創建自己的類
class FlashReader { public: const char* Read(); private: char buffer[FLASH_STOP_ADDR-FLASH_START_ADDR+2]; };
這更像是一個冗長的解決方案,並且可能開始聽起來像是過度設計。 但它確實結合了 #1 和 #5 的最佳部分。 也就是說,您可以獲得緩沖區的堆棧分配,您不需要知道大小,並且函數本身不需要額外的參數。
如果您確實想要一個靜態緩沖區,那么您可以只定義該類的一個靜態實例,但不同之處在於代碼中的明確意圖。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.