How Does a Pointer Behave Like an Array in C Programming?

In summary: Yeh, that's about it. strings are just like any other variable in terms of how you access and use them. You can access them like any other variable by writing their name (or an abbreviation like "s"), followed by the address of the character or string you want to access. For example, you could writes"Hello, world!"to print "Hello, world!" at the current location in the text box.
  • #1
Epic Sandwich
25
0
So I'm learning C, and I think I'm doing pretty well so far. Anyway, I'm up to Arrays, and some code that was posted in the tutorial is this:

Code:
#include <stdlib.h>

int main()
{
    int*    myArray = malloc( sizeof(int) * 20 );    // could write int myArray[20]; instead.

    myArray[5] = 42;

    // ... do something else here.

    free( myArray ); // Give up ownership once we're done.

    return 0;
}

The thing that's confusing me is this. So first, you define a pointer variable, (myArray), and you make it point to some memory with malloc. So now, the pointer contains the address to some data that can hold 20 ints. All correct so far?

Anyway, when myArray[5] comes along, they simply treat the pointer like an array. What I don't i understand is this. How can a variable holding a pointer to some data be an array? I thought you would have to declare an array, and then tell it to go into the data that you just allocated with malloc.

Or, is it not really an array? By saying myArray[5], are you simply referring to the sixth block of memory in the myArray section which was just allocated?

I hope I didn't word this question in a confusing way, I'm just trying to go through C making sure I understand everything instead of rushing through.

Thanks.
 
Technology news on Phys.org
  • #2
By saying myArray[5], are you simply referring to the sixth block of memory in the myArray section which was just allocated?

Correct. myArray is a pointer to a block of memory, and myArray[5] is the element in that block with an offset 5*sizeof(int) from the beginning.

If you were to write

Code:
int myArray[20];

that code would really have dual roles. It would allocate a 20-unit array on the stack and assign "myArray" to be the pointer to the beginning of that array. You could even access an element of that array by writing
Code:
*(myArray+5)
// or
myArray[5]

regardless of whether it was allocated as a local array on the stack or allocated using malloc().

The only functional difference between

Code:
int*    myArray = malloc( sizeof(int) * 20 );
and
Code:
int myArray[20];

is that, in the first case, sizeof(myArray) is the size of the pointer (probably 4), and, in the second case, it's the size of the entire array (most likely 80). And that, in the first case, you're responsible for freeing the memory, and, in the second case, the memory is automatically released when the array goes out of scope.
 
Last edited:
  • #3
Thanks a lot, that answer really helped me out. One more question came from your post though.

hamster143 said:
The only functional difference between

Code:
int*    myArray = malloc( sizeof(int) * 20 );
and
Code:
int myArray[20];

is that, in the first case, sizeof(myArray) is the size of the pointer (probably 4), and, in the second case, it's the size of the entire array (most likely 80). And that, in the first case, you're responsible for freeing the memory, and, in the second case, the memory is automatically released when the array goes out of scope.

So to be clear, when you declare an array with "int myArray[6]", for example, the size of myArray is the entire array, so chances are 24 bytes? However, if I defined it with malloc, the size of myArray is only the pointer to the first block of my 24 bytes?

Another thing, I ran this code to test what you said:

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

int		main()
{
	int * myArray = malloc( sizeof(int) * 20 );
	
	int size = sizeof(myArray);
	
	printf("%d", size);
	
	return 0;
}

However it returns a value of 8. How come the pointer is 8 bytes, I thought they were 4?
 
  • #4
You must be using a 64-bit operating system. (More specifically, a 64-bit OS and a compiler in 64-bit mode.) In that case, the pointer would be 8 bytes.
 
Last edited:
  • #5
hamster143 said:
You must be using a 64-bit operating system. (More specifically, a 64-bit OS and a compiler in 64-bit mode.) In that case, the pointer would be 8 bytes.

Yeh, that makes sense, I'm using a 64bit mac. Just out if interest, why are pointers larger on 64 bit?
 
  • #6
Epic Sandwich said:
Yeh, that makes sense, I'm using a 64bit mac. Just out if interest, why are pointers larger on 64 bit?

That's the whole point of 64 bit. Or most of it. A 32-bit pointer can't address more than 4 gigabytes of memory.
 
  • #7
