Hello guys I have a question,
I have an array with 10 elements and a function which returns me a pointer to a randomly chosen element in the array. Now I want to print the array from this element the pointer points to, how can I do that.
Example:
Array: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Pointer points to Element 6.
I want to print: 6, 7, 8, 9, 10
Code looks like this in C:
int* randomElement(int* array, int size) {
int* pointer = NULL;
int randomNumber = 0;
randomNumber = rand() % size;
*pointer = *(array + randomNumber);
return pointer;
}
int main(void) {
int size = 10;
int array[size];
int* pointer = NULL;
srand(time(NULL));
pointer = randomElement(array, size);
/* Want to print the array from this element here */
return EXIT_SUCCESS;
}
You can't.
By only knowing a random element in an array (i.e. having a pointer to one element), you can't print the entire array using that pointer.
You need at least two other data:
1) Length of the array (which you seem to indicate always 10.)
2) The position of the element within the array for which you have a pointer. So that you can calculate, from that position, how many elements before and after are available. (Basically determining array boundaries).
After you edit, the answer remains the same. But your code has problems:
1) You are not filling the array with values. So their values are indeterminate and accssing them is undefined behaviour.
2) You never set pointer to point to an element of the array in randomElement() and the function returns NULL. you are dereferencing NULL (pointer). Again, this will lead to undefined behaviour.
3) You should use size_t for representing array size instead of int.
I will not comment on your code, that is already done. I'll anwer the original question instead. Blue Moon says "You can't", but you can if you wish. You can always do a sequential lookup in any table, if your list of values is terminated with what is called a sentinel value. That is a special value which is known in advance not to belong to the collection of normal data, and thus can be used to flag the end of the sequence, for instance a negative value if all normal data are known to be positive.
For a sequence of n non-negative integers stored in an array of n+1 elements, we can store array[n]= -1 as a sentinel after populating the first n elements with normal data. Then start at a random position in the data sequence and read until the end, with something like
// -- we assume pointer p is an initialized int* that
// satisfies the condition array <= p < array + n
// AND that array[n] is negative.
for( ; *p >= 0; ++p ){
// do something useful with *p
}
Terminating a sequence with a sentinel is a well known general technique and you'll find it in any book on algorithms. You can use it with arrays and with linked lists. In your case you must make sure that the element following the last element you wish to access in the array is a sentinel and that the random choice has not selected the sentinel (if n is the length of the sequence, then rand() % n will give you a correct offset; pointing to a sentinel would not harm, but the for loop would terminate immediately). The size of the allocated array has to be at least n+1, that is the maximum number of data elements you need, plus one for the sentinel.
By the way, in C the last element of an array is not array[size] but array[size-1]. There is no bounds checking on array access when bumping a pointer in C, that's up to you, as you will learn sooner or later from crashing programs. To get rid of confusion between pointers and referenced values you can read the instructive answers to "What exactly is a C pointer if not a memory address?", here at Stackoverflow.
The usual way to use a pointer to iterate over an array where you know the size is:
for (p = array; p != array + size; ++p)
In your case you are initializing p differently but the rest of the loop can stay the same:
for ( ; pointer != array + size; ++pointer )
{
printf("%d\n", *pointer);
}
Of course it is also possible to use an integer index instead of a pointer (where you find the initial index by doing pointer - array).
Note that your randomElement function is currently implemented wrongly. It writes through a null pointer. Instead, what you want to do is to form a pointer to a randomly-selected element and return that pointer, without dereferencing. (i.e. take the *'s out of the line before the return).
Related
I’m taking a C class on Udemy. Unfortunately the instructor isn’t replying to my question so I thought I’d try this site. My assumption is that it is probably fairly common when developing a program to not know how many elements may be part of an array. When initializing an array the instructor recommends not specifying a size but to let the compiler do it.
Example: int array[ ] = {2,3,4,5,6,7,8};
Obviously, using this method there is no index to use to terminate looping. According to “C Primer Plus” by Stephen Prata the element after the last element in the array is a valid pointer location:
(pg. 406) - C guarantees that when it allocates space for an array, a
pointer to the first location after the end of the array is a valid
pointer.
If I’m using pointer notation (array++) to loop through the array, what condition can I use to terminate the looping? Is there a value in that location after the final element that I can use? Is that value always the same or does it change depending on the type of array?
In C pointers are signed. That has consequences dealing with array-like data structures where you might:
while (a <= a+last) {
...
a++;
}
if the index one beyond the end of a could have a change of sign, then that code could fail. Idiomatic C does not suggest the above; but it needs to be preserved, thus this limitation.
In system code, it is possible that you deal with allocations that do not conform to this, thus you should try to work with the idiomatic:
while (a < a+len) {
...
a++
}
So, for your exact question:
for (size_t i = 0; i < sizeof array/sizeof array[0]; i++) {
...
}
or
for (int *p = array; p < array + sizeof array / sizeof array[0]; p++) {
...
}
Your basic idea (looping through an array using pointers) is sound; however, there are a number of points in your question that need some attention.
Is there a value in that location after the final element that I can use? Is that value always the same or does it change depending on the type of array?
Yes, there is a (almost certainly) some value in that location, but it's not something you can ever use! The pointer to the 'one-past-the-end' element is valid only for use in pointer arithmetic or comparison operations; attempting to dereference it (to read the value at that address) is undefined behaviour.
You can get that 'one-past-the-end' pointer by adding the number of elements in the array to the address of the array's first element (or the array 'name' itself). The idiomatic way to get the number of elements in an array is to divide the size of the entire array by the size of its first element. So, for your array, we can declare and initialize our "end pointer" like this, using the sizeof operator:
int* end = array + sizeof(array) / sizeof(*array);
// int* end = array + sizeof array / sizeof *array; // Alternative form: "()" optional
Another important point: In your question you mention using array++ to loop through your array variable. You cannot do this, because array isn't actually a (modifiable) pointer variable – it's the name of a variable (an array) whose location is fixed at the point when main (or whatever function it is declared inside) is entered. Instead, you will need to copy the address of the array into another int* pointer, and increment that in the loop.
With those points in mind, here's an illustrative example of how you can loop through your array using a pointer:
#include <stdio.h>
int main(void)
{
int array[] = { 2,3,4,5,6,7,8 };
int* end = array + sizeof(array) / sizeof(*array);
for (int* p = array; p < end; ++p) {
// Note that, when we reach p == end, the loop will not run, so ...
printf("%d\n", *p); // ...we never attempt the *p operation on that
}
return 0;
}
A couple of other points of clarification:
The int* p = array assignment works (and is perfectly valid C) because an array variable name can readily decay into a pointer to its first element (as it will if you pass that array as an argument to a function, for example). See: What is array to pointer decay?
Because of that last point above, you cannot use the sizeof(a)/sizeof(*a) paradigm to determine the size of an array in a function it is passed to as an argument; in such cases, you need to pass the array's size as an additional argument. See: How do I determine the size of my array in C?
This question already has answers here:
How can I get the size of an array from a pointer in C?
(16 answers)
Closed 1 year ago.
I have a pointer to an array in C which I would like to iterate through, but I don't know the size:
int *array;
I am unsure as to how I should proceed. I was thinking that I should probably try by finding the size by doing:
int array_size = sizeof(array) / sizeof(int);
But I don't know if that could work. I was wondering if there was a more optimal way of doing this?
In C, there is no way to tell the number of elements in an array from a pointer to an element. sizeof(array) / sizeof(*array) only works for an actual array, not for a pointer, which is what a function receives as an argument, even if the array syntax is used in the function prototype. In this case sizeof(array) evaluates to the size of the pointer, so dividing that by the size of an element is meaningless.
The best approach for your function to get the number of elements is to provide it as a separate argument.
If this is not practical, there are different ways to infer the number of elements, relying on a convention that must be adhered to by the callers:
the array could have a known fixed number of elements
the array could have a sentinel value as the last element of the array.
It is common to use a null pointer (NULL) as such a sentinel for arrays of pointers, such as the char *argv[] argument of the main() function, but note that int argc is also provided to this function.
The null byte (\0) is used to tell the end of C strings, which are arrays of char.
In your case, you could consider 0 or -1 to signify the end of the array, but this convention must be used consistently by all callers of your function.
You cannot iterate over an array in c without knowking the number of elements.
Please note that sizeof(array) / sizeof(array[0]) won't work on a pointer, i.e it will not give the number of elements in the array.
It will also not work inside a function, where the array was passed as an argument due to array decay to pointer.
If the array does not contain a known sentinel value (as for example character arrays that contain strings have as the sentinel value the terminating zero character '\0') then you can not find its end.
If you have a pointer like this
int *array;
then the expression sizeof( array ) will yield the size of the pointer itself that does not depend on whether the pointer points to a single object of the type int or to the first element of an integer array with a known number of elements in the array. That size for example can be equal either to 4 or 8 depending on the used system. Thus the expression sizeof( array ) / sizeof( int ) in general will always yield either 1 or 2.
So you have to pass to the function explicitly also the number of elements in the array.
You could determine the number of elements in an array if you pass a pointer to the whole array. For example
void f( int( *a )[10] );
//...
int a[10];
//...
f( &a );
In this case dereferencing the pointer within the function you will get an object of the array type. Thus the expression sizeof( *a ) will yield the size of the original array.
I have a pointer to an array in c to which I would like to iterate through but I don't know the size:
You are in luck if you truly have a pointer to an array as the type of a pointer to an array carries information about the array size.
int some_array[7] = {1, 2, 3, 4, 5, 6, 7};
int (*pointer_to_an_array)[7] = &some_array;
#define N (sizeof(*pointer_to_an_array) / sizeof(*pointer_to_an_array[0]))
for (size_t i = 0; i < N; i++) {
printf("%d\n", (*pointer_to_an_array)[i]);
}
Unfortunately, with int *array;, code does not have a pointer to an array, but a pointer to an int and information about the original array size of some_array[] is not available through array.
int some_array[7] = {1,2,3,4,5,6,7};
int *array = some_array; // Not a pointer to an array
Carry information about array size in another variable.
size_t some_array_n = sizeof some_array/ sizeof some_array[0];
I'm using an array of pointers where each index holds a pointer that points to an array of integers. While I was able to figure out how to print the values in an array using the pointer array, there is one line of code that I need clarity on. I want to understand the difference between **(x+i) and *(*x+i) as the former throws a Segmentation fault exception while the latter prints the desired output. Please refer to my example code below.
int pointer_array=malloc(1*sizeof(int*));
int number_array = malloc(2*sizeof(int));
*(pointer_array)=number_array;
for(int i=0;i<2;i++) {
*(pointer_array+i)=i;
}
for(int i=0;i<2;i++) {
//printf("\n%d",**(pointer_arr+i)); This throws Segmentation Fault exception
printf("\n%d",*(*pointer_arr+i)); // This prints the desired output 0 \n 1
}
The difference between the expressions becomes very clear if we convert them to array notation by making use of the *(a + i) == a[i] equivalence and its corollary *a == a[0].
**(x + i) is x[i][0], whereas *(*x + i) is x[0][i].
In your code we want this:
#include <stdlib.h>
int **pointer_array = malloc(1*sizeof(int*));
^^
int *number_array = malloc(2*sizeof(int));
^
Then the rest of the code means this:
*(pointer_array)=number_array; // pointer_array[0] = number_array
Oops: the loop assigns integers to pointers:
for(int i=0;i<2;i++) {
*(pointer_array+i)=i; // pointer_array[i] = i
}
The above is probably intended to be number_array[i] = i.
for(int i=0;i<2;i++) {
printf("\n%d",*(*pointer_arr+i)); // printf ... pointer_arr[0][i]
}
If we correct the first loop to initialize number_array, then this second loop should retrieve those values.
Otherwise we are marching over uninitialized values.
**(x+i) means "evaluate x+i, which will give a pointer, then read the value that it points to, which will give another pointer, then read the value that it points to", or equivalently, x[i][0]. *(*x+i) means "evaluate x, which will give a pointer, then read the value that it points to, which will give another pointer, then add i to that, then read the value that it points to", or equivalently, x[0][i]. Obviously, these are very different expressions.
Your code is unsafe; malloc will return a void * — a pointer type. You are storing the results in an int. An int is not guaranteed to be large enough to store a void * and indeed won't be on x86, the current predominant architecture.
That being said:
(x+i) if x is a pointer will evaluate to i*sizeof(*x) + x. So it'll evaluate to a pointer that is i slots after x;
**(x+i) will therefore read the pointer from i slots after x and then read whatever that pointer points to.
So from an array of pointers to arrays, it will read the first item from the ith array.
Whereas:
*x+i will read a pointer from x and then add i*sizeof(**x) to it;
*(*x+i) will read a pointer from there and dereference it.
So from an array of pointers to arrays, it will read the iith item from the first array.
I'm trying to create a int and a float array without a size (it might be 0 or it might increment while the user use the program).
I was trying to do the follow:
int bills[];
float totalAmount[];
I can't assign a max size because I'm printing each array with a for loop (If I assign a size of 99 I'll print 99 lines, and I don't want that).
C does not support arrays with a dynamic number of elements. The number of elements of an array must be determined either at compile time or since C99 can be evaluated at runtime at the point of creation. Once the array is created, its size is fixed and cannot be changed. There are a few cases where the size is not explicitly specified between the [], either in array definitions or in array declarations.
You can define an array without an explicit size for the leftmost dimension if you provide an initializer. The compiler will infer the size from the initializer:
int a[] = { 1, 2, 3 }; // equivalent to int a[3] = { 1, 2, 3 };
int m[][2] = {{ 1, 2 }, { 3, 4 }}; // equivalent to int m[2][2] = {{ 1, 2 }, { 3, 4 }};
char s[] = "Hello world\n"; // equivalent to char s[13] = "Hello world\n";
Note how the compiler adds the implicit null terminator in the string case.
You can declare an array without a size specifier for the leftmost dimension in multiples cases:
as a global variable with extern class storage (the array is defined elsewhere),
as a function parameter: int main(int argc, char *argv[]). In this case the size specified for the leftmost dimension is ignored anyway.
as the last member of a struct with more than one named member. This is a C99 extension called a flexible array.
The compiler has no information on the actual size of these arrays. The programmer will use some other information to determine the length, either from a separate variable or from the array contents.
In the case of a function argument, the array is passed as a pointer and even if the number of elements is specified, sizeof(argv) evaluates to the size of a pointer.
You don't declare an array without a size, instead you declare a pointer to a number of records.
so, if you wanted to do
int bills[];
The proper way to do this in C is
int* bills;
And you will have to allocate the size at some point in time and initialize the array.
bills = (int*)malloc(sizeof(int)*items);
The same goes for arrays of other data types. If you don't know the size of the array until runtime, you should use pointers to memory that are allocated to the correct size at runtime.
You could use a combination of malloc() (or calloc()), realloc() and free() to achieve this.
Memory can be allocated as blocks of a fixed size rather than reallocating memory for each number to be stored.
Let's define a macro (or a const if you like) BLOCK_SIZE.
#define BLOCK_SIZE 10
First declare a pointer of appropriate type and allocate the first block.
Note that malloc() as well as realloc() return NULL if some error occurred due to reasons like insufficient memory.
int *ptr=malloc(sizeof(int)*BLOCK_SIZE);
if(ptr==NULL)
{
perror("some error");
return 1;
}
Now declare a variable to store the maximum possible index as per the currently allocated memory (to avoid illegal memory access).
int max_index = BLOCK_SIZE-1;
Now use a loop.
for(int i=0; ; ++i)
{
if(i > max_index)
{
ptr=realloc(ptr, (max_index+1 + BLOCK_SIZE)*sizeof(int));
if(ptr == NULL)
{
perror("insufficient memory!");
break;
}
printf("\nRealloced!");
max_index += BLOCK_SIZE;
}
scanf("%d", &ptr[i]);
printf("\n%d: %d", i, ptr[i]);
}
In each iteration, we check if i is greater than max_index. If it is, another block is allocated using realloc() before reading the value.
Don't forget to deallocate the memory once you are done using it.
free(ptr);
Also, as discussed in this post, malloc() is effectively the same as realloc() with the latter's first argument NULL.
And in the code you posted, there's no need to explicitly cast the return value of calloc() as what's returned is a void pointer which would implicitly be converted to the target pointer type.
See this and this.
i think you can give it a max size ,if you only want to show the first few elements you can put a a for loop upto that element only,same goes for input if u want to initiallize first 30 elements put a for loop upto 30.
I'm a Java programmer struggling to understand C pointers and arrays. (FULL DISCLOSURE: I'm also a CS student, and yes, this question helps me with a programming assignment.)
I'm trying to create an array of int* pointers, then ensure that every pointer is NULL. Later, this will come into play when I need to look up data in the array; whether there is a valid int or a NULL in a given spot will be important.
So allocating the space for the array is easy, but how to set all those pointers to NULL? Here's my less-than-stellar attempt:
#include<stdio.h>
#include<stdlib.h>
#define TABLESIZE 10
int main(int argc, char *argv[]){
int* table = (int*) malloc(TABLESIZE * sizeof(int));
// Initialize all *int pointers to NULL
int i;
for(i=0; i<TABLESIZE; i++){
if((table+i)!=NULL){ // They may be NULL already? I don't know...
*(table+i) = NULL; // This generates a warning:
// "warning: assignment makes integer from pointer without a cast [-Wint-conversion]"
}
}
// Sanity check : are all int* are NULL ?
for(i=0; i<TABLESIZE; i++){
printf("%d: %p %d ", i, (table+i), *(table+i));
if((table+i) == NULL)
printf("(NULL)");
printf("\n");
}
free(table);
return 1;
}
Output is:
$ ./a.exe
0: 0x6000103c0 0
1: 0x6000103c4 0
2: 0x6000103c8 0
3: 0x6000103cc 0
4: 0x6000103d0 0
5: 0x6000103d4 0
6: 0x6000103d8 0
7: 0x6000103dc 0
8: 0x6000103e0 0
9: 0x6000103e4 0
$
So I'll be flat-out honest... I don't know what the above tells me. I'm guessing that I've created a 1D array where all the values in the array are valid ints, all 0.
But this is problematic for later in my program. When it comes time for my code to insert data into table[x], the code must be able to look at the array and know if another valid int was previously inserted in the same spot. If it sees table[x] = 0, does it conclude a 0 was inserted into index x, or that the spot is available?
I liked the idea of using an array of pointers to ints because that would neatly solve this problem. If my code saw:
table[x] --> NULL // This spot is empty and available
table[x] --> 0 // This spot is occupied, can't insert here
But I don't think I'm coding what I want.
Any thought/advice/comments/criticism is greatly appreciated.
Thanks!
-Pete
int* table = malloc(TABLESIZE * sizeof(int));
Does not create an array of pointers, rather it creates a single int pointer to the start of block of allocated memory of size (TABLESIZE * sizeof(int))
The reason you are getting an error is that an int* is just that; a pointer to an int.
The * operator is called the 'dereference' operator. Its job when placed before a variable is to say 'go to wherever this pointer is pointing'. Therefore, the line
*(table+i) = NULL;
Means 'go to wherever table is pointing, move along i * sizeof(int), then set that particular int to NULL. This obviously doesn't make sense - you can't set a an int to NULL, as that's a pointer value. Hence your error.
By the way, since pointers can also be treated like arrays in C, the above line is also the exact equivalent of
table[i] = NULL;
If you want your initial malloc to be an array of pointers you need to allocate space not for int but for int*, so you could do
int** table = malloc(TABLESIZE * sizeof(int*));
Then you have an int** (Double pointer - aka a pointer to a pointer) referencing a block of TABLESIZE int*'s
Once you have done this, the code below that line will correctly set your pointers to NULL. To then achieve the table as described in your question, you will need to do a further malloc for each cell before you put an int in it. So for example to put '3' into cell 2
if(*(table + 2) == NULL) {
*(table + 2) = malloc(sizeof(int));
}
**(table + 2) = 3;
Note the double deference on the last line: 'Go to wherever table is pointing, move along 2 * sizeof(int*), then go to wherever that pointer is pointing.' Again, this can also be achieved with array syntax
if(table[2] == NULL) {
table[2] = malloc(sizeof(int));
}
*table[2] = 3;
Be careful not to call malloc() on the same cell twice; if you do this you will have a memory leak.
I'm a Java programmer struggling to understand C pointers and arrays.
Yes, the "struggling" part is evident in your code.
A C array is simply an ordered collection of elements of a specified type, arranged contiguously in memory. This is similar to a Java array, but Java provides no means for you to see or probe the arrangement of the elements in memory, and its arrays have additional data associated with them (in particular, they know their own lengths).
A C pointer is a value that represents the address of some other object, where "object" means a stored value of any type, including built-in (Java: "primitive") types, aggregate types (structures and arrays), pointer types, and even no particular type. This is similar in some ways to a Java "reference", which is reflected in the fact that Java raises "NullPointerException" if it tries to dereference a null reference.
It is very important to understand that although there is a close relationship between arrays and pointers, they are not at all the same thing. That should be clear from the descriptions above, but I regularly come across clueless claims to the contrary.
It is also important to understand that pointer values can be invalid -- not pointing to any object. You can easily have a pointer value, maybe stored in a variable or an array, whose value is garbage. This is something to manage, not to be afraid of.
Furthermore, it is important to understand that pointer values do not necessarily have to be obtained via memory allocation functions. They can also be obtained via the address-of operator (&) or through evaluation of an expression involving an array, or garbage pointer values can spring up naturally when a pointer is declared but not initialized.
I'm trying to create an array of int* pointers
I'm not sure whether you mean an array whose elements have type int * (pointer to int), an array whose elements have type int ** (pointer to pointer to int), or maybe an array whose elements have type int. My guess from your wording would be the first, reading you literally yields the second, and your actual code presents something like the third.
This would be the declaration of an array of int *:
int *table[TABLESIZE];
Not having specified an initializer, you cannot rely on any particular values for the elements until you assign values. Code similar to what you presented could be used for that (less the NULL check, which has undefined behavior on account of the initial values being indeterminate, and anyway would provide no advantage whatever), but I'd be inclined to write it slightly differently:
for (int i = 0; i < TABLESIZE; i++) {
table[i] = NULL;
}
At this point, the elements of your table are all initialized with the one pointer value that you can be certain does not point to any object. You can check those pointer values, but you must not dereference them:
// Sanity check : are all int* are NULL ?
for(int i = 0; i < TABLESIZE; i++) {
printf("%d: %p ", i, (void *) table[i]);
if(table[i] == NULL)
printf("(NULL)");
printf("\n");
}
I liked the idea of using an array of pointers to ints because that
would neatly solve this problem. If my code saw:
table[x] --> NULL // This spot is empty and available
table[x] --> 0 // This spot is occupied, can't insert here
That does not make sense, because 0 interpreted as a value of any pointer type is a null pointer constant. However, having started by assigning all elements of the table to be NULL, if you intend to set elements to valid pointers when you assign them, then you can check for NULL to see whether a spot is available, since NULL is never a pointer to an object.
Do note, by the way, that if you declare table as a bona fide array, as above, then you do not need to free it. You might, however, need to free some or all of the objects to which its elements point, depending on whether those objects were dynamically allocated, and on whether they have been or will be freed by other means.
In both C and Java, int holds an integer value. There is no additional, distinguishable null state. Usually, every possible bit-pattern for an int represents a distinct integer value, so it is not physically possible to store this extra state.
If you want to implement something that can be "either 'null' or any possible value in the range of int" then you will have to use additional storage for each array entry. (For example, you could maintain a parallel set of boolean flags indicating whether each entry is "active" or not).
An alternative solution would be to reserve one particular integer value to represent that that array entry should be considered "empty". This technique is called sentinel value.
In Java you can have an array of Integer , which is an array of references that may either be "null" or refer to an int stored elsewhere (the language manages the allocation behind the scenes). To simulate that memory layout in C
the code would be:
// Allocate array and initialize all entries to NULL
int * array[ARRAYSIZE] = { NULL };
// Insert at position (repeatable)
if ( array[2] == NULL )
array[2] = malloc( sizeof(int) );
*array[2] = 10;
// Use item
printf("%d\n", *array[2]);
// Remove from position
free( array[2] );
array[2] = NULL;
To avoid memory leaks you will need to remember to loop through and do the removal procedure before array goes out of scope. It would also be good to check for malloc failure and abort the program or take some other action.
Note that this technique would be considered unusual in C, and not space-efficient compared to the other available options.