If I do this below:
#include <stdio.h>
int main()
{
printf ("%s\n",__FILE__);
return 0;
}
>gcc cfilename.c
>./a.out
>cfilename.c
>pwd
>/home/tek/cpp
> gcc -v
> gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
only file name is printed, I think it should print it with complete path, google search tells me people asking help to get only file name?
The ISO C standard (currently C11) has this to say about the content of the __FILE__ predefined macro:
__FILE__: The presumed name of the current source file (a character string literal).
And that's about it. There is no mandate on the format of the content so I suspect a implementation could probably get away with setting it to "some file I found in the /src tree" and still claim conformance.
So it's basically up to the implementation as to what it puts in there. You'll need to investigate specific implementations to see how they handle it. The gcc compiler, for example, uses the file exactly as you specified on the command line so, if you want the full path, it's the command line you'll have to change, something like:
gcc -o myexec $(pwd)/myexec.c
It's interesting to note that gcc seems to do the opposite for included files. When you use:
#include "myheader.h"
the __FILE__ macro is set to the full expansion of the header file.
If you have an implementation that doesn't set __FILE__ in the manner you need, there's nothing stopping you from creating your own with something like:
dodgycc -o myexec -DMY_FILE_NAME=$(pwd)/myexec.c myexec.c
(where the -D option of the dodgycc compiler defines a preprocessor token to be what you need).
Related
I'm currently toying around with the C library NanoVG library. The library depends on OpenGL fucntions and has 2 header files nanovg.h and nanovg_gl.h. The latter file contains part of the implementation. For convenience, I have placed these two header files in /usr/include/nanovg.
When I try to compile the following code to an object file, gcc does not complain:
// working.c
#include <GL/gl.h>
#include <nanovg/nanovg.h>
#define NANOVG_GL3_IMPLEMENTATION
#include <nanovg/nanovg_gl.h>
(Command: gcc -c working.c -o working.o)
Now, I copy the header files from /usr/include/nanovg/ to the working directory, and replace the code with:
// notworking.c
#include <GL/gl.h>
#include "nanovg.h"
#define NANOVG_GL3_IMPLEMENTATION
#include "nanovg_gl.h"
(Command: gcc -c notworking.c -o notworking.o)
Gcc now complains that some OpenGL functions are not declared:
... (many more similar complaints)
src/nanovg_gl.h: In function ‘glnvg__renderDelete’:
src/nanovg_gl.h:1540:3: warning: implicit declaration of function ‘glDeleteBuffers’; did you mean ‘glSelectBuffer’? [-Wimplicit-function-declaration]
1540 | glDeleteBuffers(1, &gl->fragBuf);
| ^~~~~~~~~~~~~~~
...
Why does one file compile smoothly but not the other?
A bit deeper:
Using the cpp tool, I found that the difference between the two pre-processed files is limited to # directives but I don't see any difference as far as the "C content" goes. Below is a snippet of the pre-processed working.c. If I add the # lines from the pre-processed notworking.c, then gcc no longer compiles the pre-processed working.c and complains about a missing declaration for glDeleteBuffers.
// ...
if (gl ==
// # 1533 "src/nanovg_gl.h" 3 4 // <- uncomment this line and glDeleteBuffers is considered missing by gcc
((void *)0)
// # 1533 "src/nanovg_gl.h" // <- idem
) return;
glnvg__deleteShader(&gl->shader);
if (gl->fragBuf != 0)
glDeleteBuffers(1, &gl->fragBuf); // <- the function that gcc complains about is here
// ...
Edit: Just to make sure that I did not do anything sneaky that might have caused the difference, I followed the following steps which hopefully should be reproducible on another computer:
GCC version: gcc (Ubuntu 10.3.0-1ubuntu1) 10.3.0
Copy the version of GL/gl.h can be found here to working directory and call it glfoo.h
Copy the headers of nanovg (as found in the repo) to /usr/include/nanovg/ and nanovg/ (relative to working directory).
Save the following as test.c in the working dir:
#include "glfoo.h"
#include <nanovg/nanovg.h>
#define NANOVG_GL3_IMPLEMENTATION
#include <nanovg/nanovg_gl.h>
Run gcc -c test.c -o test.o => compilation works
Replace <...> with ".." on lines 2 and 4 and run command => compilation fails.
Just tried these exact steps and I was able to reproduce it.
After investigating this a bit I found the solution. gcc does not apply the same warning level to system headers as it does for "normal" files (this is mainly because system headers are sometimes doing weird things which are not backed up by the C standard, but are "safe" for the platform they are coming with).
The gcc documentation states (emphasis mine):
-Wsystem-headers:
Print warning messages for constructs found in system header files. Warnings from system headers are normally suppressed, on
the assumption that they usually do not indicate real problems and
would only make the compiler output harder to read. Using this
command-line option tells GCC to emit warnings from system headers as
if they occurred in user code. However, note that using -Wall in
conjunction with this option does not warn about unknown pragmas in
system headers—for that, -Wunknown-pragmas must also be used.
When you include nanovg via <...>, it is treated as a system header.
So doing gcc -Wsystem-headers working.c actually will bring on the warning.
Note that your code is neither working in working.c nor notworking.c, as working.c just hides the warning messages. The proper way to access any GL function beyond what is defined in GL 1.1 is to use the GL extension mechanism, which means you have to query the GL function pointers at run-time. Full GL loader libs like GLEW and glad can do that for you automatically. Many of these loaders (including GLEW and GLAD) work by re-#define-ing every GL function name to an internal function pointer, so when you include the header which comes with the loader, every GL function called in your code (and nanovg's) will be re-routed to the loader-libraries function pointers, and your code can actually work (provided you properly initialize the loader at run-time before any of the GL functions is called).
simply
#include <file.h>
include file from the path listed default to the compiler, while
#include "file.h"
include file from the current folder (where you are compiling).
As in your case , switching from <> to "" makes come files missing which makes that compiler error coming.
I have a header foo.h with functions bar(), baz(), qux(). Where would I copy it/what would I have to do it so that I can include it in C programs like other systemwide headers, like stdio.h, unistd.h etc?
From the GCC documentation (I am assuming you are using GCC since you included the Linux tag):
2.3 Search Path
GCC looks in several different places for headers. On a normal Unix system, if you do not instruct it otherwise, it will look for headers requested with #include in:
/usr/local/include
libdir/gcc/target/version/include
/usr/target/include
/usr/include
[...] In the above, target is the canonical name of the system GCC was configured to compile code for; often but not always the same as the canonical name of the system it runs on. version is the version of GCC in use.
So that mostly answers your question. But really, you probably shouldn't be putting non-system headers in places like /usr/include. Most of the time, it's best to keep the headers for your program in the include sub-directory for the project. Then tell GCC how to find those files like this:
You can add to this list with the -Idir command line option. All the directories named by -I are searched, in left-to-right order, before the default directories. The only exception is when dir is already searched by default. In this case, the option is ignored and the search order for system directories remains unchanged.
[...]
Also keep in mind the differences between #include "file.h" and #include <file.h>
GCC looks for headers requested with #include "file" first in the directory containing the current file, then in the directories as specified by -iquote options, then in the same places it would have looked for a header requested with angle brackets. For example, if /usr/include/sys/stat.h contains #include "types.h", GCC looks for types.h first in /usr/include/sys, then in its usual search path.
[...]
Can I make a custom header file named stdio.h and can use it in my program along with <stdio.h>?
C11 7.1.2p3:
If a file with the same name as one of the above < and > delimited sequences, not provided as part of the implementation, is placed in any of the standard places that are searched for included source files, the behavior is undefined.
The standard places then refers to 6.10.2p2:
searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.
So the only guarantee given here is that if your stdio.h is not in an implementation-defined place for a searching a header, then the behaviour wouldn't be undefined. You can then include it with
#include "stdio.h"
However if you really intended that the file would be included with
#include <stdio.h>
then for the compiler to find it you need to place it in any of the standard places, and all bets are off.
However, in a freestanding - i.e. not hosted - execution environment. stdio.h might not be a standard header name so it might as well be perfectly OK there. Not that there is anything portable about the freestanding execution environment.
Thus, unless you specify more specifically what you're up to, we can only refer to the C standard and shrug. Having a source file named stdio.h isn't strictly conforming but it very much might be conforming, so YMMV.
As noted by Antti Haapala, it is explicitly described as undefined behavior to name a file stdio.h and put it in any of the directories where the compiler looks for include files.
Yet, by default, the compiler does not search for standard headers in the directory of the source file, but a command line argument of -I. can easily change this behavior.
Without this option and assuming you do not put your source files in the compiler's system directories, you could use the name stdio.h for an include file and include that with #include "stdio.h" without interfering with the standard header referred to in #include <stdio.h> (which might not even be a file at all).
You could go one step further into confusion-land by naming the source file itself stdio.h...
I you truly want to confuse the reader, name the source file a.out and compile with gcc -o stdio.h -x c a.out.
If you specify where in your file directory your custom "stdio.h" comes from (i.e. doing
#include "C:/ProgrammingC/stdio.h"
is probably fine, but
#include "stdio.h" //This only selects the standard include
//if there's no other stdio.h in the build directory
is risky, and
#include <stdio.h>
is definitely not what you want.
I've created a file named as stdio.h and main.c afterwards added this content to main.c to test out if it works properly.
#include "stdio.h"
#include <stdio.h>
int main()
{
testArea(); // this will use "stdio.h"
int test = 2;
printf("%d", test); // this will use <stdio.h>
return 0;
}
Program output:
1002 (100 from "stdio.h" and 2 from <stdio.h>)
Content of my stdio.h:
#include <stdio.h>
void testArea()
{
int abc = 100;
printf("%d", abc);
}
Surprise surprise, it does! Now, you should know that using "" means searching header file via file path. Meanwhile <> basically looks at the includes folder of the compiler.
So that, you can do that.
PS: If you're going to downvote, make an explanation so that I can learn what's wrong too. It just works fine for me.
Edit: Now, you can see that program knows what to call and what to do.
Bonus: If you try to add a same name function that exists in the file compiler will give you an error.
#include <stdio.h>
void testArea()
{
int abc = 100;
printf("%d", abc);
}
void printf()
{
}
Will return stdio.h:9:7: error: conflicting types for ‘printf’ as an example. You just should avoid using existing functions, but it's not restricted to same name header files. You just can't do it with any filename since the names are going to conflict.
Again, the usage of this is fine. There should be no problems at all.
Edit 2: I'm using Linux Mint 18.2.
Here is my gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
And, here is how I compile my code:
duman#duman-pc ~/Desktop/Nuclear Test Zone $ gcc main.c -o test
duman#duman-pc ~/Desktop/Nuclear Test Zone $ ./test
Nothing fancy, and I don't really know what can cause undefined behaviour since my compiler won't allow usage of same name functions.
Edit 3: Just to see if anything related to name usage throws a warning I compiled the same code with ALL of these flags: https://stackoverflow.com/a/34971392/7735711 and there were none about the names.
That's the best I can do. Hopefully it helps you.
Inspired by this PCG challange: https://codegolf.stackexchange.com/q/61836/31033
I asked my self, if one would try to leave as few trace as possible when compiling such kind of tool (no matter of a browser or something else), is there some way (aimed for gcc/clang as this probably are the preinstalled commandline compillers in such a working enviroment) to hand over source code to the compiler as command line argument or equal mechanism, without need for the source code beeing saved as *.c file, as the user would usually do?
(ofcourse the compiler will produce temp files while compiling, but those probably won't get scanned.)
At least gcc can as it is able to read source from the standard input. You can also use Unix here string bash construction :
gcc -xc - << "int main() { exit(0); }"
or here file sh construction :
gcc -xc - <<MARK
int main() {
exit(0);
}
MARK
----EDIT----
You can also imagine using cryptography to encode your source, uncipher the content on the fly and inject the result to the standard input of gcc, something like:
uncipher myfile.protected | gcc -xc -
I compile an example.c file that has the line:
#include "parse/properties/properties.h"
The compiler creates get an example.o file. Is the path to the header file included in the example.o file? or is that information external?
It may or may not, the object file format is not standardised (the standard does not even mention "object files"). A compiler might insert the #include for debugging purposes, or it may skip it completely.
Note also that #include'ing is done by the compiler in what the standard desrcibes as the first phase in translation, using a textual preprocessor; the #include-directive tells the preprocessor to copy verbatim and inplace the contents of another file. This happens long before actual object files would be produced
It is implementation defined but generally when you compile with debugging options ( eg -g in gcc ) the file paths are included to aid you in debugging