简体   繁体   中英

About pointers and strcpy() in C

I am practicing allocation memory using malloc() with pointers, but 1 observation about pointers is that, why can strcpy() accept str variable without * :

char *str;
str = (char *) malloc(15);
strcpy(str, "Hello");
printf("String = %s,  Address = %u\n", str, str);

But with integers, we need * to give str a value.

int *str;
str = (int *) malloc(15);
*str = 10;
printf("Int = %d,  Address = %u\n", *str, str);

it really confuses me why strcpy() accepts str , because in my own understanding, "Hello" will be passed to the memory location of str that will cause some errors.

In C, a string is (by definition) an array of characters. However (whether we realize it all the time or not) we almost always end up accessing arrays using pointers. So, although C does not have a true "string" type, for most practical purposes, the type pointer-to-char (ie char * ) serves this purpose. Almost any function that accepts or returns a string will actually use a char * . That's why strlen() and strcpy() accept char * . That's why printf %s expects a char * . In all of these cases, what these functions need is a pointer to the first character of the string. (They then read the rest of the string sequentially, stopping when they find the terminating '\\0' character.)

In these cases, you don't use an explicit * character. * would extract just the character pointed to (that is, the first character of the string), but you don't want to extract the first character, you want to hand the whole string (that is, a pointer to the whole string) to strcpy so it can do its job.

In your second example, you weren't working with a string at all. (The fact that you used a variable named str confused me for a moment.) You have a pointer to some ints, and you're working with the first int pointed to. Since you're directly accessing one of the things pointed to, that's why you do need the explicit * character.

The * is called indirection or dereference operator.

In your second code,

 *str = 10;

assigns the value 10 to the memory address pointed by str . This is one value (ie, a single variable).

OTOTH, strcpy() copies the whole string all at a time. It accepts two char * parameters, so you don't need the * to dereference to get the value while passing arguments.

You can use the dereference operator, without strcpy() , copying element by element, like

char *str;
str = (char *) malloc(15);   //success check TODO
int len = strlen("Hello");    //need string.h header

for (i = 0; i < len; i ++)
    *(str+i)= "Hello"[i];  // the * form. as you wanted

str[i] = 0;   //null termination

Many string manipulation functions, including strcpy , by convention and design, accept the pointer to the first character of the array, not the pointer to the whole array, even though their values are the same.

This is because their types are different; eg a pointer to char[10] has a different type from that of a pointer to char[15] , and passing around the pointer to the whole array would be impossible or very clumsy because of this, unless you cast them everywhere or make different functions for different lengths.

For this reason, they have established a convention of passing around a string with the pointer to its first character, not to the whole array, possibly with its length when necessary. Many functions that operate on an array, such as memset , work the same way.

Well, here's what happens in the first snippet :

You are first dynamically allocating 15 bytes of memory, storing this address to the char pointer, which is pointer to a 1-byte sequence of data (a string). Then you call strcpy() , which iterates over the string and copy characters, byte per byte, into the newly allocated memory space. Each character is a number based on the ASCII table, eg. character a = 97 (take a look at man ascii ).

Then you pass this address to printf() which reads from the string, byte per byte, then flush it to your terminal.

In the second snippet, the process is the same, you are still allocating 15 bytes, storing the address in an int * pointer. An int is a 4 byte data type. When you do *str = 10 , you are dereferencing the pointer to store the value 10 at the address pointed by str. Remind what I wrote ahead, you could have done *str = 'a', and this index 0 integer would had the value 97, even if you try to read it as an int. you can event print it if you would.

So why strcpy() can take a int * as parameter? Because it's a memory space where it can write, byte per byte. You can store "Hell" in an int, then "o!" in the next one.

It's just all about usage easiness.

See there is a difference between = operator and the function strcpy .

* is deference operator. When you say *str , it means value at the memory location pointed by str.

Also as a good practice, use this

str = (char *) malloc( sizeof(char)*15 )

It is because the size of a data type might be different on different platforms. Hence use sizeof function to determine its actual size at the run time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM