In C, what happen if define a variable with undefined thing? - c

I have an example code like this:
int var;
var = MACRO_A;
I expect the MACRO_A has been defined like this:
#define MACRO_A 1234
However, I can not find the MACRO_A defined anywhere in the source code, but I can build the code successfully, so what is the value of var at the end ?
The compiler is gcc.

However, I can not find the MACRO_A defined anywhere in the source
code, but I can build the code successfully, so what is the value of
var at the end
It's there somewhere or it wouldn't compile. Perhaps it's defined directly on the command line ? (-DMACRO_A)

That macro could have been passed during compilation with -D option.
#include <stdio.h>
int main()
{
int i = MACRO_A;
printf("MACRO_A : %d \n", i);
return 0;
}
Output:
$ gcc macro.c -D MACRO_A=10
$ ./a.out
MACRO_A : 10
$

Related

Expanding a dynamic macro inside printf function

I want to compile a c program under different names. In the main file, I have the following macro:
#ifndef EXECUTABLE_NAME
#define EXECUTABLE_NAME "defaultname"
#endif
When compiling using gcc, I use -D switch to define this macro (is that the right term?):
$ gcc main.c -DEXECUTABLE_NAME="newname"
I do not know if the -D works fine or not because when I try to do something like the code below...it fails...I can not tell if the -D switch is screwing up or the syntax of using the macro inside the printf() function is not correct:
printf("no or invalid arguments. usage: %s [0,255]\n", EXECUTABLE_NAME);
I get this error:
main.c:48:57: note: in expansion of macro ‘EXECUTABLE_NAME’
printf("no or invalid arguments. usage: %s [0,255]\n", EXECUTABLE_NAME);
Any suggestions?
It works, and you can see that because of the error. Which by the way is because you're defining your macro wrong on the command line, this is how you quote a string in a macro:
$ gcc main.c -DEXECUTABLE_NAME='"newname"'
And this said, it's not even needed. The executable path is always your first argument: *argv.
I tried this program with an integer, which is as follows
#ifndef EXECUTABLE_NAME
#define EXECUTABLE_NAME 2
#endif
int main()
{
printf("%d",EXECUTABLE_NAME);
}
and then typed gcc main.c -DEXECUTABLE_NAME=1 and it works as the value changes to 1. Is it a problem with the data type 'string' that you are using?

Undefined function sensing

I am trying to do this (is this possible?) with GCC compiler:
Specifiy a function but this function if is not implemented point to a NULL. Example:
extern void something(uint some);
And if this is unimplemented point to a NULL value.
So it's possible check like this:
something != NULL ? something(222) : etc.;
I would like solution with trough GCC (this could be solvable with function pointers).
This is definitely not portable, but gcc can do this with weak symbols on some platforms. I know this works on Linux and *BSD, but doesn't work on MacOS.
$ cat weak.c
#include <stdio.h>
extern int foo(void) __attribute__((__weak__));
int
main(int argc, char **argv)
{
int x = foo ? foo() : 42;
printf("%d\n", x);
return 0;
}
$ cat weak2.c
int
foo(void)
{
return 17;
}
$ cc -o weak weak.c && ./weak
42
$ cc -o weak weak.c weak2.c && ./weak
17
$
You can do this using GCC's weakref attribute:
extern void something(int);
static void something_else(int) __attribute__((weakref("something")));
int main()
{
if (something_else)
something_else(122);
}
If something is not defined in the program then the weak alias something_else will have an address of zero. If something is defined, something_else will be an alias for it.
Essentially you are trying to get the compiler to locate a function at the memory address 0 (NULL). This cannot be done in C without platform/compiler specific constructs.
One question though, is why you would ever want to do this. C is a static language, so if you know that the function will never exist during compilation you might as well just use the pre-processor to tell the rest of the program about this at compile time. Indeed these sorts of compile time substitutions are precisely why the preprocessor is there in the first place.
I would create a macro that you define if your function exists as follows:
#define THE_SOMETHING_FUNCTION_EXISTS
Then replace anywhere you would have tested for something == NULL with an #ifdef instead.
Of course, if the function’s existence might change at run-time then the correct way to implement the behaviour you want is to make something a function pointer.

Why can't I read a C constant from Golang properly?

