Segmentation fault when accessing array via pointer - c

I have a global array declared as
int Team1[12][8];
When I call the function
int readLineupB(int teamNr){
int (*teamToRead)[12][8];
teamToRead = &Team1;
for (int currentPlayersNumber = 1; currentPlayersNumber<11; currentPlayersNumber++) {
for (int otherNumber = 1; otherNumber<7; otherNumber++) {
*teamToRead[currentPlayersNumber][otherNumber] = 20;
}
}
return 1;
}
it fills the array until position [10],[3], then seemingly for [10],[4] I get a segmentation fault, and I cannot understand why.

Check the data types.
teamToRead is a pointer to int [12][8] array.
Due to operator precedence, the subscript operator binds higher that the dereference.
So, in case of
*teamToRead[currentPlayersNumber][otherNumber] = 20;
you're trying to say something like
*(* ( teamToRead + currentPlayersNumber ) ) [otherNumber] = 20;
where, the pointer arithmetic becomes illegal as they honor the pointer type and thereby ventures out of bounds.
To solve that, you need to enforce the precedence of the dereference by explicit parentheses, like
(*teamToRead)[currentPlayersNumber][otherNumber] = 20;

Another option is to forgo the pointer to 2-dimensional array, and just use pointer to (first of array of) one-dimensional array:
int Team1[12][8];
int readLineupB(int teamNr){
// declare teamToRead as a pointer to array of 8 ints
int (*teamToRead)[8];
// Team1 is of type int x[12][8] that readily decays
// to int (*x)[8]
teamToRead = Team1;
for (int currentPlayersNumber = 1; currentPlayersNumber<11; currentPlayersNumber++) {
for (int otherNumber = 1; otherNumber<7; otherNumber++) {
// no dereference here.
teamToRead[currentPlayersNumber][otherNumber] = 20;
}
}
return 0;
}

Related

Error: assignment to expression with array type, when assigning values to an array

I would like to insert value into the array's last position. So, I created the function insert. This function returns the new array.
In this code, I would like to insert value=0 into array={1}'s last position and assign the new array to an array I declare at the beginning of the main.
So I wrote:
array = insert(&array[0], value, NUM(array), NUM(array)+1)
However, I received the error:
ERROR: assignment to expression with array type` in the line:
`array = insert(&array[0], value, NUM(array), NUM(array)+1);
but if I declare a new_array this error does not occur.
I would like to know why this occurs and how to solve it.
Thanks.
#include <stdio.h>
#define NUM(a) (sizeof(a) / sizeof(*a))
int * insert(int *, int, int, int);
void main(){
int array[] = {1};
// int *new_array;
int value = 0;
int num = 3;
int pos = 2;
array = insert(&array[0], value, NUM(array), NUM(array)+1);
int i;
for(i = 0; i < NUM(array); i++) {
printf("array[%d] = %d\n", i, array[i]);
}
}
int * insert(int *p, int a, int N, int pos){
int i;
// // now shift rest of the elements downwards
// for(i = N; i >= 0; i--) {
// p[i+1] = p[i];
// }
// increase the size by 1
N++;
// shift elements forward
for (i = N-1; i >= pos; i--)
p[i] = p[i - 1];
// insert x at pos
p[pos - 1] = a;
return p;
}
In C, array names are non modifiable lvalues. You cannot assign anything to an array variable. Hence, you are getting error on this statement:
array = insert(&array[0], value, NUM(array), NUM(array)+1);
new_array is a pointer and remember arrays and pointers are different. When you access an array, it is converted to a pointer to first element (there are few exceptions to this rule)1).
Also note that
int array[] = {1};
the size of array array is 1. When you omit the dimension of an array, compiler deduce it based on the size of initialiser and you are initialising array with only one element. So, the array array is an array of one int type element.
That means, this
int array[] = {1};
is same as this
int array[1] = {1};
You are passing NUM(array)+1 to insert() function and accessing array element at pos index, where pos value is NUM(array)+1, i.e. accessing array beyond its size, which is an undefined behaviour.
Also, you should not use void as return type of main() function . As per C language standards, the return type of main() function should be int.
From C11 Standards#6.3.2.1p3 [emphasis added]
3 Except when it is the operand of the sizeof operator, the _Alignof 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. ....

