9

Just have a question in mind that troubles me.

I know pointers and arrays are different in C because pointers store an address while arrays store 'real' values.

But I'm getting confused when it comes to string.

char *string = "String";

I read that this line does several things :

An array of chars is created by the compiler and it has the value String.

Then, this array is considered as a pointer and the program assigns to the pointer string a pointer which points to the first element of the array created by the compiler.

This means, arrays are considered as pointers.

So, is this conclusion true or false and why ?

If false, what are then the differences between pointers and arrays ? Thanks.

mctylr
  • 5,159
  • 20
  • 32
user5491
  • 101
  • 1
  • 1
  • 2

6 Answers6

10

A pointer contains the address of an object (or is a null pointer that doesn't point to any object). A pointer has a specific type that indicates the type of object it can point to.

An array is a contiguous ordered sequence of elements; each element is an object, and all the elements of an array are of the same type.

A string is defined as "a contiguous sequence of characters terminated by and including the first null character". C has no string type. A string is a data layout, not a data type.

The relationship between arrays and pointers can be confusing. The best explanation I know of is given by section 6 of the comp.lang.c FAQ. The most important thing to remember is that arrays are not pointers.

Arrays are in a sense "second-class citizens" in C and C++. They cannot be assigned, passed as function arguments, or compared for equality. Code that manipulates arrays usually does so using pointers to the individual elements of the arrays, with some explicit mechanism to specify how long the array is.

A major source of confusion is the fact that an expression of array type (such as the name of an array object) is implicitly converted to a pointer value in most contexts. The converted pointer points to the initial (zeroth) element of the array. This conversion does not happen if the array is either:

  • The operand of sizeof (sizeof array_object yields the size of the array, not the size of a pointer);

  • The operand of unary & (&array_object yields the address of the array object as a whole); or

  • A string literal in an initializer used to initialize an array object.

    char *string = "String";

To avoid confusion, I'm going to make a few changes in your example:

const char *ptr = "hello";

The string literal "hello" creates an anonymous object of type char[6] (in C) or const char[6] (in C++), containing the characters { 'h', 'e', 'l', 'l', 'o', '\0' }.

Evaluation of that expression, in this context, yields a pointer to the initial character of that array. This is a pointer value; there is no implicitly created pointer object. That pointer value is used to initialize the pointer object ptr.

At no time is an array "treated as" a pointer. An array expression is converted to a pointer type.

Another source of confusion is that function parameters that appear to be of array type are actually of pointer type; the type is adjusted at compile time. For example, this:

void func(char param[10]);

really means:

void func(char *param);

The 10 is silently ignored. So you can write something like this:

void print_string(char s[]) {
    printf("The string is \"%s\"\n", s);
}
// ...
print_string("hello");

This looks like just manipulating arrays, but in fact the array "hello" is converted to a pointer, and that pointer is what's passed to the print_string function.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
5

So, is this conclusion true or false and why ?

Your conclusion is false.

Arrays and pointers are different. comp.lang.c FAQ list · Question 6.8 explains the difference between arrays and pointers:

An array is a single, preallocated chunk of contiguous elements (all of the same type), fixed in size and location. A pointer is a reference to any data element (of a particular type) anywhere. A pointer must be assigned to point to space allocated elsewhere, but it can be reassigned (and the space, if derived from malloc, can be resized) at any time. A pointer can point to an array, and can simulate (along with malloc) a dynamically allocated array, but a pointer is a much more general data structure.

When you do

char *string = "String";  

and when a C compiler encounters this, it sets aside 7 bytes of memory for the string literal String. Then set the pointer string to point to the starting location of the allocated memory.

enter image description here

When you declare

char string[] = "String";    

and when a C compiler encounters this, it sets aside 7 bytes of memory for the string literal String. Then gives the name of that memory location, i.e. the first byte, string.

enter image description here

So,

  • In first case string is a pointer variable and in second case it is an array name.
  • The characters stored in first case can't be modified while in array version it can be modified.

This means arrays is not considered as pointers in C but they are closely related in the sense that pointer arithmetic and array indexing are equivalent in C, pointers and arrays are different.

haccks
  • 104,019
  • 25
  • 176
  • 264
0

We can create an array with the name 'string'

char string[] = "Hello";

We can allocate a pointer to that string

char* stringPtr = string;

The array name is converted to a pointer

So, an array name is similar to the pointer. However, they're not the same, as the array is a contiguous block of memory, whereas the pointer references just a single location (address) in memory.

char *string = "String";

This declaration creates the array and sets the address of the pointer to the block of memory used to store the array.

This means, arrays are considered as pointers. So, is this conclusion true or false

False, arrays are not pointers. However, just to confuse(!), pointers can appear to be arrays, due to the dereference operator []

char *string = "String";
char letter = string[2];

In this case string[2], string is first converted to a pointer to the first character of the array and using pointer arithmetic, the relevant item is returned.

Community
  • 1
  • 1
TheDarkKnight
  • 27,181
  • 6
  • 55
  • 85
0

You have to understand what is happening in memory here.

A string is a contiguous block of memory cells that terminates with a special value (a null terminator). If you know the start of this block of memory, and you know where it ends (either by being told the number of memory cells or by reading them until you get to the null) then you're good to go.

A pointer is nothing more than the start of the memory block, its the address of the first memory cell, or its a pointer to the first element. All those terms mean the same thing. Its like a cell reference in a spreadsheet, if you have a huge grid you can tell a particular cell by its X-Y co-ordinates, so cell B5 tells you of a particular cell. In computer terms (rather than spreadsheets) memory is really a very, very long list of cells, a 1-dimensional spreadsheet if you like, and the cell reference will look like 0x12345678 rather than B5.

The last bit is understanding that a computer program is a block of data that is loader by the OS into memory, the compiler will have figured out the location of the string relative to the start of the program, so you automatically know which block of memory it is located in.

This is exactly the same as allocating a block of memory on the heap (its just another part of the huge memory space) or the stack (again, a chunk of memory reserved for local allocations). You have the address of the first memory location where your string lives.

So

char* mystring = "string";

char mystring[7];
copy_some_memory(mystring, "string", 7);

and

char* mystring = new char(7);
copy_some_memory(mystring, "string", 7);

are all the same thing. mystring is the memory location of the first byte, that contains the value 's'. The language may make them look different, but that's just syntax. So an array is a pointer, its just that the language makes it look different, and you can operate on it with slightly different syntax designed to make operations on it safer.

(note: the big difference between the 1st and other examples is that the compiler-set set of data is read-only. If you could change that string data, you could change your program code, as it too it just a block of CPU instructions stored in a section of memory reserved for program data. For security reasons, these special blocks of memory are restricted to you).

gbjbaanb
  • 51,617
  • 12
  • 104
  • 148
0

Here's another way to look at them:

First, memory is some place you can store data.

Second, an address is the location of some memory. The memory referred to by the address may or may not exist. You can't put anything in an address, only at an address - you can only store data in the memory the address refers to.

An array is contiguous location in memory - it's a series of memory locations of a specific type. It exists, and can have real data put into it. Like any actual location in memory, it has an address.

A pointer contains an address. That address can come from anywhere.

A string is a NUL-terminated array of characters.

Look at it this way:

memory - A house. You can put things in it. The house has an address.

array - A row of houses, one next to the other, all the same.

pointer - a piece of paper you can write an address on. You can't store anything in the piece of paper itself (other than an address), but you can put things into the house at the address you write on the paper.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
0

Then, this array is considered as a pointer and the program assigns to the pointer string a pointer which points to the first element of the array created by the compiler.

Not really great wording here. Array is still an array and is considered as such. The program assigns a pointer-to-first-element value (rvalue) to pointer-to-char variable (lvalue in general). That is the only intermediate/non-stored pointer value here, as compiler and linker know array's address at compile-link time. You can't directly access the array though, because it is anonymous literal. If you were instead initializing an array with literal, then literal would disappear (think like optimized-out as separate entity) and array would be directly accessible by its precomputed address.

char s[] = "String"; // char[7]
char *p = s;
char *p = &s[0];
user3125367
  • 2,920
  • 1
  • 17
  • 17