Creating an array in fortran - arrays

I am trying to debug a fortran script and I can't figure out why an array is not being defined how it should be. I have parameters
parameter(nx0=101,nd0=40,nindex=1)
parameter(dep1=0,dep2=200,dep3=5)
parameter(del1=0,del2=1000,del3=10)
parameter(pmin=0,nump=6000)
and the array is defined as
real t(nx0,nd0,nindex)
However when I get fortran to print t (which is huge)
print *, 't = ', t
It outputs only zeros and NaNs. Yet when a vector is defined in the same manner:
real x(nx0)
x is defined properly with no zero or NaN terms that do not belong.
I can't understand why t is not initialized properly, does anyone know why?
NOTE: this fortran code that I'm working with is widely used and freely available via the USGS as HASH_v1.2

Variable initialisation is often compiler specific. You should check the documentation for your compiler. Better yet. Manually initialise the arrays and then check that the correct values are returned. Manual initialisation is best practise.

Related

Where are enum for meminfo_proc_show() and variables for si_meminfo() set?

I am not a developer but I understand some C concepts. However, I'm having a hard time finding where the enums (e.g NR_LRU_LISTS, etc) in meminfo.c/meminfo_proc_show() and the variables (e.g. totalram_pages, etc) in page_alloc.c/si_meminfo() are set.
What I meant by set is for example NR_LRU_LISTS = 324077 for instance. What I understood there is that LRU_ACTIVE_FILE equals 3, but there's no = operator in front of NR_LRU_LISTS, so it must be set somewhere else.
I've clicked on the enums/variables to see where they may be called, but there's either too much unrelevant or either non-defining references.
The last thing would be me not being aware of something, but what ?
To be honest, my goal here is to determine how /proc/meminfo 's values are calculated.
But, here my question is: Where do these enums and variables are set ?
Update 1:
The enums part is now solved, and NR_LRU_LISTS equals 5.
But the totalram_pages part seems to be harder to find out...
The constants you are asking about are defined using C's "enum" feature.
enum Foo { A = 4, B, C };
declares constants named A, B, and C with values 4, 5, 6 respectively.
Each constant with no initializer is set to one more than the previous constant. If the first constant in an enum declaration has no initializer it is set to zero.
The variables you are asking about are defined with no initializer, at file scope (that is, outside of any function). For instance, totalram_pages is defined on line 128 of page_alloc.c, with a public declaration for use throughout the kernel on line 50 of linux/mm.h. Because they are defined at file scope and they don't have initializers, they are initialized to zero at program start. (This is a crucial difference from variables defined inside a function with no initializers. Those start off with "indeterminate" values, reading which provokes undefined behavior.)
I do not know how totalram_pages receives a meaningful value. This code is too complicated for me to want to track that down right now.
It sounds like you are just beginning to learn C. Studying other people's code is a good way to learn, but you should start with simple programs. The Linux kernel is not simple, and because it's an operating system kernel, it also does a lot of things that would be considered bad style or just plain wrong in any other program. Don't start with it.
... That said, declaring a bunch of related constants using an enum and letting them take sequential values implicitly is totally normal and good style, and so is defining variables at file scope with no initializer and relying on them to be zero at program start. (It is often wrong to have a global variable in the first place, but if you genuinely need one, relying on implicit initialization to zero is not wrong.) These are things you need to understand and things you are likely to want to do yourself in due course.

How to check if a variable has been initialized in C?

