Basic C, pointers into arrays?

  • #1
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.
 

Answers and Replies

  • #2
907
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.

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
907
2
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
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
907
2
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
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
907
2
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
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
907
2
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
1,868
0
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 learnt a lot today! I shall be looking in to alloc, realloc and free very soon. Thanks again :D
 
  • #13
ZQrn
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
rcgldr
Homework Helper
8,710
539
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
ZQrn
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
rcgldr
Homework Helper
8,710
539
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).
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
ZQrn
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'.
 

Related Threads on Basic C, pointers into arrays?

  • Last Post
Replies
10
Views
3K
  • Last Post
Replies
3
Views
1K
Replies
2
Views
10K
Replies
6
Views
6K
  • Last Post
Replies
20
Views
8K
  • Last Post
Replies
5
Views
2K
  • Last Post
Replies
3
Views
3K
  • Last Post
Replies
2
Views
3K
  • Last Post
Replies
0
Views
2K
Top