This doesn't look like a function. What is this? - c

A friend asked me to write a function in C to return the 100th element of an array. I'm not very familiar with C, so I wasn't sure how to make a generic function that could do this with any type of array, so I cheated and assumed that it was an array of integers and wrote this function:
int GetHundredthElement(int *array) {
return array[100 - 1];
}
(the - 1 is there because arrays are zero-indexed)
I asked him how to make a function that would work for any type of array. He told me there was a simple way to do it:
int GetHundredthElement = 100 - 1;
and that this "function" could be called like this:
GetHundredthElement[array];
I tried it, and it worked, but doesn't look like a function to me because it uses bracket notation, which isn't how function calls are written in C. I don't really understand exactly what this code is doing or how it's doing it. What's going on here?

It's not a function, it simply takes advantage of a little-known C fact that array indexes can be interchanged. All the x[y] notation really means is that you're accessing the xth offset of the y array. But you could just as easily write y[x] in your case and get the same result.
99[array] and array[99] are interchangeable and mean the same thing. By declaring GetHundredthElement to be 99, your friend played a neat trick :)
You CAN however write a generic function to get the hundredth element of an array fairly easily using C++ templates (not C).

You are right about the fact that GetHundredthElement is not a function-- it is, as you would expect, an integer.
However, this illustrates a surprising ability in C where you can reverse the order of your array access!
assert(a[5] == 5[a]);
This is because an array access can be implemented in pointer arithmetic:
assert(a[5] == *(a+5));
assert(*(a+5) == *(5+a));
assert(*(5+a) == 5[a]);

When using pointers, pointer[ index ] and index[ pointer ] are actually the same. It's not a function, its a regular operator; its the same as array[ GetHundredthElement ] or array[ 100 - 1 ].

This is the special funky way you can access arrays.
Let's recall that arrays can be treated like pointers, and you can use arithmetic.
For example:
let x be some arbitrary array:
int x[4];
Implies accessing x's 5th element, which is *(x+4).
Terrible example of memory layout:
x -> [0][1][2][3][4]
Now, the weird thing you can do with C arrays/pointers to blocks, is flip the number and variable in bracket notation.
x[4] is equal to 4[x]
Because they break down to:
*(x+4) and *(4+x)

In C, the bracket notation is short hand for pointer arithmetic. A normal use like x[i] is syntactically equivalent to *(x + i) (remember that arrays are pointers). If instead you had used i[x] then it's the same as *(i + x) and produces the same output. As noted by other answers, this approach is not a function, just an interesting technique.

Related

Fortran Array Splice Initialization

I'm trying to initialize an array with equal spacing between 0 and 1 in fortran.
My code is :
program test
double precision :: h
double precision, dimension(:), allocatable :: x
h = 1./11
if(.not. allocated(x)) allocate(x(10))
x(1:10) = [h:(1-h):h] (*)
end program
The error I am given is "The highest data type rank permitted is INTEGER(KIND=8)" at the stared line.
I've tried to change it with
x(1:10) = h:(1-h):h
x = h:(1-h):h
x(1:10) = (/(h:(1-h):h)/)
and various other forms with no luck.
The syntax you're using is not valid Fortran and implied DO loops can't have non-integer bounds. You want something like this:
x = h * real([(i,i=1,size(x))],kind(h))
For more information, look up "array constructors" in the standard or a textbook.
Don't use (1:10) on the left side - see https://software.intel.com/en-us/blogs/2008/03/31/doctor-it-hurts-when-i-do-this
This expression
[h:(1-h):h]
is, from a Fortran point of view, broken. It looks a bit like an array slice, but that would require integers, not reals, and ( and ) rather than the [ and ]. And it looks a bit like an array constructor, for which [ and ] are correct, but h:(1-h):h isn't.
Try this
x = REAL([(ix,ix=1,10)],real64)/11
(having declared ix to be an integer). The expression (ix,ix=1,10) is an implied do-loop and, inside the [ and ] produces an array with integers from 1 to 10. I trust the rest is obvious.
Incidentally, since the lhs of my suggested replacement is the whole of x you don't actually need to explicitly allocate it, Fortran will automatically do that for you. This is one of the differences between a whole array section, such as your x(1:10) and the whole array, x.
And if that doesn't produce the results you want let us know.