I am using go-hdf5 to read an hdf5 file into golang. I am on windows7 using a pretty recent copy of mingw and hdf5 1.8.14_x86 and it seems like trying to use any of the predefined types doesn't work, let's focus for example on T_NATIVE_UINT64. I have reduced the issue to the following, which basically leaves go-hdf5 out of the problem and points at something quite fundamental going wrong:
package main
/*
#cgo CFLAGS: -IC:/HDF_Group/HDF5/1.8.14_x86/include
#cgo LDFLAGS: -LC:/HDF_Group/HDF5/1.8.14_x86/bin -lhdf5 -lhdf5_hl
#include "hdf5.h"
#include <stdio.h>
void print_the_value2() { printf("the value of the constant is %d\n", H5T_NATIVE_UINT64); }
*/
import "C"
func main() {
C.print_the_value2()
}
You obviously need to have hdf5 and point the compiler at the headers/dlls and running go get, then executing prints this on my pc
the value of the constant is -1962924545
Running variations of the above, in how/where the constant is read, will give different answers for the value of H5T_NATIVE_UINT64. However I am pretty sure that is none are the right value and in fact trying to use a type with the id returned doesn't work, unsurprisingly.
If I write and run a "real" C program, I get different results
#include <stdio.h>
#include "hdf5.h"
hid_t _go_hdf5_H5T_NATIVE_UINT64() { return H5T_NATIVE_UINT64; }
int main()
{
printf("the value of the constant is %d", _go_hdf5_H5T_NATIVE_UINT64());
}
Compiling using
C:\Temp>gcc -IC:/HDF_Group/HDF5/1.8.14_x86/include -LC:/HDF_Group/HDF5/1.8.14_x86/bin -lhdf5 -lhdf5_hl -o stuff.exe stuff.c
and running gives me
the value of the constant is 50331683
And that appears to be the right value as I can use it directly from my go program. Obviously I want to be able to use the constants instead. Any idea why this could be happening?
Extra info following comments below:
I looked for the definition of H5T_NATIVE_UINT64 in the hdf5 headers and see the following
c:\HDF_Group\HDF5\1.8.14_x86\include>grep H5T_NATIVE_UINT64 *
H5Tpkg.h:H5_DLLVAR size_t H5T_NATIVE_UINT64_ALIGN_g;
H5Tpublic.h:#define H5T_NATIVE_UINT64 (H5OPEN H5T_NATIVE_UINT64_g)
H5Tpublic.h:H5_DLLVAR hid_t H5T_NATIVE_UINT64_g;
The whole header is here
http://www.hdfgroup.org/ftp/HDF5/prev-releases/hdf5-1.8.14/src/unpacked/src/H5Tpublic.h
Thanks!
H5T_NATIVE_UINT64 is NOT a constant but a #define that ultimately evaluates to (H5Open(), H5T_NATIVE_UINT64_g), which cgo does not understand.
It's easy to check by turning on debug output on gcc's preprocessor:
gcc -E -dM your_test_c_file.c | grep H5T_NATIVE_UINT64
Result:
#define H5T_NATIVE_UINT64 (H5OPEN H5T_NATIVE_UINT64_g)
Now the same for H5OPEN:
gcc -E -dM test_go.c | grep '#define H5OPEN'
gives:
#define H5OPEN H5open(),
Right now, cgo does understand simple integer constant defines like #define VALUE 1234, or anything that the gcc preprocessor will turn into an integer constant. See the function func (p *Package) guessKinds(f *File) in $GOROOT/src/cmd/cgo/gcc.go.

Replace #define X macro value with another one specified in compilation command

Given the following code:
#include <stdio.h>
#ifndef STR
#define STR "HELLO"
#endif
int main() {
printf(STR "WORLD \n");
return 0;
}
which says: if STR was not defined, then define it to be "HELLO",
so the output will be
HELLO WORLD
How can I modify the value of STR when compiling using gcc?
I've tried
gcc -Wall program.c -DSTR="HI" -o program
but it didn't produce the expected output.
Try in the form of:
-DSTR=\"MyString\"

Print all defined macros

I'm attempting to refactor a piece of legacy code and I'd like a snapshot of all of the macros defined at a certain point in the source. The code imports a ridiculous number of headers etc. and it's a bit tedious to track them down by hand.
Something like
#define FOO 1
int myFunc(...) {
PRINT_ALL_DEFINED_THINGS(stderr)
/* ... */
}
Expected somewhere in the output
MACRO: "FOO" value 1
I'm using gcc but have access to other compilers if they are easier to accomplish this task.
EDIT:
The linked question does not give me the correct output for this:
#include <stdio.h>
#define FOO 1
int main(void) {
printf("%d\n", FOO);
}
#define FOO 0
This very clearly prints 1 when run, but gcc test.c -E -dM | grep FOO gives me 0
To dump all defines you can run:
gcc -dM -E file.c
Check GCC dump preprocessor defines
All defines that it will dump will be the value defined (or last redefined), you won't be able to dump the define value in all those portions of code.
You can also append the option "-Wunused-macro" to warn when macros have been redefined.

Resources