I'm writing a program which converts CIL bytecode to C source code for machine consumption. I was concerned about inaccuracy in floating-point constants due to conversion to and from decimal. After doing some research, I discovered that C (but not C++) is supposed to be able to accept a hexadecimal notation for floating-point constants.
I decided to try it out, but MS VC9 gives me errors no matter what I try. Here is what I'm trying:
// Switches: /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FD /MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb" /W3 /nologo /c /ZI /TC
#include <tchar.h>
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
double d = 0x1.0p+1; // error C2059
//double d = 0x1p+1; // doesn't work either
//double d = 0x1p1; // doesn't work either
//double d = 0x1.0p1; // doesn't work either
printf( "%f\n", d );
return 0;
}
I expected this to print out 2, from 1x2^1, but instead it gives me this compiler error:
error C2059: syntax error : 'bad suffix on number'
I realize C++ doesn't support this syntax (or so I've read,) but notice this is compiled with /TC so it should be straight C, and I used a *.c filename for good measure also.
Am I doing something wrong here, or is VC9 just not standards compliant?
There's nothing wrong with your code. Floating-point hexadecimal constants were added to C in the C99 standard, but MSVC only supports the older C90 standard (with some extensions, like // single-line comments and the long long type).
C++17 standard added full support of C99 hexadecimal floating-point literals. Visual C++ will have them available in Visual Studio 2017 15.6 release.
Related
Today I read this question Any rules about underscores in filenames in C/C++?,
and I found it very interesting that the standard seems to not allow what is usually seen in many libraries (I also do it in my personal library this way):
For example, in opencv we can see this:
// File: opencv/include/opencv2/opencv.hpp
#include "opencv2/opencv_modules.hpp"
But the standard says:
ยง 6.10.2 Source file inclusion
Semantics
5 The implementation shall provide unique mappings for sequences
consisting of one or more nondigits or digits (6.4.2.1) followed by a
period (.) and a single nondigit. The first character shall not be
a digit. The implementation may ignore distinctions of alphabetical
case and restrict the mapping to eight significant characters before
the period.
nondigit means letters (A-Z a-z) and underscore _.
It says absolutely nothing about / which would imply that it is forbidden to use a path, not to mention dots or hyphens in file names.
To test this first, I wrote a simple program with a source file test.c and a header file _1.2-3~a.hh in the same directory tst/:
// File: test.c
#include "./..//tst//./_1.2-3~a.hh"
int main(void)
{
char a [10] = "abcdefghi";
char b [5] = "qwert";
strncpy(b, a, 5 - 1);
printf("b: \"%c%c%c%c%c\"\n", b[0], b[1], b[2], b[3], b[4]);
/* printed: b: "abcdt" */
b[5 - 1] = '\0';
printf("b: \"%c%c%c%c%c\"\n", b[0], b[1], b[2], b[3], b[4]);
/* printed: b: "abcd" */
return 0;
}
// File: _1.2-3~a.hh
#include <stdio.h>
#include <string.h>
Which I compiled with this options: $ gcc -std=c11 -pedantic-errors test.c -o tst with no complain from the compiler (I have gcc (Debian 8.2.0-8) 8.2.0).
Is it really forbidden to use a relative path in an include?
Ah; the standard is really talking about the minimum character set of the filesystem supporting the C compiler.
Anything in the "" (or <> with some preprocessing first) is parsed as a string according to normal C rules and passed from there to the OS to do whatever it wants with it.
This leads to compiler errors on Windows when the programmer forgets to type \\ instead of '\' when writing a path into the header files. On modern Windows we can just use '/' and expect it to work but on older Windows or DOS it didn't.
For extra fun, try
#include "/dev/tty"
Really nice one. It wants you to type C code while compiling.
I'd would say it's not forbidden but not recommanded since it will not compile in some of cases there.
For example:
if you clone this directory into your root (so you'd have C:\test\).
if you try to run it in a virtual environment online, you may face issues.
Is it really forbidden to use a path in an include?
Not sure what you mean here: relative paths are commonly used, but using absolute path would be foolish.
i'm trying to compile a program for image deblurring.
I try to run
mex apply_blur_kernel_mex.c
where the file apply_blur_kernel_mex.c have the following code
#include <mex.h>
#include <stdlib.h>
#include <math.h>
#include <matrix.h>
#include "ow_homography.h"
...
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
...
compute_homography_matrix(Ksharp, &theta_list[k*3], invKblurry, H);
...
}
The problem is in the function compute_homography_matrix that is in another file ow_homography.h
#ifndef OW_HOMOGRAPHY_H
#define OW_HOMOGRAPHY_H
#include "ow_mat3.h"
INLINE void compute_homography_matrix(const double *Ksharp, const double *theta, const double *invKblurry, double *H) {
double R[9];
/* Compute homography */
cp3(invKblurry,H);
rot3(theta[0],theta[1],theta[2],R);
mmip3(R,H);
mmip3(Ksharp,H);
}
This last operations (cp3, rot3...) are in another file ow_mat3.h that contains all the operations for the program.
So when i try to call
mex apply_blur_kernel_mex.c
i have the following problem:
Error using mex
Undefined symbols for architecture x86_64:
"_compute_homography_matrix", referenced from:
mexFunction in apply_blur_kernel_mex.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Any suggestions to solve this problem?
Thank you all.
http://clang.llvm.org/compatibility.html#inline
C compatibility C99 inline functions
By default, Clang builds C code in GNU C11 mode, so it uses standard
C99 semantics for the inline keyword. These semantics are different
from those in GNU C89 mode, which is the default mode in versions of
GCC prior to 5.0. For example, consider the following code:
inline int add(int i, int j) { return i + j; }
int main() { int i = add(4, 5); return i; }
In C99, inline means that a function's definition is provided only for
inlining, and that there is another definition (without inline)
somewhere else in the program. That means that this program is
incomplete, because if add isn't inlined (for example, when compiling
without optimization), then main will have an unresolved reference to
that other definition. Therefore we'll get a (correct) link-time error
like this:
Undefined symbols: "_add", referenced from:
_main in cc-y1jXIr.o
By contrast, GNU C89 mode (used by default in older versions of GCC)
is the C89 standard plus a lot of extensions. C89 doesn't have an
inline keyword, but GCC recognizes it as an extension and just treats
it as a hint to the optimizer.
There are several ways to fix this problem:
1) Change add to a static inline function. This is usually the right solution if only one translation unit needs to use the function.
static inline functions are always resolved within the translation
unit, so you won't have to add a non-inline definition of the function
elsewhere in your program.
2) Remove the inline keyword from this definition of add. The inline keyword is not required for a function to be inlined, nor does it
guarantee that it will be. Some compilers ignore it completely. Clang
treats it as a mild suggestion from the programmer.
3) Provide an external (non-inline) definition of add somewhere else in your program. The two definitions must be equivalent!
4)Compile in the GNU C89 dialect by adding -std=gnu89 to the set of Clang options. This option is only recommended if the program source
cannot be changed or if the program also relies on additional
C89-specific behavior that cannot be changed.
All of this only applies to C code; the meaning of inline in C++ is
very different from its meaning in either GNU89 or C99.
I have an algorithm coded in MATLAB, which contains complex arc cos of some value (computation requires arccos of 15, which is approximately 3.4i). I want to code C or C++ counterpart of this code running on my Windows 7 PC. Actually, I want to produce it as a mex function compiled with Visual Studio C++.
I included "complex.h" and used cacosf function (complex arccos returning float _Complex) but I could not compile it as a mex function because Visual C++ compiler does not have "complex.h" support. However, mex file can take libraries as input, so I can compile my c code with another compiler that MATLAB does support (for example mingw, I integrated it to matlab with gnumex utility.) I downloaded Bloodshed C++ IDE which uses mingw at backend, I can compile my c++ code. The following C++ code represents a similar operation to my goal:
#include <stdio.h>
#include <complex.h>
int main() {
float _Complex myComplex;
myComplex = cacosf(5);
printf("Complex number result of acos(5) is : %f + %fi \r\n",crealf(myComplex),cimagf(myComplex));
return 0;
}
The output should be:
Complex number result of acos(5) is : 0.000000 + -2.292432i
However I get
Complex number result of acos(5) is : -1.#IND00, -0.000000
When I compile my C++ code with Linux GCC on Ubuntu 14.04 computer with Eclipse CDT Luna I get
The output should be:
Complex number result of acos(5) is : 0.000000 + -2.292432i
Where can I be wrong? Why can't I compile this code in Windows + mingw setup?
Note: I can compute cacosf(0) as 1.570796 + -0.000000 when I use mingw.
What version of mingwrt are you using? With mingwrt-3.21.1, the following works for me, (cross-compiling on a Linux host, and running under wine):
$ cat foo.c
#include <stdio.h>
#include <complex.h>
int main()
{
double _Complex Z = cacos(5.0);
printf( "arcos(5) = (%g, %gi)\n", __real__ Z, __imag__ Z );
return 0;
}
$ mingw32-gcc -o foo.exe foo.c
$ ./foo.exe
arcos(5) = (0, -2.29243i)
This seems to be consistent with your expected result. However, if you use any mingwrt version pre-dating mingwrt-3.21, (and the less said about utterly broken mingwrt-4.x the better), then there is a known bug resulting from arbitrarily deeming any purely real cacos() argument value greater than (1.0, 0.0i) to be outside the valid domain, (as would be the case for acos() on its real part), which would yield the result you report.
Visual C++, as the name says, is a C++ compiler. C++ uses the <complex> header and std::complex<float> type. Since C++ has overloading, you can call std::acos for complex values too.
Your code is in fact C, which is no longer supported by MSVC++. (They stopped doing that back in 1996 or so)
This is a program I wrote :
#include "stdafx.h"
#include "math.h"
int main ()
{
int phi;
float c;
scanf_s("%d",&phi);
c=(pow(sin(phi)*cos(phi),-2))-(pow(tan(phi),2)+pow(tan(phi),-2));
if (c==2)
{
printf("C is 2,Don't Worry \n");
}
else
{
printf("Be Careful,C is not 2,How is this possible ?! \n");
}
}
The problem is Visual Studio won't recognize sin,cos,tan and pow.
what am I doing wrong ?
(as you see, the language is C!)
Despite that you haven't pointed out error message, most probable answer is that you need to explicitely tell your compiler, that you want to treat your code as C source file instead of C++ one. Visual Studio does not have project template for C console application "as is", but you may add source file manually. Just make sure that it has .c extension instead of .cpp.
I'm assuming you are actually compiling this as a C++ file as it should compile fine as a C file. You didn't specify the exact error message but in VS 2010 I get the error:
error C2668: 'sin' : ambiguous call to overloaded function
This is because your argument phi is an int and the compiler doesn't know which version of sin() to use. You can fix this by casting the integer to the desired type like:
int phi;
c = sin((float) phi);
or, simply change the type of phi to a float or a double.
I'm using a fairly new install of Visual C++ 2008 Express.
I'm trying to compile a program that uses the log2 function, which was found by including using Eclipse on a Mac, but this Windows computer can't find the function (error C3861: 'log2': identifier not found).
The way I understood it, include directories are specific to the IDE, right? math.h is not present in my Microsoft SDKs\Windows\v6.0A\Include\ directory, but I did find a math.h in this directory: Microsoft Visual Studio 9.0\VC\include. There is also a cmath in that directory...
Where is log2?
From here:
Prototype: double log2(double anumber);
Header File: math.h (C) or cmath (C++)
Alternatively emulate it like here
#include <math.h>
...
// Calculates log2 of number.
double Log2( double n )
{
// log(n)/log(2) is log2.
return log( n ) / log( 2 );
}
Unfortunately Microsoft does not provide it.
log2() is only defined in the C99 standard, not the C90 standard. Microsoft Visual C++ is not fully C99 compliant (heck, there isn't a single fully C99 compliant compiler in existence, I believe -- not even GCC fully supports it), so it's not required to provide log2().
If you're trying to find the log2 of strictly integers, some bitwise can't hurt:
#include <stdio.h>
unsigned int log2( unsigned int x )
{
unsigned int ans = 0 ;
while( x>>=1 ) ans++;
return ans ;
}
int main()
{
// log(7) = 2 here, log(8)=3.
//for( int i = 0 ; i < 32 ; i++ )
// printf( "log_2( %d ) = %d\n", i, log2( i ) ) ;
for( unsigned int i = 1 ; i <= (1<<30) ; i <<= 1 )
printf( "log_2( %d ) = %d\n", i, log2( i ) ) ;
}
With Visual Studio 2013, log2() was added. See C99 library support in Visual Studio 2013.
Note that:
log2(x) = log(x) * log(e)
where log(e) is a constant. math.h defines M_LOG2E to the value of log(e) if you define _USE_MATH_DEFINES before inclusion of math.h:
#define _USE_MATH_DEFINES // needed to have definition of M_LOG2E
#include <math.h>
static inline double log2(double n)
{
return log(n) * M_LOG2E;
}
Even though usual approach is to do log(n)/log(2), I would advise to use multiplication instead as division is always slower especially for floats and more so on mobile CPUs. For example, on modern Intel CPUs the difference in generated code in just one instruction mulsd vs divsd and according to Intel manuals we could expect the division to be 5-10 times slower. On mobile ARM cpus I would expect floating point division to be somewhere 10-100 slower than multiplication.
Also, in case if you have compilation issues with log2 for Android, seems like log2 is available in headers starting from android-18:
#include <android/api-level.h>
#if __ANDROID_API__ < 18
static inline double log2(double n)
{
return log(n) * M_LOG2E;
}
#endif