开发者

Fundamental C pointer question using 'strcpy'

Man, pointers continue to give me trouble. I thought I understood the concept.(Basically, that you would use *ptr when you want to manipulate the actual memory saved at the location that ptr points to. You would just use ptr if you would like to move that pointer by doing things such as ptr++ or ptr--.) So, if that is the case, if you use the asterisk to manipulate the files that the pointer is pointing to, how does this work:

char *MallocAndCopy( char *line ) {

    char *pointer;
    if ( (pointer = malloc( strlen(line)+1 )) == NULL ) {
        printf( "Out of memory!!!  Goodbye!\n" );
        exit( 0 );
    }
    strcpy( pointer, line );

    return pointer;
}

malloc returns a pointer, so I understand why the "pointer" in the if conditi开发者_如何转开发on does not utilize the asterisk. However, in the strcpy function, it is sending the CONTENTS of line to the CONTENTS of pointer. Shouldn't it be:

strcpy( *pointer, *line);

????? Or is my understanding of pointers correct and that is just the way that the strcpy function works?


A C-style string is an array of character bytes. When you pass an array around as a pointer to the array type, the pointer contains the address of the first element of the array.

The strcpy function takes the pointer to the first char of the source array (which is the start of the string) and the pointer to the first char in the destination array, and iterates over the source until it reaches a '\0' character, which terminates the string.

That's also why when you call malloc, the size that you pass to it is strlen(line)+1, because you need to allocate one more byte for the termination character (as far as I know).


char* strcpy(char *destination, const char *source) is the signature for strcpy. It expects to get pointers as arguments. In your instance, pointer is already a pointer, and so is line.

strcpy will take the pointers source and destination, and copy the underlying bytes pointed at from source to destination until it either hits the \0 (NULL) byte in the string pointed to by source, or if it segmentation faults because it never encounters that byte (unterminated string) and just reads off into the abyss.

If you used *pointer, you would actually be dereferencing the pointer and getting the char at the address the pointer points to.


The signature of strcpy is

char * strcpy ( char * destination, const char * source );

You are sending in pointer which is char*, and line which is also char*. Thus you are matching the signature exactly as expected. Sending in *pointer or *line would be sending 'the values these pointers point to' - which would be wrong.


scrcpy takes one pointer, and writes the contents it is pointing to to the location pointed by the another pointer. It is like rewriting cell contents in the table. You don't necessarily have to cut and paste a part of the table, you can rewrite the numbers in it. In that case pointer is just a hint which cells you have to touch.


Look at the declaration of strpcy().

char *strcpy(
   char *strDestination,
   const char *strSource 
);

You need to pass a pointer. So you don't dereference pointer and line. Because that would pass a char.


The * is inside strcpy.

Applying the * operator is called dereferencing, and is exactly the same as applying the [0].

strlen and strcpy need to know where the strings start so that they can access all of their elements, not just the first.

The type of pointer is char * while the type of *pointer is char, meaning a single character with no concept of neighboring characters.


By writing *pointer, you obtain the character that it points to (which happens to be the first character of the string that pointer represents). Passing it to strcpy involves creating a copy of that character. It's impossible for strcpy to know where it should be writing, unless you give it a pointer to that data.

In a similar fashion, by providing *line you're only giving strcpy a copy of the first character of your string.

So, you're basically saying:

I have two strings. I'm not giving them to you. The first letter of one is C, the first letter of the other is µ. Copy the contents of the first to the second


I see why you expect to pass *pointer and *line to strcpy. But remember that pointer points to the location in memory where the content is stored and where there is strlen(line)+1 bytes of memory is reserved and allocated. Thus what strcpy is exactly doing is to copy strlen(line) bytes of memory starting from the address line into corresponding locations, starting from the address of pointer. If you pass *pointer and *line, strcpy will have access to only the first char and not the rest of strlen(line)-1. Hope that clarifies your confusion about the pointers and why we need to pass pointers to strcpy.


Your basic understanding of strcpy is correct. The function indeed copies the contents of line over the contents of pointer. However, you have to pass pointers to the function and not the data itself. This is done for several reasons.

First, the data that is being copied is a string (that is, an array) and not a regular variable. When passing an array to a function, you can't cram the entire array into a single function argument so instead you have to pass a pointer to the beginning of the array. This is a limitation of array passing in C and is not specific to strcpy.

Also, passing data to a function provides the function with a copy of the variable's content. If you directly passed data (or de-referenced pointers) to strcpy, the function would be working with copies and not the original data. It would be unable to write data to the original string.

Essentially, by handing pointers to strcpy you are telling it the location of the source data and of the destination. The function handles all of the de-referencing internally. In human language, the call to strcpy can be thought of as "take the string that starts at memory address line and write a copy it starting at memory address pointer". To communicate memory addresses, you use pointers.


Consider the strcpy code as:

char * strcpy(char * dst, char* src) 
{
    int i = 0 ;
    for (;dst[i]=source[i++];);
    return dst ;
}

\0(NULL) is the end of both the string and the for loop.


Your function is basically what strdup does. The function is defined on many platform, if it isn't you can define this way:

char * my_strdup(const char* s)
{
  size_t len = strlen(s);
  char *r = malloc(len+1);
  return r ? memcpy(r, s, len+1) : NULL;
}

memcpy is usually faster than strcpy for longer strings.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