Questions on Array

Status
Not open for further replies.

electroRF

Member
Hi,
I read that to declare an array in C, one needs to specify the type of the elements and the number of elements required by an array as follows:
type arrayName [ arraySize ];

However, I see many times the following:
int[] arr;
or
int[][] arr;

How come these are valid?

I tried it myself and it resulted in an error.

I also tried it inside function's argument, and also got an error.

(working with DEV-C++).

Thank you for any help.



---EDIT---
I'd appreciate it if you could also comment on the following:

when declaring a pointer:
char *p;
it points on a garbage.

But when declaring + initializing a pointer:
char *p = "text";
does it allocate 5 bytes in memory for p? (text + '\0' are 5 bytes)
 
Last edited:
int[] arr;
or
int[][] arr;
I don't think any of these are valid in C or C++... Looks like a java / C# style to me...

when declaring a pointer:
char *p;
it points on a garbage.

First rule of C/C++... NEVER USE AN UNINITIALIZED POINTER!!

You have no idea where its pointing!!!
But when declaring + initializing a pointer:
char *p = "text";
does it allocate 5 bytes in memory for p? (text + '\0' are 5 bytes)
Indeed!!
 
But when declaring + initializing a pointer:
char *p = "text";
does it allocate 5 bytes in memory for p? (text + '\0' are 5 bytes)
It allocates 5 bytes of memory somewhere else and puts "text"\0 into this memory. It makes sure that this memory is initalized with the "text"\0 before the program runs. Then it allocates memory for the pointer p (whatever the size of the pointer is). Then it initializes p to point to the memory allocated for "text"\o.
 
Correct NG... I should have explained... P is indeed merely a pointer to the allocated text..
 
I want to point out one important difference between arrays and pointers.

char *p = "text";
As said, this allocates 5 bytes for the string and some bytes for the pointer.. and then initializes the pointer to point to the start of the string.
Now, If you say:
sizeof(p);
The size of the pointer variable is returned, which depends on the machine you are programming.

If you declare the variable as an array:
char s[] = "text";
This allocates an array for 5 chars and initializes it to {'t', 'e', 'x', 't', '\0'}
If you now say:
sizeof(s);
The length of the array is returned (5 bytes).

Arrays can be used as pointers, but arrays and pointers are not exactly the same. Using array in this case actually saves you memory, because no extra pointers are allocated. Also accessing the array is probably more efficient.

I see that you post many C questions. If you want to keep studying C, I recommend three books for you:
https://www.amazon.com/Understanding-Using-Pointers-Richard-Reese/dp/1449344186
https://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298/ref=pd_sim_b_2
https://www.amazon.com/21st-Century-Tips-New-School/dp/1449327141/ref=pd_sim_b_1
 
Last edited:
Hi T, NG and IAN,
Thank you very much.

That is very helpful to me!

T, i've got a C book which i'm Reading, but things aren't always 100% clear.

I'd appreciate it if you could help out with the following program that I saw online:

This program writes new malloc and free.

It saves the memory location of p1 in p2[-1] and returns p2 to the user.

Isn't in an error - that this aligned_malloc function returns void** pointer, while it is defined as void* ?

Must they use void** pointer for that? couldn't they used another void* pointer for that?

PHP:
void* aligned_malloc(size_t required_bytes, size_t alignment)
{
void* p1; // original block
void** p2; // aligned block
int offset = alignment - 1 + sizeof(void*);
if ((p1 = (void*)malloc(required_bytes + offset)) == NULL) 
{
return NULL;
}
p2 = (void**)(((size_t)(p1) + offset) & ~(alignment - 1));
p2[-1] = p1;
return p2;
}
void aligned_free(void *p) 
{
free(((void**)p)[-1]);
}
 
This is very advanced stuff

void** is a void pointer to a pointer.. This means you can have several pointers allocated to blocks of memory, the pointer pointer is used to point to one of these memory block pointers...

Are you familiar with normal pointers... try reading about pointer arrays first, so you can get your head round it...
 
Hi Ian,

I'm very familiar with Pointers to Pointers, and also with Pointers.