Is there a way to check if a variable has been initialized or not in C?
Consider the following example,
int main(){
int a = 3, b = 7, c;
if ( a > b )
c = a-b;
// Now, how can I check if the variable "c" has some value or not
// I don't want check like this,
// if ( isalpha(c) ) or if ( isdigit(c) )
// or anything similar to like that
}
In other words, does C has some function like defined in Perl. In Perl, I can simply do if (defined c)that would check if the variable is defined or not, and it'd return False for above example. How can I achieve the same in C?
C does not have this ability. You have two main options:
A sentinel value
For example, if you know that the value of c will never be negative, then initialize it to -1, and test that for that.
Add another variable
Create another variable bool we_set_c_to_something = false; and then set it to true when you write to c.
C is a compiled language which doesn't support runtime variable binding, while Perl is a interpreted language which support dynamic typing. So you can check the definition of a variable in Perl, but not in C.
When you declare a variable in C int c;, this variable c is defined but without initialization. The declaration and definition are in one statement.
The definition of a variable in C is not checked by code writer. The compilers do it for you. When compile and link your C code, the compiler will check all variable's definitions. An error will be invoked and the compiling or linking process will stop if there are undefined variables found in your code.
Hope this will make you distinguish the differences.
Wrong question. You're not asking whether the variable is defined. If the variable is not defined then compilation fails. Look up the difference between "declaration" and "definition". In the case of those local variables, you have defined the variable c.
What you're looking for is initialisation. Many compilers will warn you about using variables before they're initialised, but if you persist in running that code then the assumption is that you know better than the compiler. And at that point it's your problem. :) Some languages (e.g. Perl) have an extra flag that travels along with a variable to say whether it's been initialised or not, and they hide from you that there's this extra flag hanging around which you may or may not need. If you want this in C, you need to code it yourself.
Since C++ allows operator overloading, it's relatively easily to implement this in C++. Boost provides an "optional" template which does it, or you could roll your own if you want a coding exercise. C doesn't have the concept of operator overloading though (hell, the concept didn't really exist, and the compilers of the day probably couldn't have supported it anyway) so you get what you get.
Perl is a special case because it rolls the two together, but C doesn't. It's entirely possible in C to have variables which are defined but not initialised. Indeed there are a lot of cases where we want that to be the case, particularly when you start doing low-level access to memory for drivers and stuff like that.

Need help to understand the syntax in xv6 kernel

I am reading files of xv6 kernel and I cannot understand what the following means:
static int (*syscalls[])(void) = {
[SYS_fork] sys_fork,
[SYS_exit] sys_exit,
[SYS_wait] sys_wait,
[SYS_pipe] sys_pipe,
...
}
Can someone explain this to me? Especially what square brackets (e.g [SYS_fork]) mean.
Thank you
That code is making an array of function pointers, using an old alternative GNU extension for designated initialization.
Designated initializations is a feature that was added to C in C99 that lets you specify which array index to assign a specific value for arrays, so they need not be in order. The same feature exists for struct initializations where you can specify the specific field to assign a given value to.
The C99 syntax for array designated initializations is [index] = value. This code in particular though is using an older alternative syntax from GCC, which as per this document has been obsolete since GCC 2.5, in which there is no equals sign used.
In syscall.c the indices are specified using macros defined in syscall.h, the first of which is defined to 1 in syscall.h, et.c.
This is most likely a non-standard way of initializing an array of function pointers. The identifiers SYS_fork etc. are very likely macros or enum constants specifying the element index.
Another possibility is that this is not a C file, but is turned into a syntactically valid C file using some filtering tool prior to compilation.

Run-time parameters in gcc (inverse va_args/varargs)

