C : explain theory behind - c

I have minimal experience with C, but have been asked to convert a C program into R. There is one bit troubling me:
I have a function that takes an int
int a
and within the function i have an array:
double b[3] = {
1.8293,
-0.592,
2.3330,
}
and later on in the function i have:
c = b[a];
can someone tell me what this line is doing? what is being assigned to c? is it simply an array of size b, where all the values of b have been multiplied by a?
Thanks.

c is assigned with the a th value of array b[].
if a is equal to 1 then c will be equal to -0.592

if a contains 0 then c = b[a] means that the first element of the array b[] is assigned to a, without changing array b

The variable a here is an index into the array. For example if a=0, then b[a] is the first element (1.8293 in this case).
In general b[a] extracts out a particular element from the array.

So here's a mock up of your function as you described it (I made up the parts you failed to mention) I added comments // to explain what is going on:
void foo(int a)
{
// define an array of 3 doubles
//b[0] = 1.8293
//b[1] = -0.592
//b[2] = 2.333
double b[3] = { 1.8293, -0.592, 2.3330 };
double c; // Note c is a double, because we're going to assign
// one of the values from b
//we're going to use a to access array b, that means a has to be 0, 1, or 2
if(a < 3)
c = b[a];
//Now c is set to one of those three values in b
//(depending on what value a has)
return;
}

The a'th element of the double array b is assigned to c (the first element has index 0).

you need to make some step in C learning.
b[a] means that you will get the content of element with index a from b array

Related

Defining an array(C) in Julia by appending array B to array A without changing the values of the array A

I have two arrays A and B. Let's say A=[1,2,3] and B=[4,5,6]. I want to define a third array C = append!(A,B). The problem is this also changes A to be A=[1,2,3,4,5,6]. How to avoid this problem?
append! pushes the elements of the second collection to the first one, modifying it, to just concatenate them, use vcat:
C = vcat(A, B)
Or you can use ; to build a new array from the contents of A and B:
C = [A ; B]
You could try this:
A=[1,2,3]
B=[4,5,6]
C=A
append!(C,B)
Then C = [1,2,3,4,5,6] and B = [4,5,6]. But unfortunately, A = [1,2,3,4,5,6].
The problem is C=A, which makes A and C the same in every way, except for the variable name. Unfortunately, changes to C then also change A, because they occupy the same area of memory, they have the same address.
What you have to do is to copy A to C, before appending B. Then C and A have the same data, before B is appended, but they are separate things. Changing C no longer changes A.
A = [1,2,3]
B = [4,5,6]
C=copy(A)
append!(C,B)
Then C = [1,2,3,4,5,6] and B = [4,5,6]. And, A = [1,2,3].

I'm not able to find what is causing the segmentation error in my C++ code

I have a C++ program where I have to rotate the array clockwise according to the given number of elements to be rotated (x). For example if the input array is
[1,2,3,4,5]
given that 2 elements (denoted as x) must to rotated.
The output array should be
[3,4,5,1,2]
Code:
#include <iostream>
#include<algorithm>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n,x;
cin>>n>>x;
int a[n],b[x];
for(int i=0;i<n;i++){
cin>>a[i];
}
copy(a,a+x,b);
copy(b,b+x,a+n);
n=n+x;
for(int i=x;i<n;i++){
cout<<a[i]<<" ";
}
}
return 0;
}
What I'm doing here is that I copy the given number of elements to a new array. Later copy them back to the original array starting from 'n'. So my array will look like [1,2,3,4,5,1,2].
Later I'm printing out the array starting from the index 'x'. So that my array will look like [3,4,5,1,2].
I'm able to compile the program and I'm getting the output. But while submitting the code in a website called GeekforGeeks its complier is throwing out a Segmentation Fault (SIGSEGV).
This
int a[n],b[x];
is not standard c++. See here for details: Why aren't variable-length arrays part of the C++ standard? . Use std::vector for dynamic arrays.
Then here:
copy(a,a+x,b);
you use x but the size you used for a was n not x. Depending on your input this may acces the array out-of-bounds.
Next, here:
copy(b,b+x,a+n);
you try to copy to a+n but already a+n is beyond the last element of a. Arrays have fixed size, also n=n+x; wont help to change that.
To rotate elements of an array (or std::vector) you can use std::rotate.
Problem 1
The line
copy(a,a+x,b);
does not do what you want to do. It copies the first x elements of a to b, without an offset. If x is 2, that is equivalent to:
b[0] = a[0];
b[1] = b[1];
You need something that will do:
b[0+x] = a[0];
b[1+x] = a[1];
...
b[n] = a[n-x-1];
To achieve that, you need to use:
std::copy(a, a+(n-x), b+x);
Problem 2
The line
copy(b,b+x,a+n);
is notright.
You want to copy from a to b, not from b to a.
Using a+n immediately results in accessing the array using out-of-bounds indices, which causes undefined behavior.
The offsets used in that call don't make sense at all.
After the first line of std::copy is executed, you need something what will do the following:
b[0] = a[n-x];
b[1] = a[n-x+1];
...
b[x-1] = a[n-1];
To achieve that, you need to use:
std::copy(a+(n-x), a+n, b);
Arrays must have determined size
some compilers accept your code but other don't
so try to use pointers instead

What happens if i don't use zero-based array in C

