I am a total FORTRAN 77 newbie, and I don't understand why the first code shows an error while the second one compiles when I expect them to do the same.
First code (which doesn't compile and gives a error citing an unexpected data declaration statement at z):
program FOO
integer x, y
x = 1
y = 2
integer z
z = 3
end
This code which looks 100% similar in functionality to the first one compiles without errors
program FOO
integer x, y, z
x = 1
y = 2
z = 3
end
I also tried disabling implicit variable declarations in the first code with no effects.
Fortran is one of those quaint "define everything at the top" languages. In other words, this would be fine:
program FOO
integer x, y
integer z
x = 1
y = 2
z = 3
end
since all type specifications are before any executable code. If you're going to define a variable, you should define it first. See here for example:
Such non-executable statements must be placed at the beginning of a program, before the first executable statement.
I don't know real solution but maybe fortran77 doesn't support any code between variables.
for example;
integer x, y, z
x = 1
y = 2
z = 3
works but
integer x, y
x = 1
y = 2
integer z
z = 3
doesn't work. Because between two integer definening (integer x, y and integer z ), there are variables assigning.
#paxdiablo: you think right!
and the errormessage:
"... unexpected data declaration statement at ..."
all DELCARATION must be made BEFORE the first STATEMENT occurs. fortran77 is really "old", I´m not shure if this is changed in F95
For your information: Disabling implicit variable declarations simply removes Fortan's ability to make assumptions about what type your variables are.
Implicit variable declaration makes the following assumptions: Any variable beginning with (capital or lowercase): I, J, K, L, M, or N is to be INTEGER. Any variable beginning with any other letter (capital or lowercase) is to be REAL. This applies only to variables which do not have an explicit type declaration.
You could write:
program FOO
ijk
ifjkask
end
and ijk and ifjkask would be INTEGER values.
Related
I am new to Fortran and I am trying on the common block. My code is simple
program main
implicit double precision (p)
real * 8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end program main
function power(x)
implicit none
real * 8 :: power
real * 8 :: x, y
common /yvalue/ y
power = x ** y
end function power
It works but if I comment out the second line, which implicitly declares variables starting with p to be double precision, the compiler complains the following
Error: Return type mismatch of function ‘power’ at (1) (REAL(4)/REAL(8))
I do get the point that the return value power is by default a single precision variable, but why declaring power as double precision in the function is not enough? And why writing real * 8 power in main would not work either?
When a procedure (function or subroutine) that you are trying to invoke in your code lays outside the body of your program and also is not part of any module, it's named an external function (or subroutine).
Fortran is a statically-typed language, so the types of all variables and functions must be known at compile-time. So, if you want to reference an external function in your program, there must be a way for the program to know its return type. You have 3 (bad) options for this, and I'll list them, starting from the worst:
WORST: Rely on an implicit-typing rule that happens to match the return type of the external function with the type associated with its identifier in the caller (as you did in your sample).
Why you shouldn't do that? Because it is cancer. It makes the meaning of the code obscure, you can't know what this name reference to. It may even look just like an array variable in some circumstances, instead of a function. Also, the compiler doesn't check argument conformance in this case, so if you don't have specific compiler options turned on, the code will fail at runtime, or worse, will give wrong results. Moreover, implicit-typing is very very rarely useful these days, most of the time it's an ask for trouble. Always use implicit none!
As you noted, by the default rules of implicit-typing, any variable with a name starting with p will be default real type (in your compiler, it is real(4)). As you declared the function result as real*8, that your compiler interpret as real(8) (see final note), the error arises.
BAD: Declare the function's name and type in the caller's specification area.
You'd do that just like you'd declare a variable, like this:
program main
implicit none
real*8 :: x, y, power
By the way, the attribute external may be applied to external procedures like yours. More than giving some properties to the procedure (can be passed as an actual argument, disambiguation from intrinsic procedures), it would make the origin of the identifier clearer.
program main
implicit none
real*8 :: x, y, power
external :: power
Why you shouldn't do that? There is no argument checking by the compiler either. This severely limits your options for communicating to external functions: the arguments cannot be assumed-shape, assumed-rank, polymorphic, parameterized, coarray, or be declared on the callee side as allocatable, optional, pointer, target, asynchronous, volatile or value; the return type cannot be an array, or pointer, or allocatable; the function cannot be passed as argument, be elemental and, if pure, can't be used in such contexts. And the reason for all this is the lack of an explicit interface.
ACCEPTABLE: Specify an interface for your external function in the caller.
Like this:
program main
implicit none
interface
real*8 function power(y)
real*8 :: y
end function
end interface
This way, the compiler is able to know all details of declaration and all the restrictions I mentioned won't apply. Total freedom and code clarity!
Why you shouldn't do that? Because there is a better way, that is using modules! Well, it's totally ok to do this in contexts were you can't go for modules, e.g. when working with already existent large old code. The downside is that, you have almost the same code in two different places, and they must always match.
Bonus: BETTER: Use modules.
program main
use :: aux_module
implicit none
real*8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
contains
function power(x)
real*8 :: power
real*8 :: x, y
common /yvalue/ y
power = x ** y
end
end
Why you should definitely do that? Because with modules, interfaces are automatically and implicitly available (less code duplication, no restrictions); modules can be recompiled separately and updated without breaking code. Also, you can declare shared variables in the scope of the module and avoid using common declarations. An even better version of your code would be:
program main
use aux_module
implicit none
real*8 :: x
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
real*8 :: y
contains
function power(x)
real*8 :: power
real*8 :: x
power = x ** y
end
end
There is even the option to include your functions directly into your program, after contains. This is recommended only if you don't plan to reuse this function in other program units. #IanBush's answer covers this case.
Final note: take a look on this answer to see why the syntax real*8 is non-standard and should be avoided.
As stated in the comments simply declaring the function in not only its own scope but also the scope that it is called will solve your problem. However I also want to discourage you from using common, implicit typing, and the completely non-standard real*8. As such here is a version of your program in a more modern dialect
ian#eris:~/work/stackoverflow$ cat power.f90
Program power_program
Implicit None
Integer, Parameter :: wp = Selected_real_kind( 14, 70 )
Real( wp ) :: x, y
x = 3.0_wp
y = 3.0_wp
! Return type and kind of the function power in scope
! due to the implicit interface
Write( *, '( 3( a, 1x, f0.6, 1x ) )' ) &
'x =', x, 'y = ', y, 'x**y = ', power( x, y )
Contains
Pure Function power( x, y ) Result( r )
Real( wp ) :: r
Real( wp ), Intent( In ) :: x
Real( wp ), Intent( In ) :: y
r = x ** y
End Function power
End Program power_program
ian#eris:~/work/stackoverflow$ gfortran -std=f2003 -Wall -Wextra -O power.f90
ian#eris:~/work/stackoverflow$ ./a.out
x = 3.000000 y = 3.000000 x**y = 27.000000
ian#eris:~/work/stackoverflow$
Consider the variable
character*100 xx
I want to initialize it to some value, possibly some printable character or blanks. I tried
data xx /100*char(120)/
But that did not work.
Minimum working example:
cat car_array.F
character*10 xx
data xx /10*char(120)/
write(*,*)xx
end
ifort car_array.F
car_array.F(2): error #6169: This construct is not valid in this context. [CHAR]
data xx /10*char(120)/
--------------------^
compilation aborted for car_array.F (code 1)
making a bold assumption that you don't really need to be f77 standard compliant,
you should try:
character*10 :: xx=repeat(char(120),10)
in f77 you would have needed to make this a runtime assignment,
character*10 xx
integer i
do i=1,10
xx(i:i)=char(120)
end do
the only way i see to use a repeat count data statement to initialize a string in f77 is via equivalence with a length 1 character array, and here you can not use the char function
equivalence(x,y)
character*10 x
character*1 y(10)
data y/10*'a'/
write(*,*)x
aaaaaaaaaa
Very similar to agentp's post.
You can use the CHAR() function indirectly if you use it in a compile-time PARAMETER statement.
Old-timey, but this works on openVMS Fortran.
PARAMETER CHAR_120 = CHAR(120)
CHARACTER*1 X(10) /10*CHAR_120/
CHARACTER*10 XX
EQUIVALENCE (X, XX)
TYPE *,XX
If an integer is uneven (odd), I would like to get the previous number, otherwise I would like to keep the current number. E.g. if x = 3, I would like to assign 2 to x, if x = 4, then nothing happens.
At the moment, I do the following: x = (x/2)*2, but I have heard that division is computational expensive. Does -O3 optimize this expression? I am using the c++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4 compiler. x is a uint32_t.
Try the following
x &= ~1;
I suppose that x is declared as having type int. Otherwise if the rank of type x is greater than the rank of type int then you should use an integer literal of the type of the variable x.
Consider the following snippets:
C++:
#include <iostream>
using namespace std;
int main()
{
int x = 10, y = 20;
y = x + (x=y)*0;
cout << y;
return 0;
}
which gives a result of 20, because the value of y is assigned to x since the bracket is executed first according to the Operator Precedence Table.
VB.NET:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim x As Integer = 10
Dim y As Integer = 20
y = x + (x = y) * 0
MsgBox(y)
End Sub
which instead gives a result of 10.
What is the reason for this difference?
What is the order of execution of operators in VB.NET?
Unlike in C++, VB.NET's = is not always an assignment. It can also be the equality comparison operator (== in C++) if it appears inside an expression. Therefore your two expressions are not the same. They are not even equivalent. The VB.NET code does not do what you might think it does.
First to your C++ code: Like you're saying, the assignment x=y happens first; thus your code is roughly equivalent to this: (It seems that was incorrect; see Jens' answer.) Since you end up with y being 20, it is likely that your C++ compiler evaluated your code as if you had written this:
int x = 10, y = 20;
x = y;
y = x + x*0; // which is equivalent to `y = 20 + 20*0;`, or `y = 20 + 0;`, or `y = 20;`
In VB.NET however, because the = in your subexpression (x=y) is not actually interpreted as an assignment, but as a comparison, the code is equivalent to this:
Dim x As Integer = 10
Dim y As Integer = 20
y = 10 + False*0 ' which is equivalent to `y = 10 + 0*0`, or `y = 10` '
Here, operator precedence doesn't even come into play, but an implicit type conversion of the boolean value False to numeric 0.
(Just in case you were wondering: In VB.NET, assignment inside an expression is impossible. Assignments must always be full statements of their own, they cannot happen "inline". Otherwise it would be impossible to tell whether a = inside an expression meant assignment or comparison, since the same operator is used for both.)
Your C++ snippet is undefined behavior. There is no sequence point between using x as the first argument and assigning y to x, so the compiler can evaluate the sub-expressions in any order. Both
First evaluate the left side: y = 10 + (x=y) * 0 -> y = 10 + (x=20) * 0 -> y = 10 + 20*0
First evaluate the right side: y = x + (x=20) * 0 -> y = 20 + 20 * 0
It is also generally a very bad style to put assignments inside expressions.
This answer was intended as a comment, but its length quickly exceeded the limit. Sorry :)
You are confusing operator precedence with evaluation order. (This is a very common phenomenon, so don't feel bad). Let me try to explain with a simpler example involving more familiar operators:
If you have an expression like a + b * c then yes, the multiplication will always happen before the addition, because the * operator binds tighter than + operator. So far so good? The important point is that C++ is allowed to evaluate the operands a, b and c in any order it pleases. If one of those operands has a side effect which affects another operand, this is bad for two reasons:
It may cause undefined behavior (which in your code is indeed the case), and more importantly
It is guaranteed to give future readers of your code serious headaches. So please don't do it!
By the way, Java will always evaluate a first, then b, then c, "despite" the fact that multiplication happens before addition. The pseudo-bytecode will look like push a; push b; push c; mul; add;
(You did not ask about Java, but I wanted to mention Java to give an example where evaluating a is not only feasible, but guaranteed by the language specification. C# behaves the same way here.)
So I'm looking over C++ operator rules as I do when my programs start behaving wonkily. And I come across the comma operator. Now, I have known it was there for a while but never used it, so I began reading, and I come across this little gem:
if (int y = f(x), y > x)
{
// statements that use y
}
I had never thought about using commas' first arguments' side-effects to get locally-scoped variables without the need for bulky block-delimited code or repeated function calls. Naturally, this all excited me greatly, and I immediately ran off to try it.
test_comma.cpp: In function 'int main()':
test_comma.cpp:9:18: error: expected ')' before ',' token
if (int y = f(x), y > x) {
I tried this on both a C and C++ compiler, and neither of them liked it. I tried instead declaring y in the outer scope, and it compiled and ran just fine without the int in the if condition, but that defeats the purpose of the comma here. Is this just a GCC implementation quirk? The opinion of the Internet seems to be that this should be perfectly valid C (and ostensibly, to my eye, C++) code; there is no mention of this error on any GCC or C++ forum that I've seen.
EDIT: Some more information. I am using MinGW GCC 4.8.1-4 on Windows 7 64-bit (though obviously my binaries are 32-bit; I need to install mingw-w64 one of these days).
I also tried using this trick outside of a conditional statement, as below:
int y = (int z = 5, z);
This threw up two different errors:
test_comma.cpp: In function 'int main()':
test_comma.cpp:9:11: error: expected primary-expression before 'int'
int y = (int z = 5, z);
^
test_comma.cpp:9:11: error: expected ')' before 'int'
With creative use of parentheses in my if statement above, I managed to get the same errors there, too.
Contrary to what several other people have claimed, declarations inside the if conditional are perfectly valid. However, your code is not.
The first problem is that you're not actually using the comma operator, but [almost] attempting to declare multiple variables. That is not valid in an if conditional. And, even if it were possible, your second declaration would be entirely broken anyway since you try to redeclare y, and you do so with > instead of =. It all simply makes no sense.
The following code is sort of similar:
if (int y = (f(x), y > x))
Now at least it's half-valid, but you're using y uninitialised and yielding undefined behaviour.
Declarations and expressions are not the same thing, so the following is quite different code:
int y = 0;
if (y = f(x), y > x)
Now you don't have a problem with uninitialised variables, either (because I initialised y myself), and you're getting this "side-effect declaration" that doesn't change the resulting value of the if conditional. But it's about as clear as mud. Look how the precedence forms:
int y = 0;
if ((y = f(x)), (y > x))
That's not really very intuitive.
Hopefully this total catastrophe has been a lesson in avoiding this sort of cryptic code in entirety. :)
You cannot declare variable and apply operator , simultaneously either you are declaring variable (in case of if it would be only one 'cause result needs to be resolved to bool), either you are writing some statement (also resolving to bool) which may include operator , in it.
You need to declare y on the top of if condition:
int y;
if(y=f(x),y>x)
{
}
This will check the last condition defined in the if condition and rest others are executed as general statements.