Why does C support negative array indices?

From this post in SO, it is clear that C supports negative indices.
Why support such a potential memory violation in a program?
Shouldn't the compiler throw a Negative Index warning at least? (am using GCC)
Or is this calculation done in runtime?
EDIT 1: Can anybody hint at its uses?
EDIT 2: for 3.) Using counters of loops in [] of arrays/pointers indicates Run-time Calculation of Indices.
The calculation is done at runtime.
Negative indices don't necessarily have to cause a violation, and have their uses.
For example, let's say you have a pointer that is currently pointing to the 10th element in an array. Now, if you need to access the 8th element without changing the pointer, you can do that easily by using a negative index of -2.
char data[] = "01234567890123456789";
char* ptr = &data[9];
char c = ptr[-2]; // 7
Here is an example of use.
An Infinite Impulse Response filter is calculated partially from recent previous output values. Typically, there will be some array of input values and an array where output values are to be placed. If the current output element is yi, then yi may be calculated as yi = a0•xi + a1•xi–1 +a2•yi–1 +a3•yi–2.
A natural way to write code for this is something like:
void IIR(float *x, float *y, size_t n)
{
for (i = 0; i < n; ++i)
y[i] = a0*x[i] + a1*x[i-1] + a2*y[i-1] + a3*y[i-2];
}
Observe that when i is zero, y[i-1] and y[i-2] have negative indices. In this case, the caller is responsible for creating an array, setting the initial two elements to “starter values” for the output (often either zero or values held over from a previous buffer), and passing a pointer to where the first new value is to be written. Thus, this routine, IRR, normally receives a pointer into the middle of an array and uses negative indices to address some elements.
Why support such a potential memory violation in a program?
Because it follows the pointer arithmetic, and may be useful in certain case.
Shouldn't the compiler throw a Negative Index warning at least? (am using GCC)
The same reason the compiler won't warn you when you access array[10] when the array has only 10 elements. Because it leaves that work to the programmers.
Or is this calculation done in runtime?
Yes, the calculation is done in runtime.
Elaborating on Taymon's answer:
float arr[10];
float *p = &arr[2];
p[-2]
is now perfectly OK. I haven't seen a good use of negative indices, but why should the standard exclude it if it is in general undecidable whether you are pointing outside of a valid range.
OP: Why support ... a potential memory violation?
It has potential uses, for as OP says it is a potential violation and not certain memory violation. C is about allowing users to do many things, include all the rope they need to hang themselves.
OP: ... throw a Negative Index warning ...
If concerned, use unsigned index or better yet, use size_t.
OP ... calculation done in runtime?
Yes, quite often as in a[i], where i is not a constant.
OP: hint at its uses?
Example: one is processing a point in an array of points (Pt) and want to determine if the mid-point is a candidate for removal as it is co-incident. Assume the calling function has already determined that the Mid is neither the first nor last point.
static int IsCoincident(Pt *Mid) {
Pt *Left = &Mid[-1]; // fixed negative index
Pt *Right = &Mid[+1];
return foo(Left, Mid, Right);
}
Array subscripts are just syntactic sugar for dereferencing of pointers to arbitrary places in memory. The compiler can't warn you about negative indexes because it doesn't know at compile time where a pointer will be pointing to. Any given pointer arithmetic expression might or might not result in a valid address for memory access.
a[b] does the same thing as *(a+b). Since the latter allows the negative b, so does the former.
Example of using negative array indices.
I use negative indices to check message protocols. For example, one protocol format looks like:
<nnn/message/f>
or, equally valid:
<nnn/message>
The parameter f is optional and must be a single character if supplied.
If I want to get to the value of character f, I first get a pointer to the > character:
char * end_ptr = strchr(msg, '>');
char f_char = '1'; /* default value */
Now I check if f is supplied and extract it (here is where the negative array index is used):
if (end_ptr[-2] == '/')
{
f_char = end_ptr[-1];
}
Note that I've left out error checking and other code that is not relevant to this example.

The idea of C array in matlab

Is it possible to apply the idea of array in C to MATLAB
For example, if we have
Double array[10];
and if we want to assign a value we write for example
Array[5]=2;
Is there any way to write equivalent one in MATLAB ?
I'm not sure what you mean by "Is it possible to apply the idea of array in C to MATLAB". An array is just a 1D list of numbers (or other data types). MATLAB primarily is designed to work with matrices (MATLAB is short for Matrix laborartory) and an array or vector is simply a special case of a matrix. So I guess the answer to your question is yes, if I have understood correctly.
To initialise arrays or matrices in MATLAB we use zeros or ones:
>> array = zeros(1,5)
array =
0 0 0 0 0
We can then index elements of the array in the same way as C:
>> array(3) = 3
array =
0 0 3 0 0
Note, however, that MATLAB array indexing is one based whereas C arrays are zero based.
This article describes matrix/array indexing in MATLAB.
You can define your own class, override the [] operator.
I described the mechanism in Here
Since it is a custom function, you might as well change the 1-based indexing to 0-based indexing.
Regarding the constructor, I doubt that you can do it.
Anyhow, why would you want to do it?
You will confuse all of the Matlab users, and cause havoc.
When in Rome, do as Romans do.
Yes you can. Arrays are used in C and MATLAB and they can be used for the same functions. Except, please keep in mind the array-indexing of C and MATLAB are different.
The first element of a C array has an index of zero. i.e. in X = [10 20 30 40], x[0] will return 10. But in MATLAB, this will give an error. To access the number 10, you have to use the expression x[1] in MATLAB.
There is no indexing operator []. You must use () for indexing array.
If you write
x = 1:10;
x[2]
then you'll get the following error
x[2]
|
Error: Unbalanced or unexpected parenthesis or bracket.

Matlab array of struct : Fast assignment

Is there any way to "vector" assign an array of struct.
Currently I can
edges(1000000) = struct('weight',1.0); //This really does not assign the value, I checked on 2009A.
for i=1:1000000; edges(i).weight=1.0; end;
But that is slow, I want to do something more like
edges(:).weight=[rand(1000000,1)]; //with or without the square brackets.
Any ideas/suggestions to vectorize this assignment, so that it will be faster.
Thanks in advance.
This is much faster than deal or a loop (at least on my system):
N=10000;
edge(N) = struct('weight',1.0); % initialize the array
values = rand(1,N); % set the values as a vector
W = mat2cell(values, 1,ones(1,N)); % convert values to a cell
[edge(:).weight] = W{:};
Using curly braces on the right gives a comma separated value list of all the values in W (i.e. N outputs) and using square braces on the right assigns those N outputs to the N values in edge(:).weight.
You can try using the Matlab function deal, but I found it requires to tweak the input a little (using this question: In Matlab, for a multiple input function, how to use a single input as multiple inputs?), maybe there is something simpler.
n=100000;
edges(n)=struct('weight',1.0);
m=mat2cell(rand(n,1),ones(n,1),1);
[edges(:).weight]=deal(m{:});
Also I found that this is not nearly as fast as the for loop on my computer (~0.35s for deal versus ~0.05s for the loop) presumably because of the call to mat2cell. The difference in speed is reduced if you use this more than once but it stays in favor of the for loop.
You could simply write:
edges = struct('weight', num2cell(rand(1000000,1)));
Is there something requiring you to particularly use a struct in this way?
Consider replacing your array of structs with simply a separate array for each member of the struct.
weights = rand(1, 1000);
If you have a struct member which is an array, you can make an extra dimension:
matrices = rand(3, 3, 1000);
If you just want to keep things neat, you could put these arrays into a struct:
edges.weights = weights;
edges.matrices = matrices;
But if you need to keep an array of structs, I think you can do
[edges.weight] = rand(1, 1000);
The reason that the structs in your example don't get initialized properly is that the syntax you're using only addresses the very last element in the struct array. For a nonexistent array, the rest of them get implicitly filled in with structs that have the default value [] in all their fields.
To make this behavior clear, try doing a short array with clear edges; edges(1:3) = struct('weight',1.0) and looking at each of edges(1), edges(2), and edges(3). The edges(3) element has 1.0 in its weight like you want; the others have [].
The syntax for efficiently initializing an array of structs is one of these.
% Using repmat and full assignment
edges = repmat(struct('weight', 1.0), [1 1000]);
% Using indexing
% NOTE: Only correct if variable is uninitialized!!!
edges(1:1000) = struct('weight', 1.0); % QUESTIONABLE
Note the 1:1000 instead of just 1000 when indexing in to the uninitialized edges array.
There's a problem with the edges(1:1000) form: if edges is already initialized, this syntax will just update the values of selected elements. If edges has more than 1000 elements, the others will be left unchanged, and your code will be buggy. Or if edges is a different type, you could get an error or weird behavior depending on its existing datatype. To be safe, you need to do clear edges before initializing using the indexing syntax. So it's better to just do full assignment with the repmat form.
BUT: Regardless of how you initialize it, an array-of-structs like this is always going to be inherently slow to work with for larger data sets. You can't do real "vectorized" operations on it because your primitive arrays are all broken up in to separate mxArrays inside each struct element. That includes the field assignment in your question – it is not possible to vectorize that. Instead, you should switch a struct-of-arrays like Brian L's answer suggests.
You can use a reverse struct and then do all operations without any errors
like this
x.E(1)=1;
x.E(2)=3;
x.E(2)=8;
x.E(3)=5;
and then the operation like the following
x.E
ans =
3 8 5
or like this
x.E(1:2)=2
x =
E: [2 2 5]
or maybe this
x.E(1:3)=[2,3,4]*5
x =
E: [10 15 20]
It is really faster than for_loop and you do not need other big functions to slow your program.

