增加C中字符串指针的值

时间:2018-06-10 21:53:16

标签: c memory

我正在完成一项任务。我有正确的工作代码,但是,我无法理解一行的作用。

函数的描述是:

此函数将malloc 5个字节的内存,使用strcpy在这5个字节(4个字母加'\ 0')中存储“bird”,并将字符串指针指向的值增加字符串的长度(计算使用strlen)它指向(所以它最终指向句子末尾的'\ 0')。然后它将返回malloced内存。

以下是执行上述操作的代码

char *get_word( char **string_ptr ){

    char *word; 

    word = malloc( 5 ); 

    strcpy( word, "bird" ); 

    *string_ptr += strlen( *string_ptr );

    return word;

}

我不明白行是什么“* string_ptr + = strlen(* string_ptr);”即使有上面​​的描述也是如此。有人能给我一个更详细的解释吗?

1 个答案:

答案 0 :(得分:1)

传递给get_word的参数是char **(可能是由于调用者传递了地址而不是指针集合)。

由于C中的所有参数都是按值传递的,因此为了更改作为参数传递的指针的地址,必须传递地址指针。否则,该函数将简单地接收指针的副本(具有其自己且非常不同的地址),并且对函数内的指针所做的任何更改都将在调用函数中不可见。

虽然您没有提供A Minimal, Complete, and Verifiable Example (MCVE),但我们可以从您的函数中推断出字符串的地址正在传递给get_word,例如:

#define MAXC 1024
...
char buffer[MAXC] = "word_one";
char *p = buffer;
char *new_word = NULL;
...
new_word = get_word (&p);

之后有一些事情需要在该指针的末尾附加文本(这是*string_ptr += strlen( *string_ptr );get_word的目的),例如:

strcpy (p, new_word);

结果是,缓冲区现在包含:

"word_onebird"

因此,实际上,通过将地址指向get_word,指针将string_ptr推进到*string_ptr += strlen( *string_ptr );中当前单词的末尾} string_ptr所指向的位置的变化将反映在调用函数中。

如果您只通过get_word(string_ptr),则get_word中所做的更改将不会在调用函数中显示,并且指针将保持不变。但是,通过使用string_ptr传递 get_word(&string_ptr)地址,get_word(通过*string_ptr = ...对原始指针本身进行操作的更改已反映出来在原始指针中回调用函数。

按示例理解指针

指针只是一个普通变量,它将地址保存为其他值。换句话说,指针指向可以找到其他内容的地址。在您通常认为保持立即值的变量(例如int a = 5;)的情况下,指针只会保存5存储在内存中的地址,例如int *b = &a;get_word。它以同样的方式工作,无论指针指向什么类型的对象。 (一个指针,只是一个指针....)

如果需要更改函数内指针所指向的地址而不返回新指针,则必须将原始指针的地址作为参数传递,以便该函数可以在原始指针本身,而不是指针的副本,如果参数占用了指针本身,它将出现在函数中。

一个例子可能有所帮助。花点时间处理代码并理解get_word_single中原始指针的可用方式,但下面的#include <stdio.h> #include <string.h> #define MAXC 256 /* parameter passes only the pointer p in main() */ void get_word_single (char *string_ptr) { printf ("in get_word_single()\n" " address of string_ptr: %p <-- a new pointer\n" " value in string_ptr: %p <-- changes only seen locally\n\n", (void*)&string_ptr, (void*)string_ptr); string_ptr += strlen (string_ptr); } /* parameter passes address of p in main() */ void get_word (char **string_ptr) { printf ("in get_word()\n" "address of string_ptr: %p <-- a new pointer\n" " value in string_ptr: %p <-- holding original address\n\n" "address of *string_ptr: %p <-- dereference to expose address\n" " value in *string_ptr: %p <-- modify to change original\n\n", (void*)&string_ptr, (void*)string_ptr, (void*)&(*string_ptr), (void*)*string_ptr); *string_ptr += strlen (*string_ptr); } int main (void) { char buf[MAXC] = "one", /* a 3-character word in buf */ *p = buf; printf ("in main()\n" "address of p: %p <-- address of the pointer itself\n" " value in p: %p <-- address held by the pointer\n\n", (void*)&p, (void*)p); get_word_single (p); printf ("in main()\n" "address of p: %p <-- address of pointer itself unchanged\n" " value in p: %p <-- no change in address held\n\n", (void*)&p, (void*)p); get_word (&p); printf ("in main()\n" "address of p: %p <-- address of pointer itself unchanged\n" " value in p: %p <-- address held incremented by 3\n\n", (void*)&p, (void*)p); return 0; } 中只提供了原始指针的副本:

$ ./bin/passaddrex
in main()
address of p: 0x7ffc8594f370  <-- address of the pointer itself
  value in p: 0x7ffc8594f380  <-- address held by the pointer

in get_word_single()
 address of string_ptr: 0x7ffc8594f378  <-- a new pointer
   value in string_ptr: 0x7ffc8594f380  <-- changes only seen locally

in main()
address of p: 0x7ffc8594f370  <-- address of pointer itself unchanged
  value in p: 0x7ffc8594f380  <-- no change in address held

in get_word()
address of  string_ptr: 0x7ffc8594f348  <-- a new pointer
  value in  string_ptr: 0x7ffc8594f370  <-- holding original address

address of *string_ptr: 0x7ffc8594f370  <-- dereference to expose address
  value in *string_ptr: 0x7ffc8594f380  <-- modify to change original

in main()
address of p: 0x7ffc8594f370  <-- address of pointer itself unchanged
  value in p: 0x7ffc8594f383  <-- address held incremented by 3

示例使用/输出

namespace Flow.Models
{    
    public abstract class Project
    {
        public int ID { get; set; }

        public String HashID { get; set; }

        public string FileLoc { get; set; } //Use HashedID above.
        public bool Network { get; set; }

        public int ClientID { get; set; }
        public int FirmID { get; set; }

        public ICollection<Order> Orders { get; set; }
    }
}