I'm trying to make some improvements to a interpreter for microcontrollers that I'm working on. For executing built-in functions I currently have something like this (albeit a bit faster):
function executeBuiltin(functionName, functionArgs) {
if (functionName=="foo") foo(getIntFromArg(functionArgs[0]));
if (functionName=="bar") bar(getIntFromArg(functionArgs[0]),getBoolFromArg(functionArgs[1]),getFloatFromArg(functionArgs[2]));
if (functionName=="baz") baz();
...
}
But it is for an embedded device (ARM) with very limited resources, and I need to cut down on the code size drastically. What I'd like to do is to have a general-purpose function for calling other functions with different arguments - something like this:
function executeBuiltin(functionName, functionArgs) {
functionData = fast_lookup(functionName);
call_with_args(functionData.functionPointer, functionData.functionArgumentTypes, functionArgs);
}
So I want to be able to call a standard C function and pass it whatever arguments it needs (which could all be of different types). For this, I need a call_with_args function.
I want to avoid re-writing every function to take argc+argv. Ideally each function that was called would be an entirely standard C function.
There's a discussion about this here - but has anything changed since 1993 when that post was written? Especially as I'm running on ARM where arguments are in registers rather than on the stack. Even if it's not in standard C, is there anything GCC specific that can be done?
UPDATE: It seems that despite behaviour being 'undefined' according to the spec, it looks like because of the way C calls work, you can pass more arguments to a function than it is expecting and everything will be fine, so you can unpack all the arguments into an array of uint32s, and can then just pass each uint32 to the function.
That makes writing 'nice' code for calls much easier, and it appears to work pretty well (on 32 bit platforms). The only problem seems to be when passing 64 bit numbers and compiling for 64bit x86 as it seems to do something particularly strange in that case.
Would it be possible to do at compile time with macros?
Something along the lines of:
https://www.redhat.com/archives/libvir-list/2014-March/msg00730.html
If runtime was required, perhaps __buildin_apply_args() could be leveraged.
from this document, section 5.5, Parameter Passing, it seems like parameters are passed both in registers and in stack, as with most of today platforms.
With "non standard C" I am thinking to pack the parameters and call the function following the documentation with some asm(). However you need a minimal information about the signature of the function being called anyway (I mean, how many bits for each argument to be passed).
From this point of view I would prefer to prepare an array of function names, an array of function pointers and an array of enumerated function signatures (in the number of bits of each argument... you don't need to differentiate void* from char* for example) and a switch/case on the signatures, and a switch/case on the last one. So I have reported two answers here.
You can do a very simple serialization to pass arbitrary arguments. Create an array and memcpy sizeof(arg) bytes into it for each passed argument.
Or you can create structs for function arguments.
Every function takes a char* or a void*. Then you pass either a pointer to a struct with that functions parameters, or you define a set of macros or functions to encode and decode arbitrary data from an array and pass the pointer to that array.

Fortran90 Error: EXTERNAL attribute conflicts with DIMENSION attribute

I've written a function which calculates the eigenvalues of a 2*2 matrix. It takes a 2*2 matrix as an argument and returns 2 eigenvalues via a 2-element array. I have declared the function in the program unit like this:
real, dimension(2), external :: eigenvalues
But it won't compile, it comes up with this error:
Error: EXTERNAL attribute conflicts with DIMENSION attribute
Is it just not possible to have functions that return arrays, or am I doing something wrong?
Any help/suggestions are appreciated, thanks. If it helps, I'm using fortran 90 with the gfortran compiler
Modestly extending the other two answers, I think other approaches are typically preferable to the old "external". (The "Fortran 2003 Handbook" lists at least one case in which "external" must be used.) As already suggested, for your own source code, place the procedures (functions & subroutines) into a contains section of a module and then use it. This will automatically make the interface of your procedures explicit so that the compiler can check compatibility between arguments in calls and the dummy arguments of the procedure -- this can catch a lot of programmer mistakes. If for some reason you don't have access to Fortran source code, for example, you are linking to a library or calling C, then I would write an interface statement describing the procedure. This will inform that compiler that the declared name is a function or program and specify the interface to allow argument check. I would only do this when the module method isn't possible because it is more work and prone to mistakes when changes are made because two items have to be changed.
Probably the reason this isn't working is, that according to the "Fortran 2003 Handbook", the use of the external attribute does not provide an explicit interface, and an explicit interface is required for a function returning an array argument. I don't know why the interface is considered to be non-explicit in this case.
The Intel Fortran compiler documentation tells me that EXTERNAL is incompatible with DIMENSION, which is roughly what your compiler is telling you. I've had a quick look at the standard for Fortran 2003 but have failed to interpret it unambiguously on this point -- so I'll agree with Intel and assert that what your are trying to do is non-standard.
You certainly can write functions which return arrays.
It looks a little odd to me that you have written the function EIGENVALUES and are then trying to declare it to be EXTERNAL. I would normally put my function definitions either in a CONTAINS section within a larger program unit or in a MODULE which the calling unit USEs. In neither case do I need to declare anything EXTERNAL.
Where is the source of EIGENVALUES wrt the source of the calling program ?

Resources