簡體   English   中英

C函數實現 - 使用Pointer vs without Pointer

[英]C Function implementation - with Pointer vs without Pointer

我剛剛開始使用C,並且從來沒有處理過我以前用過的語言中的指針,所以我想知道如果只是修改一個字符串,哪種方法更好。

指針串與正常。

此外,如果您想提供有關何時使用指針的更多信息,那將是很棒的。 當我發現函數“normal”甚至會修改傳遞的字符串,並在main函數中更新而沒有返回值時,我感到很震驚。

#include <stdio.h>

void pointerstring(char *s);
void normal(char s[]);

int main() {
    char string[20];
    pointerstring(string);
    printf("\nPointer: %s\n",string);
    normal(string);
    printf("Normal: %s\n",string);
}

void pointerstring(char *s) {
    sprintf(s,"Hello");
}
void normal(char s[]) {
    sprintf(s,"World");
}

輸出:

Pointer: Hello
Normal: World

在函數聲明中, char []char *是等效的。 具有外層數組類型的函數參數被轉換為等效的指針類型; 這會影響調用代碼和函數體本身。

因此,最好使用char *語法,否則可能會混淆並嘗試獲取外層固定長度數組類型參數的sizeof

void foo(char s[10]) {
    printf("%z\n", sizeof(s));  // prints 4 (or 8), not 10
}

當您將聲明為指針的參數傳遞給函數(並且指針參數未聲明為const )時,您將顯式賦予函數權限以修改指針指向的對象或數組。

C中的一個問題是陣列是二等公民。 在幾乎所有有用的情況下, 它們傳遞給函數時,數組會衰減到指針 (從而丟失它們的大小信息)。

因此,無論是將數組作為T* arg還是T arg[]都沒有區別 - 后者僅僅是前者的同義詞 兩者都是指向main()定義的string變量的第一個字符的指針,因此它們都可以訪問原始數據並可以對其進行修改。


注意:C始終為每個副本傳遞參數。 在這種情況下也是如此。 但是,當您傳遞一個指針(或一個衰減到指針的數組)時,復制的是地址 ,因此所引用的對象可以通過其地址的兩個不同副本訪問。

用指針Vs沒有指針

1)我們可以直接將局部變量引用(地址)傳遞給新函數來處理和更新值,而不是將值發送到函數並從函數返回值。

用指針

...
int a = 10;
func(&a);
...

void func(int *x);
{
   //do something with the value *x(10)
   *x = 5;
}

沒有指針

...
int a = 10;
a = func(a);
...

int func(int x);
{
   //do something with the value x(10)
   x = 5;
   return x;
}

2)全局變量或靜態變量具有生命期范圍,局部變量僅具有范圍的功能。 如果我們想要創建用戶定義的范圍變量,則意味着需要指針。 這意味着如果我們想創建一個應該在n個函數中具有范圍的變量,則在第一個函數中為該變量創建一個動態內存並將其傳遞給所有函數,最后釋放第n個函數中的內存。

3)如果我們想要將成員函數與成員變量一起保存在sturucture中那么我們可以去尋找函數指針。

struct data;

struct data
{
    int no1, no2, ans;
    void (*pfAdd)(struct data*);
    void (*pfSub)(struct data*);    
    void (*pfMul)(struct data*);
    void (*pfDiv)(struct data*);
};

void add(struct data* x)
{
   x.ans = x.no1, x.no2;
}
...
struct data a;
a.no1 = 10;
a.no1 = 5;
a.pfAdd = add;
...
a.pfAdd(&a);
printf("Addition is %d\n", a.ans);
...

4)考慮尺寸s非常大的結構data 如果我們想將這個結構的變量發送到另一個函數,最好發送作為參考。 因為這會減少為新函數創建的激活記錄(堆棧)大小。

使用指針 - 在函數func激活記錄(堆棧中)中只需要4字節(32位m / c)或8字節(64位m / c)

...
struct data a;
func(&a);
...

沒有指針 - 它將需要函數func激活記錄(在堆棧中)中的s個字節。 考慮到ssizeof(struct data) ,這是非常大的值。

...
struct data a;
func(a);
...

5)我們可以用指針改變常量變量的值。

...
const int a = 10;
int *p = NULL;
p = (int *)&a;
*p = 5;
printf("%d", a); //This will print 5
...

除了其他答案,我對“字符串”操縱函數的評論(字符串=零終止字符數組):總是返回字符串參數作為返回值。

所以你可以使用函數procedural或functional,比如printf("Dear %s, ", normal(buf));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM