简体   繁体   中英

character pointer takes the address of what

I read that:

char a[] = "string"; 

is a: "string"

whereas

char *ptr = "string" 

is ptr: [__] ---> "string"

I am little confused. One thing I know is that pointers always store the address. In case of character pointer what address does it store? What does this block represent (block which I made pointing to string). Is it the starting address of the "string".

And in case of array? How can I clearly differentiate between char pointer and char array?

Diagrams may help.

char *ptr = "string";

+-------+          +----------------------------+
|  ptr  |--------->| s | t | r | i | n | g | \0 |
+-------+          +----------------------------+

char a[] = "string";

+----------------------------+
| s | t | r | i | n | g | \0 |
+----------------------------+

Here, ptr is a variable that holds a pointer to some (constant) data. You can subsequently change the memory address that it points at by assigning a new value to ptr , such as ptr = "alternative"; — but you cannot legitimately change the contents of the array holding "string" (it is officially readonly or const , and trying to modify it may well crash your program, or otherwise break things unexpectedly).

By contrast, a is the constant address of the first byte of the 7 bytes of data that is initialized with the value "string" . I've not shown any storage for the address because, unlike a pointer variable, there isn't a piece of changeable storage that holds the address. You cannot change the memory address that a points to; it always points to the same space. But you can change the contents of the array (for example, strcpy(a, "select"); ).

When you call a function, the difference disappears:

if (strcmp(ptr, a) == 0)
    …string is equal to string…

The strcmp() function takes two pointers to constant char data (so it doesn't modify what it is given to scrutinize), and both ptr and a are passed as pointer values. There's a strong case for saying that only pointers are passed to functions — never arrays — even if the function is written using array notation.

Nevertheless, and this is crucial, arrays (outside of paramter lists) are not pointers. Amongst other reasons for asserting that:

  • sizeof(a) == 7
  • sizeof(ptr) == 8 (for 64-bit) or sizeof(ptr) == 4 (32-bit).

In case of character pointer what address does it store? What does this block represent (block which I made pointing to string). Is it the starting address of the "string".

This blocks represents a WORD or DWORD (achitecture dependant), the content of this block is a memory address, a random location defined at compile time. That memory address is the address of first character of the string.

In practice, the difference is how much stack memory it uses.

For example when programming for microcontrollers where very little memory for the stack is allocated, makes a big difference.

char a[] = "string"; // the compiler puts {'s','t','r','i','n','g', 0} onto STACK 

char *b = "string"; // the compiler puts just the pointer onto STACK 
                    // and {'s','t','r','i','n','g',0} in static memory area.

Maybe this will help you understand.

assert(a[0] == 's'); // no error.
assert(b[0] == 's'); // no error.
assert(*b == 's');   // no error.
b++; // increment the memory address, so points to 't'
assert(*b == 's');   // assertion failed
assert(*b == 't');   // no error.

char a[] = "string"; initializes the value of the array of char s called a with the value string . And the size of a .

char *a = "string"; creates an unnamed static array of char s somewhere in memory and return the address of the first element of this unnamed array to a .

In the first one, a stores the address of the first element of the array. So when we index something like a[4], this means 'take' the 4th element after the begin of the object named a.

In the second, a[4] means 'take' the 4th element after the object that a points to.

And for your last question:

A char array is a 'block' of contiguous elements of type char. A char pointer is a reference to an element of the type char.

Due to pointer arithmetics, a pointer can be used to simulate (and access) an array.

Maybe those 3 links help make the difference more clear:

http://c-faq.com/decl/strlitinit.html

http://c-faq.com/aryptr/aryptr2.html

http://c-faq.com/aryptr/aryptrequiv.html

You may find it useful to think of:

char * a = "string";

as the same as:

char SomeHiddenNameYouWillNeverKnowOrSee[] = "string";   /*  may be in ReadOnly memory! */
char * a = &SomeHiddenNameYouWillNeverKnowOrSee[0];

Did you ever tried to open some executabe file with a text editor ? It appears merely as garbage, but in the middle of the garbage you can see some readable strings. These are all the litteral strings defined in you program.

printf("my literal text");
char * c = "another literal text"; // should be const char *, see below

If your program contains the above code you may be able to find my literal text and another literal text in program's binary (actually it depends on the details of the binary format, but it often works). If you are Linux/Unix user you can also use the strings command for that.

By the way, if you write the above code, C++ compilers will emit some warning (g++ say: warning: deprecated conversion from string constant to 'char*' because such strings are not of type char * but const char [] (const char array) which decay to const char * when assigned to a pointer.

This also is the case with C compilers, but the above error is so very common that this warning is usually disabled. gcc does not even include in -Wall, you have to explicitely enable it through -Wwrite-strings . The warning is warning: initialization discards 'const' qualifier from pointer target type .

It merely reminds that you are theoretically not allowed to change the literal texts through pointers.

The executable may loads such strings in a read only part of Data segment memory. If you try to change the content of string it can raise a memory error. Also the compiler is allowed to optimise literal text storage by merging identical strings for instance. The pointer just contains the address in (read only) memory where the literal strings will be loaded.

On the other hand

char c[] = "string"; is mere syntaxic sugar for char c[7] = {'s', 't', 'r', 'i', 'n', 'g', 0}; If you do sizeof(c) in your code it will be 7 bytes (the size of the array, not the size of a pointer). This is an array on stack with an initialiser. Internally the compiler can do wathever it likes to initialize the array. It can be characters constants loaded one by one in the array, or it can involved a memcpy of some hiden string literal. The thing is that you have no way to tell the difference from your program and find out where the data comes from. Only the result matters.

By the way a thing that is slightly confusing is that if you define some function parameter of the type char c[] , then it won't be an array but an alternative syntax for char * c .

In your example, ptr contains the address of the first char in the string.

As for the difference between a char array and a string, in C terms there is no difference other than the fact that by convention what we call "string" is a char array where the final char is a NULL, to terminate the string.

ie even if we have an array of char with 256 potential elements, if the first (0th) char is null (0) then the length of the string is 0.

Consider a variable str which is a char array of 5 chars , containing the string 'foo' .

*ptr  =>   str[0]   'f'
           str[1]   'o'
           str[2]   'o'
           str[3]   \0
           str[4]   ..

A char *ptr to this array would reference the first element (index = 0) and the 4th element (index = 3) would be null, marking the end of the 'string'. The 5th element (index = 4) will be ignored by string handling routines which respect the null terminator.

If you are asking what a contains in each case then:

char a[] = "string";
// a is a pointer. 
// It contains the address of the first element of the array.

char *a = "string";
// Once again a is a pointer containing address of first element.

As rnrneverdies has explained in his answer, the difference is in where the elements are stored.

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