hamster143 said:
That's the whole point of 64 bit. Or most of it. A 32-bit pointer can't address more than 4 gigabytes of memory.

Ah, that's just answered a question I've wanted to know for years! I always wondered why 32 bit processors were limited to a certain amount of ram.


I'm also learning about strings at the moment, and instead of cluttering up the forum with another thread, I thought I'd carry it on here (as they are vaguely related I guess).

So, from I understand, you can define a string by using:
Code:
char * stringName = "Text here!";
And that creates a variable that you can use as a string, print it with printf and %s, and compare with strcmp(). Correct?

My first question is, what actually happens here? Essentially, by defining char * stringName, we're making a pointer variable called stringName which can hold the address of one char. So why can you just stick a load of text in a pointer variable? Is C doing something secretly here?

Also, another way of declaring a string is:
Code:
char newString[10]
which makes a string which can hold 9 characters (plus the zero at the end to tell the compiler the string has finished). However, to define the characters in this string, you have to go and define them like so:
Code:
newString[0] = 'H';
newString[1] = 'E';
Is that right? If so, why would you use the second method of creating strings? To me, it just seems more cumbersome to have to define all the characters individually, but i assume there must be a use to it or else no one would use it at all.

I apologise for the long question, but strings just seem a bit weird to me at the moment. For someone who's used to php and javascript, this is a very odd concept to take in!

Thanks for all your help.
 
  • #8
You're not supposed to use char * stringName = "Text here!" . Even if the compiler allows you, it's just wrong. You should write const char * stringName = "Text here!" . When you do that, your program creates a global string somewhere in memory and assign the pointer to that string to "stringName". It is not appropriate to modify those strings (IIRC, the outcome is not even defined by the standard), thus the correct thing to do is to declare the pointer as "const" so it can only be used for reading.

You can do

Code:
char newString[10] = "Text here";

then it's basically the same thing as what we did with ints, and the array will be preloaded with the string. Or you can just allocate it on the stack without initializing it

Code:
char newString[10];

and then fill the elements individually.
 
  • #9
hamster143 said:
You're not supposed to use char * stringName = "Text here!" . Even if the compiler allows you, it's just wrong. You should write const char * stringName = "Text here!" . When you do that, your program creates a global string somewhere in memory and assign the pointer to that string to "stringName". It is not appropriate to modify those strings (IIRC, the outcome is not even defined by the standard), thus the correct thing to do is to declare the pointer as "const" so it can only be used for reading.

You can do

Code:
char newString[10] = "Text here";

then it's basically the same thing as what we did with ints, and the array will be preloaded with the string. Or you can just allocate it on the stack without initializing it

Code:
char newString[10];

and then fill the elements individually.

Ok, so I should only use const char * stringName = "Text here!" to store a string that I'm going to refer to later, and not change. Correct?

Hopefully my final query, if I defined a string using char newString[10] = "Text here";, how would I go about changing the contents of that string? Is the only way to go through individual characters and change them?
 
  • #10
Epic Sandwich said:
Ok, so I should only use const char * stringName = "Text here!" to store a string that I'm going to refer to later, and not change. Correct?

Hopefully my final query, if I defined a string using char newString[10] = "Text here";, how would I go about changing the contents of that string? Is the only way to go through individual characters and change them?

You can modify individual characters, or you can use standard library functions such as strcpy:

Code:
strcpy(newString, "New text");
const char* str1 = "New ";
const char* str2 = "Text";
strcpy(newString, str1);
strcat(newString, str2);

However, you must be careful, because you only have room for 10 characters in the array and you should take care not to overshoot the end.
 
  • #11
hamster143 said:
However, you must be careful, because you only have room for 10 characters in the array and you should take care not to overshoot the end.

Just to add something here: If you want to work with dynamic arrays, then look at the alloc, realloc and free functions. It might be very relevant now, since it also includes some work on pointers.
 
  • #12
Ok, thanks a lot to both of you, I've learned a lot today! I shall be looking into alloc, realloc and free very soon. Thanks again :D
 
  • #13
x[y] is shortand for *(x+y), and thus for *(y+x), and therefore to y[x]. You can actually index by index[array].

