5

Possible Duplicate:
What is the difference between char s[] and char *s in C?
Difference between char *str = “…” and char str[N] = “…”?

I have some code that has had me puzzled.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  char* string1 = "this is a test";
  char string2[] = "this is a test";
  printf("%i, %i\n", sizeof(string1), sizeof(string2));
  system("PAUSE"); 
  return 0;
}

When it outputs the size of string1, it prints 4, which is to be expected because the size of a pointer is 4 bytes. But when it prints string2, it outputs 15. I thought that an array was a pointer, so the size of string2 should be the same as string1 right? So why is it that it prints out two different sizes for the same type of data (pointer)?

Community
  • 1
  • 1
John Jacquay
  • 233
  • 1
  • 6
  • 19

7 Answers7

13

Arrays are not pointers. Array names decay to pointers to the first element of the array in certain situations: when you pass it to a function, when you assign it to a pointer, etc. But otherwise arrays are arrays - they exist on the stack, have compile-time sizes that can be determined with sizeof, and all that other good stuff.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
5

Arrays and pointers are completely different animals. In most contexts, an expression designating an array is treated as a pointer.

First, a little standard language (n1256):

6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

The string literal "this is a test" is a 15-element array of char. In the declaration


    char *string1 = "this is a test";

string1 is being declared as a pointer to char. Per the language above, the type of the expression "this is a test" is converted from char [15] to char *, and the resulting pointer value is assigned to string1.


In the declaration


    char string2[] = "this is a test";


something different happens. More standard language:

6.7.8 Initialization
...
14 An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.
...
22 If an array of unknown size is initialized, its size is determined by the largest indexed element with an explicit initializer. At the end of its initializer list, the array no longer has incomplete type.

In this case, string2 is being declared as an array of char, its size is computed from the length of the initializer, and the contents of the string literal are copied to the array.

Here's a hypothetical memory map to illustrate what's happening:

Item          Address       0x00  0x01  0x02  0x03
----          -------       ----  ----  ----  ----
no name       0x08001230    't'   'h'   'i'   's'
              0x08001234    ' '   'i'   's'   ' '
              0x08001238    'a'   ' '   't'   'e'
              0x0800123C    's'   't'    0
              ...
string1       0x12340000    0x08  0x00  0x12  0x30
string2       0x12340004    't'   'h'   'i'   's'
              0x12340008    ' '   'i'   's'   ' '
              0x1234000C    'a'   ' '   't'   'e'
              0x1234000F    's'   't'    0

String literals have static extent; that is, the memory for them is set aside at program startup and held until the program terminates. Attempting to modify the contents of a string literal invokes undefined behavior; the underlying platform may or may not allow it, and the standard places no restrictions on the compiler. It's best to act as though literals are always unwritable.

In my memory map above, the address of the string literal is set off somewhat from the addresses of string1 and string2 to illustrate this.

Anyway, you can see that string1, having a pointer type, contains the address of the string literal. string2, being an array type, contains a copy of the contents of the string literal.

Since the size of string2 is known at compile time, sizeof returns the size (number of bytes) in the array.

The %i conversion specifier is not the right one to use for expressions of type size_t. If you're working in C99, use %zu. In C89, you would use %lu and cast the expression to unsigned long:


C89: printf("%lu, %lu\n", (unsigned long) sizeof string1, (unsigned long) sizeof string2);
C99: printf("%zu, %zu\n", sizeof string1, sizeof string2);

Note that sizeof is an operator, not a function call; when the operand is an expression that denotes an object, parentheses aren't necessary (although they don't hurt).

John Bode
  • 119,563
  • 19
  • 122
  • 198
4

string1 is a pointer, but string2 is an array.

The second line is something like int a[] = { 1, 2, 3}; which defines a to be a length-3 array (via the initializer).

The size of string2 is 15 because the initializer is nul-terminated (so 15 is the length of the string + 1).

lijie
  • 4,811
  • 22
  • 26
4

An array of unknown size is equivalent to a pointer for sizeof purposes. An array of static size counts as its own type for sizeof purposes, and sizeof reports the size of the storage required for the array. Even though string2 is allocated without an explicit size, the C compiler treats it magically because of the direct initialization by a quoted string and converts it to an array with static size. (Since the memory isn't allocated in any other way, there's nothing else it can do, after all.) Static size arrays are different types from pointers (or dynamic arrays!) for the purpose of sizeof behavior, because that's just how C is.

This seems to be a decent reference on the behaviors of sizeof.

Adam Norberg
  • 3,028
  • 17
  • 22
2

The compiler know that test2 is an array, so it prints out the number of bytes allocated to it(14 letters plus null terminator). Remember that sizeof is a compiler function, so it can know the size of a stack variable.

zdav
  • 2,752
  • 17
  • 15
1

Its because

  1. string1 holds pointer, where pointer has contiguous chars & its immutable.
  2. string2 is location where your chars sit.

basically C compiler iterprets these 2 differently. beautifully explained here http://c-faq.com/aryptr/aryptr2.html.

spats
  • 805
  • 1
  • 10
  • 12
1

array is not pointer. Pointer is a variable pointing to a memory location whereas array is starting point of sequential memory allocated

ashmish2
  • 2,885
  • 8
  • 40
  • 54