3

我刚开始使用 C 语言,从来不用处理我以前使用的语言中的指针,所以我想知道如果只是修改一个字符串,哪种方法更好。

指针字符串与正常。

此外,如果您想提供有关何时使用指针的更多信息,那就太好了。当我发现“正常”函数甚至会修改传递的字符串,并在没有返回值的情况下在主函数中更新时,我感到很震惊。

#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
4

4 回答 4

7

在函数声明中,char []char *是等价的。具有外层数组类型的函数参数被转换为等效的指针类型;这会影响调用代码和函数体本身。

正因为如此,最好使用char *语法,否则您可能会感到困惑并尝试例如采用sizeof外层固定长度数组类型参数:

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

当您将声明为指向函数的指针的参数传递(并且未声明指针参数const)时,您明确授予函数修改指针指向的对象或数组的权限。

于 2012-08-23T10:20:07.110 回答
5

C 中的问题之一是数组是二等公民。在几乎所有有用的情况下,其中当将它们传递给函数时,数组会衰减为指针(从而丢失它们的大小信息)。

因此,将数组作为T* argor没有区别T arg[]——后者只是前者的同义词。两者都是指向 中string定义的变量的第一个字符的指针main(),因此两者都可以访问原始数据并可以对其进行修改。


注意:C 总是为每个副本传递参数。在这种情况下也是如此。但是,当您传递一个指针(或衰减为指针的数组)时,复制的是地址,因此可以通过其地址的两个不同副本访问所引用的对象。

于 2012-08-23T10:21:15.017 回答
1

有指针 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)如果我们想将成员函数与成员变量一起保留在结构中,那么我们可以使用函数指针。

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)考虑一个data尺寸s非常大的结构。如果我们想将此结构的变量发送到另一个函数,最好作为参考发送。因为这将减少为新函数创建的激活记录(堆栈中)大小。

使用指针 - 在函数的激活记录(堆栈中)中只需要 4 个字节(32 位 m/c)或 8 个字节(64 位 m/c)func

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

没有指针 - 它需要s函数的激活记录(堆栈中)中的字节func。考虑到这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
...
于 2012-08-23T13:29:23.407 回答
0

除了其他答案之外,我对“字符串”操作函数(字符串 = 零终止字符数组)的评论:始终将字符串参数作为返回值返回。

所以你可以使用函数程序或函数,比如printf("Dear %s, ", normal(buf));

于 2012-08-23T12:55:13.000 回答