为什么移动指针不会影响外部功能?

时间:2014-03-30 19:17:29

标签: c pointers

我有以下函数用于计算字符串中的空格:

int countSpace(char *str) {
        int nSpaces = 0;
        while (*(str) != '\0') {
                if (*(str) == ' ') {
                        nSpaces++;
                }
                str++;
        }
        return nSpaces;
}

我使用这个函数:

char a[]="Hello ";
printf("%d", countSpace(a));

我的问题是,当我这样做:printf("%s", a);,在调用countSpace之后,为什么a没有指向最后?我的意思是,我已经在countSpace函数内增加了指针,但外面似乎仍然指向了最开始。那是为什么?

我知道我在countSpace函数中的* str中所做的更改会影响外部,所以如果我这样做:str[0] = 'p',在函数之外,a的值将是{{1 }}。所以,我不明白为什么指针仍然指向一开始,即使在我使其向前移动的函数内部。

5 个答案:

答案 0 :(得分:4)

因为C按值传递参数

  int countSpace(char *str)
                      ^^ 
            This pointer is a copy of the pointer you pass in.

最初,您的str变量指向与您指针相同的内容 传递给你的函数,但在countSpace()里面你只是增加了该指针的本地副本。

答案 1 :(得分:1)

C是按值传递,所以当你将指针传递给countSpaces时,它会复制指针的值(请注意,只是指针不是它是什么的指着)。就像任何其他本地值一样:在函数内部对其进行的任何更改都不会反映在外部。

在函数外部可以看到对函数内部指针所指向的内容的任何更改。

例如:我们取a的地址,将其存储在指针p中并将其打印为指针(以查看它所拥有的内存地址):

char * p = a;
printf(" p = %p\n", p); // This will not print the string, but the address where it starts

并将其传递给countSpaces(这相当于将a传递给countSpaces):

countSpaces(p);

现在在里面,打印str作为指针

printf(" str: %p\n", str);

你会看到两个值都是相同的,这是有意义的,因为它被复制到countSpaces。但是,如果您打印pcountSpaces之外)的地址str(内部)的地址。你会发现它们是不同的:

printf("&str: %p\n", &str);

printf("&p: %p\n", &p);

因此,countSpaces可以更改strp(和a指向的内容,但不能更改指针本身:它们是复制到新变量。

答案 2 :(得分:1)

函数不会更改变量a。

了解内存中变量和值的位置有助于理解指针发生的情况。以及稍后帮助调试。

执行a和str的%p printf,你会看到他们指向的内存地址。

printf("a var %p", &a);
printf("a content %p", a);
printf("str var %p", &str);
printf("str content %p", str);

假设婴儿2字节int和ptrs。

,内存中存在事物的示例
# c compiler/linker will put string values in global memory

#Addr #Value
#0020 Hello \0
#0027 %d\0
#0030 . .

堆栈内存。 var a在堆栈mem中(假设在main函数的堆栈中)(实际上编译器可以将vars放入寄存器但产生相同的结果)

#stack-main a is a char ptr. 
#&a=0100, value of a=0020
#Addr #Value
#0100 0020

#when countSpaces is just called
#code return addr pushed to stack
#Addr #Value
#0102 0222
#space on stack for return of int
#0104 0000
#value of a put on stack (this is str)
#0106 0020
#local vars of countSpaces 
# int nSpaces
#0107 0000

在countSpaces返回堆栈后看起来像:

#&a=0100, value of a=0020
#Addr #Value
#0100 0020

#Addr #Value
#code return addr
#0102 0222
#space on stack for return of int
#0104 0001
#value of a put on stack (this is str)
#0106 0026
#local vars of countSpaces 
# int nSpaces
#0107 0001

答案 3 :(得分:0)

str是传递给函数参数列表的指针的副本。它与int参数没有区别。

因此,a保持不变。

答案 4 :(得分:0)

str是指向字符串的指针,并通过值传递给函数。

当您在函数内部更改str时,从函数外部传递的原始变量不会更改。

当然,str是一个指针,它允许您更改它指向的char

如果要从函数内部更改 outside str,则必须将指针传递给str,换句话说,指向指向字符串的指针(第一个字符)。

代码变为:

int countSpace(char **str) {
        int nSpaces = 0;
        while (**(str) != '\0') {
                if (**(str) == ' ') {
                        nSpaces++;
                }
                *str++;
        }
        return nSpaces;
}

像这样使用这个函数:

char a[]="Hello ";
printf("%d", countSpace(&a));