Can someone explain what would happen? Is it really necessary to start at index 0 instead of 1 (which would be easier for me)?
You can do whatever you want, as long as your array subscript is strictly less than the size of the array.
Example:
int a[100];
a[1] = 2; // fine, 1 < 100
What happens if I don't use zero-based array in C
Well, you can't. C arrays are zero based, by definition, by standard.
Is it really necessary to start at 0?
Well, this is no rule to prevent you from leaving index 0 unused, but then, you'll almost certainly not get the desired result.
Using non-zero based arrays in C is possible, but not recommended. Here is how you would allocate a 1-based array of 100 integers:
int * a = ((int*)malloc(100*sizeof(int)))-1;
The -1 moves the start of the pointer back one from the start of the array, making the first valid index 1. So this array will have valid indices from 1 to 100 inclusive.
a[1] = 10; /* Fine */
a[100] = 7; /* Also fine */
a[0] = 5; /* Error */
The reason why this isn't recommended is that everything else in C assumes that pointers to blocks of memory point to the first element of interest, not one before that. For example, the array above won't work with memcpy unless you add 1 to the pointer when passing it in every time.

two dimensional Arrays access using pointers

Is
*(ary[3]+8)
and
ary[3][8]
are the same ? If yes, please explain how ? ary[3] returns the address of first element or the value in ary[3][0] ? ary is a two dimensional array.
Thanks in advance.
Yes
a[i] is same as *(a+i)
ary[i][j] is same as *( *(ary+i)+j))
If x is an array (int, say) x[i] is just a syntactic sugar for *(x+i). In your case, ary is a two-dimensional array (again of int, say). By the same syntactic sugar mechanism, ary[i][j] is equivalent to *((*(ary+i))+j), from which it is clear what happens under the hood.
*(ary[3]+8) says value at 8th column of third row.ary[3] is base address of third Row.ary[3][8] will also access to same element at third row and 8th column.
For Example i am taking an 2D array of two row and 4 column which is equivalent to 1D array of 8 elements.As shown below.
int a[8] = {0,1,2,3,4,5,6,7};
int b[2][4] = {{0,1,2,3},{4,5,6,7}};
since b is 2D array , so you can consider it as array of two 1D arrays.when you pass b[1] or b[1][0] it says address of first row.Rectangular array allocated in memory by Row.so if you want to find address of element a[row][col] it will get calculated as
address = baseAddress + elementSize * (row*(total number of column) + col);
As others already have said, a[i] is just a sugar for *(a+i).
I just would like to add that it always works, that allows us to do things like that:
char a[10];
char b;
char c[10][20];
// all of these are the same:
b = a[5]; // classic
b = *(a + 5); // pointer shifting
b = 5[a]; // even so!
b = c[5][9];
b = *(c[5] + 9);
b = *(*(c + 5) + 9);
b = *(c + 5)[9];
b = 5[c][9];
b = 5[9][c]; // WRONG! Compiling error

Copying a subset of an array into another array / array slicing in C

In C, is there any built-in array slicing mechanism?
Like in Matlab for example,
A(1:4)
would produce =
1 1 1 1
How can I achieve this in C?
I tried looking, but the closest I could find is this: http://cboard.cprogramming.com/c-programming/95772-how-do-array-subsets.html
subsetArray = &bigArray[someIndex]
But this does not exactly return the sliced array, instead pointer to the first element of the sliced array...
Many thanks
Doing that in std C is not possible. You have to do it yourself.
If you have a string, you can use string.h library who takes care of that, but for integers there's no library that I know.
Besides that, after having what you have, the point from where you want to start your subset, is actually easy to implement.
Assuming you know the size of your 'main' array and that is an integer array, you can do this:
subset = malloc((arraySize-i)*sizeof(int)); //Where i is the place you want to start your subset.
for(j=i;j<arraySize;j++)
subset[j] = originalArray[j];
Hope this helps.
Thanks everyone for pointing out that there is no such built-in mechanism in C.
I tried using what #Afonso Tsukamoto suggested but I realized I needed a solution for multi-dimensional array. So I ended up writing my own function. I will put it in here in case anyone else is looking for similar answer:
void GetSlicedMultiArray4Col(int A[][4], int mrow, int mcol, int B[1][4], int sliced_mrow)
{
int row, col;
sliced_mrow = sliced_mrow - 1; //cause in C, index starts from 0
for(row=0; row < mrow; row++)
{
for (col=0; col < mcol; col++)
{
if (row==sliced_mrow) B[0][col]=A[row][col];
}
}
}
So A is my input (original array) and B is my output (the sliced array).
I call the function like this:
GetSlicedMultiArray4Col(A, A_rows, A_cols, B, target_row);
For example:
int A[][4] = {{1,2,3,4},{1,1,1,1},{3,3,3,3}};
int A_rows = 3;
int A_cols = 4;
int B[1][4]; //my subset
int target_row = 1;
GetSlicedMultiArray4Col(A, A_rows, A_cols, B, target_row);
This will produce a result (multidimensional array B[1][4]) that in Matlab is equal to the result of A(target_row,1:4).
I am new to C so please correct me if I'm wrong or if this code can be made better... thanks again :)
In C,as far as I know, array name is just regarded as a const pointer. So you never know the size of the subset. And also you can assign a arrary to a new address. So you can simply use a pointer instead. But you should manage the size of the subset yourself.

Resources