Initialize values of dynamic array in a function (C language)

this is my code:
void init_array(int** array) {
*array = (int*) malloc(3 * sizeof(int));
/* ???? **(array+2) = 666; */
return;
}
void init(int* array, int* length) {
*length = 3;
*(array+0) = 0;
*(array+1) = 1;
*(array+2) = 2;
return;
}
int main(void) {
/* Variables */
int array_length;
int* array;
/* Initialize */
init_array(&array);
init(array, &array_length);
free(array);
return 0;
}
My question is: How can I initialize values of the array in a function init_array().
I have attempted things such as:
**(array+2) = 666;
*(*(array+2)) = 666;
*array[2] = 666;
**array[2] = 666;
When I used pencil and paper I came to result that **(array+2) should work but it gives me a segmentation fault.
I would appreciate your answer because I am confused how pointers in C actually work.
You have the address of a pointer passed to the function:
array
You want to dereference that to get the pointer:
*array
Then apply the array subscript operator to the result:
(*array)[2]
Or equivalently:
*((*array) + 2)
The parenthesis are required because the array subscript operator [] has higher precedence than the dereference operator *.
Generally speaking, you should use the array subscript operator whenever possible, as it tends to be easier to read.

how to increment an array in c

I am trying to increment an int array using a variable as the increment but it throws an error.
int array[MAXSIZE];
int n;
//fill the array with some numbers
//some other code
The situation here is that once I analyze the first "n" numbers i will not need them again and it will be a waste of cycles to iterate the array from the starting so i want to increment the array by "n".
NOTE: because of the type of the problem that I'm working on I cannot just
save the position in a variable and start from that position later using array[position]; I have to increment the pointer permanently.
array += n;
and Throws this error: incompatible type in assignment.
I don't know in advance what "n" is going to be. I tried to use
array += sizeof(int)*n; but it fails as well.
int array[MAXSIZE];
array is an array and not a pointer. You can not increment an array variable.
You can do something like:
int *p = array;
p += whatever;
just make sure that you don't deference p when it is pointing to any element beyond the last element of the array.
The fact that printing out array and p will give you the same output (address) does not make them the same things.
According to the C Standard (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.
So you may not change an array such a way as
array += n;
So just use one more variable of the type int *. For example
int array[MAXSIZE];
int n;
//...
int *p = array;
p += n;
an array name is a type * const array_name so you can't move it.(pay attention it is a const pointer)
you can define a pointer yourself and then move it. for example:
int *arr = new int[siz];
or in c:
int *arr = (int *)malloc(n * sizeof(int));
if your source code is in a .c file, you do not need to do casting.
If you are trying to fill the array with data, then you will need to index into the array.
int array[MAXSIZE];
int i;
for (i = 0; i < MAXSIZE; i++) {
array[i] = rand();
}
If you genuinely want to make use of a pointer, and do 'pointer arithmetic' then you must be careful.
int array[MAXSIZE];
int *p;
int i;
p = &(array[0]);
for (i = 0; i < MAXSIZE; i++) {
*p = rand();
p += 1;
}
Pointer arithmetic may not work as you expect... Doing p += 1 does not move the pointer along one byte, or even one int, but it will move the address along the size of the variable's de-referenced type.
Do an experiment:
#include <stdio.h>
void main(void) {
struct info {
int a;
int b;
};
struct info array[10];
struct info *p;
int n;
p = &(array[0]);
printf("sizeof(*p): %zu\n", sizeof(*p));
for (n = 0; n < 10; n++) {
printf("address: %p\n", p);
p += 1;
}
}
This will advance p's value by sizeof(*p) each time around the loop.
#include<stdio.h>
#include<stdlib.h>
#define MAX 100
int main()
{
int array*,i,n;
printf("Enter size of array:\n");
scanf("%d",&n);
array = malloc(n*sizeof(int));
/* code to enter numbers in array */
array += n;
//remember to free pointers after you are done with them
free(array);
return 0;
}
This should do it.

Return Array in C?

I cant return array in c,i am quite new to C so i probably do some kind of funny mistake, here is
the code:
#define MAXSIZE 100
int recievedNumbers[MAXSIZE];
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
recievedNumbers = getACOfNumber(256);
for (int i = 0; i < sizeof(recievedNumbers) / 8; i++) {
Serial.print(recievedNumbers[i]);
}
Serial.println();
}
int* getACOfNumber(int theNumber) {
bool done = false;
int i = 0;
int theArray[100];
while (!done) {
if (theNumber % 2 == 0) {
theNumber = theNumber / 2;
theArray[i] = 2;
} else if (theNumber % 3 == 0) {
theNumber = theNumber / 3;
theArray[i] = 3;
}
else if (theNumber % 5 == 0) {
theNumber = theNumber / 5;
theArray[i] = 5;
}
else if (theNumber % 7 == 0) {
theNumber = theNumber / 7;
theArray[i] = 7;
} else {
theArray[i] = theNumber;
done = true;
}
i++;
}
return theArray;
}
Error Message :
AC:10: error: incompatible types in assignment of 'int*' to 'int
[100]'
exit status 1 incompatible types in assignment of 'int*' to 'int
[100]'
You can not assign to an array from an expression:
int recievedNumbers[MAXSIZE];
...
recievedNumbers = getACOfNumber(256);
Instead:
memcpy(receivedNumbers, getACOfNumber(256), sizeof(receivedNumbers));
An notice that you are using a local array whose lifetime ends with the function, change to
static int theArray[100];
or better yet
int *theArray = calloc(100, sizeof(*theArray)); /* Zero initializes the array */
don't forget to call free at the end:
int *temp = getACOfNumber(256);
memcpy(receivedNumbers, temp, sizeof(receivedNumbers));
free(temp);
But why don't you pass the original array to the function?:
getACOfNumber(receivedNumbers);
...
void getACOfNumber(int *theArray) {
Try replacing int theArray[100] with int *theArray=malloc(100*sizeof int).
While internally in C arrays are pointers arrays and pointers look very similar, they are of different type - this is what compiler is complaining about.
Additionally, the compiler has saved you from a painful memory corruption error:
when you define a local array variable inside your function, it gets memory allocated on function's stack. This gets released when function ends, so your result either becomes invalid or may become invalid later, or worse, cause various segmentation faults. malloc allocates memory in global application heap, it won't go bad after function terminates. But then, don't forget to free it after use.
In C, you can't return an array from any function, but you don't need to do so too. Because you can pass the array to the funtion (the array's reference will be sent) and change whatever you want in the array. The change(s) will stay in the array even if the program comes out of that function. Thank you.
The compiler is complaining about the line
recievedNumbers = getACOfNumber(256);
You cannot use the = operator to assign the contents of an array; an array expression may not be the target of an assignment operation. Also, the result of getACOfNumber is an int *, which is not the same type as int [100].
This could work if you declared receivedNumbers as
int *recievedNumbers;
In that case you're assigning a pointer to a pointer, which should work.
But, you have another problem:
int* getACOfNumber(int theNumber) {
bool done = false;
int i = 0;
int theArray[100];
...
return theArray;
}
This will not do what you expect. Once the getACOfNumber function exits, theArray no longer exists - the pointer you return is no longer valid.
IMO, your best bet is to pass the array as a parameter to getACOfNumber and update it directly in the function:
getACOfNumber( 256, receivedNumbers, MAXSIZE );
...
void getACOfNumber( int number, int *theArray, size_t max )
{
bool done = false;
size_t i = 0;
while ( i < max && !done )
{
... // use existing code
}
}

Having trouble returning C returning array

I declare hws globally and try to return it in this method but I get a pointer error. I was wondering if anyone knew why that is and could suggest a solution? Randomize just get a random number.
extern int hws[100][20];
int randomize()
{
int value;
int tru_fals = 0;
value = -1;
while ( tru_fals != 1 )
{
value = rand();
if ( 0 < value )
{
if( 101 > value )
{
tru_fals = 1;
}
}
}
return value;
}
int *populate()
{
int i, j;
i = 0;
j = 0;
while( i < 20 )
{
while ( j < 100)
{
int temp = randomize();
hws[i][j] = temp;
j++;
}
i++;
}
return hws;
}
there is a bug: the array is declared as 100x20 but then you iterate through it like it is 20x100.
You define extern int hws[100][20];.
This doesn't create any array. It just says that somewhere in the program, there should be one.
To make it work, some other source file must really define the array - int hws[100][20]; (without extern). Then, if you compile both and link together, it should work.
If you only want one source file, it's much easier - just remove extern.
But: Just noticed Serge's answer, which is actually the real cause of the problem.
Except when it is the operand of the sizeof, _Alignof, or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and its value will be the address of the first element in the array (6.3.2.1/3).
In the line return hws; in populate, the type of the expression hws is "100-element array of 20-element array of int"; by the rule above, it will be converted to type "pointer to 20-element array of int", or int (*)[20]. Thus, the correct declaration for populate would need to be
int (*populate())[20]
{
...
return hws;
}
which reads as
populate -- populate
populate() -- is a function
*populate() -- returning a pointer
(*populate())[20] -- to a 20-element array
int (*populate())[20] -- of int.
and the type of whatever you return the result to would need to be int (*)[20] as well.
Having said that...
Using global variables this way is highly discouraged for a number of reasons. It would be better to pass the array in to populate as a parameter, like so:
void populate(int (*arr)[20], size_t rows)
{
size_t i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < 20; j++)
{
arr[i][j] = randomize();
}
}
}
You would call this as simply
populate(hws, sizeof hws / sizeof hws[0]);
If you're using a compiler that supports variable length arrays (either a C99 compiler or a C2011 compiler that does not define __STDC_NO_VLA__ or defines it to 0), you could define the function as
void populate(size_t cols, size_t rows, int (*arr)[cols]) // cols must be declared
{ // before it can be used
size_t i, j; // to declare arr
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
arr[i][j] = randomize();
}
}
}
and call it as
size_t rows = sizeof hws[0] / sizeof hws[0][0]; // dividing the size of the array
size_t cols = sizeof hws / sizeof hws[0]; // by the size of the first element
populate(cols, rows, hws); // gives the number of elements
so you're not hardcoding the 20 anywhere.
If you aren't using a compiler that supports variable length arrays, and you don't want to hardcode the number of rows in the function prototype, you can do something like this:
void populate(int *arr, size_t rows, size_t cols)
{
size_t i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
arr[i * rows + j] = randomize();
}
}
}
and call it as
// rows and cols calculated as above
populate(&hws[0][0], rows, cols);
In this case, instead of passing a pointer to the array, we pass a pointer to the first element (the address value is the same, but the type is int * instead of int (*)[20]. So the populate function treats it like a 1D array, and computes the offset with i * rows + j. Note that this trick will only work for 2D arrays that have been allocated contiguously.
This also means that populate can work with arrays of any size, not just Nx20.
hws is a matrix, it means that its and int **
You are returning and int * so you are having a pointer type mismatch.
First, it doesn't need to be returned since it's global. Second, it is a pointer to a pointer to an int. It's an array of an array.

Resources