當您將字串傳遞給 C 中的函式時,字串將被解釋為指標,例如func(str)將指標傳遞給名為 str 的記憶體塊。所以默認情況下,字串在傳遞給函式時已經是指標。有沒有辦法通過值傳遞字串,而您不必最終操作 的內容str?
uj5u.com熱心網友回復:
首先,什么是字串?它是一個字符陣列,然后是一個\0. 只是為了確保我們都同意這一點。
所以問題是,你能按值傳遞一個字符陣列嗎?答案是肯定的,但前提是它位于結構或聯合中:
struct String40Chars {
char str[41];
};
void f(struct String40Chars s) {
// s was passed by value - including s.str
}
但是,由于歷史怪癖,您不能直接傳遞陣列:
void f(char str[41]) {
// you would think this would work,
// but actually, the compiler converts it to void f(char *str)
}
這對于那些真正想要按值傳遞陣列的人來說是不幸的。
幸運的是,您通常不需要這樣做。在我能想到的每一種情況下,指標都足夠好,而且速度也更快,因為它不需要復制陣列。也許您可以詳細說明為什么需要按值傳遞陣列。
PS您談論“字串是指標”,但這是無稽之談。字串是陣列。您可以擁有指向陣列的指標,但指標不是陣列。
uj5u.com熱心網友回復:
在 C 中使用字串引數實作值語意的唯一方法是擁有一個包裝字串的結構或聯合。
就像是:
#define STR_BY_VALUE_MAX_LENGTH 128
typedef struct StrByValue_
{
char str[STR_BY_VALUE_MAX_LENGTH];
} StrByValue;
void f(StrByValue strByVal)
{
// Changes to strByVal will not affect the caller
}
當然,呼叫者必須StrByValue通過將字串(例如使用 strcpy)復制到str欄位中來初始化物件。如果您不想使用以零結尾的字串,也可以向結構添加一個len欄位。StrByValue
uj5u.com熱心網友回復:
其他答案是將字串存盤在堆疊記憶體中,初始化后無法調整大小,我認為這不是長久之計。根據我的說法,字串應該存盤在堆記憶體中,以便我們以后可以擴展它,想想當最后附加一些東西時擴展的資料結構。
為了用一些糖語法很好地實作這一點,我們需要創建 3 個函式,即init_string(),append_string()和free_string().
init_string(): 初始化指標并賦值len = INIT_STR_LENappend_string(): 可用于連接兩個字串free_string():釋放分配的堆ptr,因此沒有記憶體泄漏
代碼:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
char *ptr;
size_t len;
} string;
string init_string(const char *s)
{
string x;
x.len = strlen(s);
x.ptr = malloc(x.len 1);
if (!x.ptr)
{
fprintf(stderr, "err: memory can't be allocated\n");
exit(EXIT_FAILURE);
}
memcpy(x.ptr, s, x.len 1);
return x;
}
void append_string(string *s, const char *str)
{
if (!str || !s)
{
fprintf(stderr, "err: null was passed\n");
exit(EXIT_FAILURE);
}
size_t str_l = strlen(str);
s->ptr = realloc(s->ptr, s->len str_l 1);
if (!s->ptr)
{
fprintf(stderr, "err: memory can't be allocated\n");
exit(EXIT_FAILURE);
}
memcpy(s->ptr s->len, str, str_l 1);
s->len = str_l;
}
void free_string(string *s)
{
if (!s)
{
fprintf(stderr, "err: null was passed\n");
exit(EXIT_FAILURE);
}
free(s->ptr);
s->len = 0;
}
void foo(string a) // got the value of a
{
// cannot modified permanently
}
void bar(string *a) // got the address of a
{
// can be modified permanently
}
int main(void)
{
string str = init_string("Hello world, I'm a c-string.");
puts(str.ptr);
append_string(&str, "stackoverflow");
puts(str.ptr);
free_string(&str);
return EXIT_SUCCESS;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/462104.html
標籤:C
上一篇:無法從c中的文本檔案中讀取資料