That aside, the only difference between static arrays and const pointers is at compile time, not at runtime. &array and sizeof(array) are the two differences that are often cited, but these are compile time things only, not runtime. The compiler can simply replace sizeof(array) with for instance 10*sizeof(int) if you declared int array[10]; in the same lexical block, it doesn't count any more outside of the lexical block, because outside of it has become runtime info, and at runtime an array is just a const pointer to the first element of that array.
 
  • #14
hamster143 said:
If you were to write
Code:
int myArray[20];
that code would really have dual roles. It would allocate a 20-unit array on the stack and assign "myArray" to be the pointer to the beginning of that array.
If the declaration for myArray is done outside of any function, or if it's declared as "static", then it becomes part of the programs data section (usually the "uninitialized" data section of a program), and memory for is allocated at program load time (before the program is executed).
 
  • #15
rcgldr said:
If the declaration for myArray is done outside of any function, or if it's declared as "static", then it becomes part of the programs data section (usually the "uninitialized" data section of a program), and memory for is allocated at program load time (before the program is executed).
That, and it's a const pointer, also an important difference, you can't assign to a static array the same way you can to a 'dynamic array'.
 
  • #16
hamster143 said:
If you were to write
Code:
int myArray[20];
that code would really have dual roles. It would allocate a 20-unit array on the stack and assign "myArray" to be the pointer to the beginning of that array.

rcgldr said:
If the declaration for myArray is done outside of any function, or if it's declared as "static", then it becomes part of the programs data section (usually the "uninitialized" data section of a program), and memory for is allocated at program load time (before the program is executed).

ZQrn said:
That, and it's a const pointer, also an important difference, you can't assign to a static array the same way you can to a 'dynamic array'.
Static just means the name is local to the source file and that the variable is initialized to zero. I'm not sure what you mean by assign, but there is no issue assigning values to elements of a static array, such as
Code:
static int myArray[20];
...
    myArray[3] = 5;
 
  • #17
rcgldr said:
Static just means the name is local to the source file and that the variable is initialized to zero. I'm not sure what you mean by assign, but there is no issue assigning values to elements of a static array, such as
Code:
static int myArray[20];
...
    myArray[3] = 5;
I mean you can't use:

Code:
int myArray[] = {1,2,3,4,5};
int x = 3;
myArray = &x;

Which you can do with variables that house pointers that are not const. As in from Malloc.

With static I mean the general term which some sources call 'lexical', as in static/lexical types versus dynamic types et cetera. With static in computer science people usually mean 'determined at compile time' whereas with dynamic people mean 'determined at runtime'.
 

1. What is a pointer in C?

A pointer in C is a variable that stores the address of another variable. It allows for indirect access to a variable's value, which is useful for tasks such as dynamic memory allocation and passing data between functions.

2. How do pointers work in arrays?

In C, arrays are actually a type of pointer. When declaring an array, the variable name represents the memory address of the first element in the array. This allows for easy manipulation of array elements using pointer arithmetic.

3. How do I declare a pointer to an array?

To declare a pointer to an array in C, the syntax is as follows: data_type (*pointer_name)[size]; where data_type is the type of data in the array and size is the number of elements in the array.

4. How do I access elements in an array using pointers?

To access elements in an array using pointers, you can use pointer arithmetic. For example, to access the third element in an array, you can use *(arr + 2), where arr is the name of the array. This is equivalent to arr[2].

5. What are the benefits of using pointers with arrays?

Using pointers with arrays allows for more efficient memory usage and manipulation. It also allows for passing arrays as arguments to functions without making a copy of the entire array, which can improve performance.

Similar threads

  • Programming and Computer Science
Replies
17
Views
1K
  • Programming and Computer Science
Replies
23
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
17
Views
1K
  • Programming and Computer Science
Replies
2
Views
1K
  • Programming and Computer Science
Replies
19
Views
2K
  • Programming and Computer Science
Replies
20
Views
1K
  • Programming and Computer Science
Replies
4
Views
2K
  • Programming and Computer Science
2
Replies
40
Views
2K
  • Programming and Computer Science
Replies
6
Views
2K
  • Programming and Computer Science
Replies
22
Views
2K
Back
Top