Function Returning an array in Fortran

It is my understanding that you can return an array from a function in Fortran, but for some reason my code is only returning the first value in the array I am asking it to return. This is the function:
function polynomialMult(npts,x,y)
integer npts
double precision x(npts), results(npts + 1), y(npts,npts)
polynomialMult = x(1:npts) + 1
end function
and this is where I'm calling it
C(1:numPoints) = polynomialMult(numPoints,x,f)
print *, C(1:numPoints)`
right now it doesn't do anything useful because I am trying to understand the syntax before I write the logic. I saw some stuff about specifying types for functions, but when I write
integer function polynomialMult(npts,x,y)
or whatever I get a compilation error.
To define a function which returns an array include the function declaration inside the function, like this:
function polynomialMult(npts,x,y)
integer npts
double precision x(npts), results(npts + 1), y(npts,npts)
! Change the next line to whatever you want
double precision, dimension(npts) :: polynomialMult
polynomialMult = x(1:npts) + 1
end function
Your declaration
integer function polynomialMult(npts,x,y)
declares that the function returns an integer. An integer, not an array of integers. I don't think the standard allows function declarations such as:
integer, dimension(10) function polynomialMult(npts,x,y)
but I could be wrong. I always use the form I showed you above.
If you have an up to date Fortran compiler you can do clever things such as return an allocated array. And I suggest you figure out array syntax. For example, your statement:
polynomialMult = x(1:npts) + 1
could more concisely be written:
polynomialMult = x + 1
since Fortran will map the scalar addition to all elements of the array x which you have declared to have only npts elements.
Passing the sizes of arrays into subroutines is very FORTRAN77 and almost always unnecessary now. Generally you either want to operate on every element in an array (as in the array syntax example) or you should let the subprogram figure out the size of the array it is dealing with.
I agree with the previous responder that the following works:
polynomialMult = x + 1
However, without knowing that polynomialMult and x are arrays, one might assume it is a scalar operation. I prefer to be obvious and do it this way:
polynomialMult(:) = x(:) + 1
I have even insisted that the coders in my group do it this way. I don't like to work hard to understand someone's code--I want it to be obvious what they are doing.

Resources