What I saw in this code is that aligned_malloc function is defined as void*,
but it returns p2, which is void**.

Isn't it an error?
 
No.... the function takes a pointer, allocates against that pointer, then returns a pointer to that pointer..

I agree you only need a pointer to that specific allocation, but library functions have to cater for all and sundry... this is why we write our own functions that are specific to us...

EDIT... You can still use the pointer passed to the allocating function. ie P1 and access the memory..
 
Hi Ian,
Thank you.


In my book I read that you cannot perform arithmetic operations on VOID* pointers.

However, it the function, they do:
PHP:
p2[-1] = p1; // p2 is void**, p1 is void*

How can they do that?

p2[-1] is just like *(p2-1).

How does the compiler know by how many bytes it should go down?

as p2 points to void.
 
Last edited:
What I saw in this code is that aligned_malloc function is defined as void*,
but it returns p2, which is void**.
Isn't it an error?

It may give a warning, but in this case the the void** is cast to void* when it is returned.
In another words, inside the function variable p2 is treated as void**, but the returned value is treated as void*. This should work.

I don't have the interest of finding out how the whole memory allocation etc works. They have some data-structure-system that requires pointers to be manipulated this way (maybe to ensure portability; Different systems have different size pointers etc.. using pointers to pointers eliminates the need to know the exact size of a pointer).
 
Last edited:
p2[-1] is just like *(p2-1).

How does the compiler know by how many bytes it should go down?

as p2 points to void.

All pointers are the same size in the same system. Void pointer points to a memory address which contents is unknown. Void pointer does not mean that the pointer points to "empty" or "null".

p2 here is a void**.
So, p2[-1]
is the same as *(p2-1)
But, the actual memory location value is decremented by sizeof(void*).

And... you are right. If you have void* p1, then you can not say p1[-1], because the sizeof(void) is unknown and result compile error (at least it should, some compilers do not fail).

Manipulations like this are difficult to understand without understanding and studying the underlying data structure (or algorithm) first.
 
Last edited:
P2 doesn't point to void!!! The reason P1 and P2 are declared void is you have no idea the size of the array it points at.

The idea behind the size of the pointer is so you can increment or decrement it.

void * p; just means initialize a pointer that I can point to anything.. The code shows you that to increment a void pointer you need to workout the size of the thing its pointing to.... a void** pointer is the same size... you can increment and decrement through the allocations easier....

void ** p[] = { *P1_a,*P1_b, *P1_c... etc...};

Sorry MrT didn't know you were typing...
 
Yeah.. I have a habit editing my own posts a while after posting

To summarize
sizeof(void*) // This is the size of pointer, because void* is a pointer (to unknown content)
sizeof(void) // This is the size of unknown content.. should not compile
 
Hi T
Got you!

Wow, Thanks a lot!!

p2 here is a void**.
So, p2[-1]
is the same as *(p2- sizeof(void*))

Correct me if i'm wrong, but now I understand (finally) that they actually had to use a void** p2 pointer, in order to do the p2[-1] operation, right?

I mean, they couldn't do such operation on void* type of pointer, right? (i.e. for void* p3, one can't do p3[-1])
 

Thank you Ian !

You're great.

Thank you so much guys for helping out!

As I wrote in my latest post here in reply to T,

That's why they had to use void** pointer, and couldn't do this with only void* type of pointer, because they needed the pointer[-1] operation.
 
Good style would be to use explicit cast when returning the variable p2

return (void*)p2;

instead of
return p2;


Note how they cast the p -variable before using the [-1] indexing.

void aligned_free(void *p)
{
free(((void**)p)[-1]);
}
 
Last edited:
Thank you very much T

That is a great comment!


I noticed an additional reason why they had to use a void** type of pointer.

They had to store the original address given by malloc function.

However, you can't store a value inside an address that void* pointer points to,

therefore you must use a void** pointer to points on that address, and that way you can store a value in that address.

Isn't it?
 
This t

Yes. The "aligned_malloc" wastes some of the memory returned by the standard "malloc". So, they need to store that original pointer somewhere known place, so that they can later free the whole memory. And what could be better place to store that pointer than "-1" from the aligned pointer.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…