uses undefined struct compile error - C - c

The compiler doesn't know where stat.h is?
Error:
c:\Projects\ADC_HCI\mongoose.c(745) : error C2079: 'st' uses undefined struct '_stat64'
#include <sys/types.h>
#include <sys/stat.h>
static int
mg_stat(const char *path, struct mgstat *stp)
{
struct _stat64 st; //<-- ERROR
int ok;
wchar_t wbuf[FILENAME_MAX];
to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
if (_wstat64(wbuf, &st) == 0) {
ok = 0;
stp->size = st.st_size;
stp->mtime = st.st_mtime;
stp->is_directory = S_ISDIR(st.st_mode);
} else {
ok = -1;
}
return (ok);
}
...downloaded the files straight from the source.

See MSDN: _wstat64 takes a parameter of struct __stat64 (with two underscores). Redeclare your variable st to be of type struct __stat64.

Note that neither _stat64 nor __stat64 is 'standard' in the sense of documented by any standard, such as POSIX. You would normally use struct stat; if you are worried about whether that will work with big files (over 2 GiB), then check what compilation options are required on your platform to obtain 'large file support'. For 64-bit machines and 64-bit compilations (not necessarily Windows 64), you usually don't need to worry. You can often obtain large file support using:
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
These are at least semi-standardized. Systems such as autoconf detect these things automatically (if you ask them to do so).

Change the _stat64 to stat64. At least in my Linux machines that's the name of the structure. I don't know if it is different in Windows.

I suggest you to sync to SVN trunk.
If you don't have SVN client, simply download two files:
http://mongoose.googlecode.com/svn/trunk/mongoose.h (and .c file too)
The reason is that recently the code was refactored, and CRT _stat function was substituted
with WinAPI one, GetFileAttributesExW().

Related

Get program's directory on windows [duplicate]

Is there a platform-agnostic and filesystem-agnostic method to obtain the full path of the directory from where a program is running using C/C++? Not to be confused with the current working directory. (Please don't suggest libraries unless they're standard ones like clib or STL.)
(If there's no platform/filesystem-agnostic method, suggestions that work in Windows and Linux for specific filesystems are welcome too.)
Here's code to get the full path to the executing app:
Variable declarations:
char pBuf[256];
size_t len = sizeof(pBuf);
Windows:
int bytes = GetModuleFileName(NULL, pBuf, len);
return bytes ? bytes : -1;
Linux:
int bytes = MIN(readlink("/proc/self/exe", pBuf, len), len - 1);
if(bytes >= 0)
pBuf[bytes] = '\0';
return bytes;
If you fetch the current directory when your program first starts, then you effectively have the directory your program was started from. Store the value in a variable and refer to it later in your program. This is distinct from the directory that holds the current executable program file. It isn't necessarily the same directory; if someone runs the program from a command prompt, then the program is being run from the command prompt's current working directory even though the program file lives elsewhere.
getcwd is a POSIX function and supported out of the box by all POSIX compliant platforms. You would not have to do anything special (apart from incliding the right headers unistd.h on Unix and direct.h on windows).
Since you are creating a C program it will link with the default c run time library which is linked to by ALL processes in the system (specially crafted exceptions avoided) and it will include this function by default. The CRT is never considered an external library because that provides the basic standard compliant interface to the OS.
On windows getcwd function has been deprecated in favour of _getcwd. I think you could use it in this fashion.
#include <stdio.h> /* defines FILENAME_MAX */
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
{
return errno;
}
cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */
printf ("The current working directory is %s", cCurrentPath);
This is from the cplusplus forum
On windows:
#include <string>
#include <windows.h>
std::string getexepath()
{
char result[ MAX_PATH ];
return std::string( result, GetModuleFileName( NULL, result, MAX_PATH ) );
}
On Linux:
#include <string>
#include <limits.h>
#include <unistd.h>
std::string getexepath()
{
char result[ PATH_MAX ];
ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
return std::string( result, (count > 0) ? count : 0 );
}
On HP-UX:
#include <string>
#include <limits.h>
#define _PSTAT64
#include <sys/pstat.h>
#include <sys/types.h>
#include <unistd.h>
std::string getexepath()
{
char result[ PATH_MAX ];
struct pst_status ps;
if (pstat_getproc( &ps, sizeof( ps ), 0, getpid() ) < 0)
return std::string();
if (pstat_getpathname( result, PATH_MAX, &ps.pst_fid_text ) < 0)
return std::string();
return std::string( result );
}
If you want a standard way without libraries: No. The whole concept of a directory is not included in the standard.
If you agree that some (portable) dependency on a near-standard lib is okay: Use Boost's filesystem library and ask for the initial_path().
IMHO that's as close as you can get, with good karma (Boost is a well-established high quality set of libraries)
I know it is very late at the day to throw an answer at this one but I found that none of the answers were as useful to me as my own solution. A very simple way to get the path from your CWD to your bin folder is like this:
int main(int argc, char* argv[])
{
std::string argv_str(argv[0]);
std::string base = argv_str.substr(0, argv_str.find_last_of("/"));
}
You can now just use this as a base for your relative path. So for example I have this directory structure:
main
----> test
----> src
----> bin
and I want to compile my source code to bin and write a log to test I can just add this line to my code.
std::string pathToWrite = base + "/../test/test.log";
I have tried this approach on Linux using full path, alias etc. and it works just fine.
NOTE:
If you are on windows you should use a '\' as the file separator not '/'. You will have to escape this too for example:
std::string base = argv[0].substr(0, argv[0].find_last_of("\\"));
I think this should work but haven't tested, so comment would be appreciated if it works or a fix if not.
Filesystem TS is now a standard ( and supported by gcc 5.3+ and clang 3.9+ ), so you can use current_path() function from it:
std::string path = std::experimental::filesystem::current_path();
In gcc (5.3+) to include Filesystem you need to use:
#include <experimental/filesystem>
and link your code with -lstdc++fs flag.
If you want to use Filesystem with Microsoft Visual Studio, then read this.
No, there's no standard way. I believe that the C/C++ standards don't even consider the existence of directories (or other file system organizations).
On Windows the GetModuleFileName() will return the full path to the executable file of the current process when the hModule parameter is set to NULL. I can't help with Linux.
Also you should clarify whether you want the current directory or the directory that the program image/executable resides. As it stands your question is a little ambiguous on this point.
On Windows the simplest way is to use the _get_pgmptr function in stdlib.h to get a pointer to a string which represents the absolute path to the executable, including the executables name.
char* path;
_get_pgmptr(&path);
printf(path); // Example output: C:/Projects/Hello/World.exe
Maybe concatenate the current working directory with argv[0]? I'm not sure if that would work in Windows but it works in linux.
For example:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char **argv) {
char the_path[256];
getcwd(the_path, 255);
strcat(the_path, "/");
strcat(the_path, argv[0]);
printf("%s\n", the_path);
return 0;
}
When run, it outputs:
jeremy#jeremy-desktop:~/Desktop$ ./test
/home/jeremy/Desktop/./test
For Win32 GetCurrentDirectory should do the trick.
You can not use argv[0] for that purpose, usually it does contain full path to the executable, but not nessesarily - process could be created with arbitrary value in the field.
Also mind you, the current directory and the directory with the executable are two different things, so getcwd() won't help you either.
On Windows use GetModuleFileName(), on Linux read /dev/proc/procID/.. files.
Just my two cents, but doesn't the following code portably work in C++17?
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main(int argc, char* argv[])
{
std::cout << "Path is " << fs::path(argv[0]).parent_path() << '\n';
}
Seems to work for me on Linux at least.
Based on the previous idea, I now have:
std::filesystem::path prepend_exe_path(const std::string& filename, const std::string& exe_path = "");
With implementation:
fs::path prepend_exe_path(const std::string& filename, const std::string& exe_path)
{
static auto exe_parent_path = fs::path(exe_path).parent_path();
return exe_parent_path / filename;
}
And initialization trick in main():
(void) prepend_exe_path("", argv[0]);
Thanks #Sam Redway for the argv[0] idea. And of course, I understand that C++17 was not around for many years when the OP asked the question.
Just to belatedly pile on here,...
there is no standard solution, because the languages are agnostic of underlying file systems, so as others have said, the concept of a directory based file system is outside the scope of the c / c++ languages.
on top of that, you want not the current working directory, but the directory the program is running in, which must take into account how the program got to where it is - ie was it spawned as a new process via a fork, etc. To get the directory a program is running in, as the solutions have demonstrated, requires that you get that information from the process control structures of the operating system in question, which is the only authority on this question. Thus, by definition, its an OS specific solution.
#include <windows.h>
using namespace std;
// The directory path returned by native GetCurrentDirectory() no end backslash
string getCurrentDirectoryOnWindows()
{
const unsigned long maxDir = 260;
char currentDir[maxDir];
GetCurrentDirectory(maxDir, currentDir);
return string(currentDir);
}
For Windows system at console you can use system(dir) command. And console gives you information about directory and etc. Read about the dir command at cmd. But for Unix-like systems, I don't know... If this command is run, read bash command. ls does not display directory...
Example:
int main()
{
system("dir");
system("pause"); //this wait for Enter-key-press;
return 0;
}
Works with starting from C++11, using experimental filesystem, and C++14-C++17 as well using official filesystem.
application.h:
#pragma once
//
// https://en.cppreference.com/w/User:D41D8CD98F/feature_testing_macros
//
#ifdef __cpp_lib_filesystem
#include <filesystem>
#else
#include <experimental/filesystem>
namespace std {
namespace filesystem = experimental::filesystem;
}
#endif
std::filesystem::path getexepath();
application.cpp:
#include "application.h"
#ifdef _WIN32
#include <windows.h> //GetModuleFileNameW
#else
#include <limits.h>
#include <unistd.h> //readlink
#endif
std::filesystem::path getexepath()
{
#ifdef _WIN32
wchar_t path[MAX_PATH] = { 0 };
GetModuleFileNameW(NULL, path, MAX_PATH);
return path;
#else
char result[PATH_MAX];
ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
return std::string(result, (count > 0) ? count : 0);
#endif
}
For relative paths, here's what I did. I am aware of the age of this question, I simply want to contribute a simpler answer that works in the majority of cases:
Say you have a path like this:
"path/to/file/folder"
For some reason, Linux-built executables made in eclipse work fine with this. However, windows gets very confused if given a path like this to work with!
As stated above there are several ways to get the current path to the executable, but the easiest way I find works a charm in the majority of cases is appending this to the FRONT of your path:
"./path/to/file/folder"
Just adding "./" should get you sorted! :) Then you can start loading from whatever directory you wish, so long as it is with the executable itself.
EDIT: This won't work if you try to launch the executable from code::blocks if that's the development environment being used, as for some reason, code::blocks doesn't load stuff right... :D
EDIT2: Some new things I have found is that if you specify a static path like this one in your code (Assuming Example.data is something you need to load):
"resources/Example.data"
If you then launch your app from the actual directory (or in Windows, you make a shortcut, and set the working dir to your app dir) then it will work like that.
Keep this in mind when debugging issues related to missing resource/file paths. (Especially in IDEs that set the wrong working dir when launching a build exe from the IDE)
A library solution (although I know this was not asked for).
If you happen to use Qt:
QCoreApplication::applicationDirPath()
Path to the current .exe
#include <Windows.h>
std::wstring getexepathW()
{
wchar_t result[MAX_PATH];
return std::wstring(result, GetModuleFileNameW(NULL, result, MAX_PATH));
}
std::wcout << getexepathW() << std::endl;
// -------- OR --------
std::string getexepathA()
{
char result[MAX_PATH];
return std::string(result, GetModuleFileNameA(NULL, result, MAX_PATH));
}
std::cout << getexepathA() << std::endl;
On POSIX platforms, you can use getcwd().
On Windows, you may use _getcwd(), as use of getcwd() has been deprecated.
For standard libraries, if Boost were standard enough for you, I would have suggested Boost::filesystem, but they seem to have removed path normalization from the proposal. You may have to wait until TR2 becomes readily available for a fully standard solution.
Boost Filesystem's initial_path() behaves like POSIX's getcwd(), and neither does what you want by itself, but appending argv[0] to either of them should do it.
You may note that the result is not always pretty--you may get things like /foo/bar/../../baz/a.out or /foo/bar//baz/a.out, but I believe that it always results in a valid path which names the executable (note that consecutive slashes in a path are collapsed to one).
I previously wrote a solution using envp (the third argument to main() which worked on Linux but didn't seem workable on Windows, so I'm essentially recommending the same solution as someone else did previously, but with the additional explanation of why it is actually correct even if the results are not pretty.
As Minok mentioned, there is no such functionality specified ini C standard or C++ standard. This is considered to be purely OS-specific feature and it is specified in POSIX standard, for example.
Thorsten79 has given good suggestion, it is Boost.Filesystem library. However, it may be inconvenient in case you don't want to have any link-time dependencies in binary form for your program.
A good alternative I would recommend is collection of 100% headers-only STLSoft C++ Libraries Matthew Wilson (author of must-read books about C++). There is portable facade PlatformSTL gives access to system-specific API: WinSTL for Windows and UnixSTL on Unix, so it is portable solution. All the system-specific elements are specified with use of traits and policies, so it is extensible framework. There is filesystem library provided, of course.
The linux bash command
which progname will report a path to program.
Even if one could issue the which command from within your program and direct the output to a tmp file and the program
subsequently reads that tmp file, it will not tell you if that program is the one executing. It only tells you where a program having that name is located.
What is required is to obtain your process id number, and to parse out the path to the name
In my program I want to know if the program was
executed from the user's bin directory or from another in the path
or from /usr/bin. /usr/bin would contain the supported version.
My feeling is that in Linux there is the one solution that is portable.
Use realpath() in stdlib.h like this:
char *working_dir_path = realpath(".", NULL);
The following worked well for me on macOS 10.15.7
brew install boost
main.cpp
#include <iostream>
#include <boost/filesystem.hpp>
int main(int argc, char* argv[]){
boost::filesystem::path p{argv[0]};
p = absolute(p).parent_path();
std::cout << p << std::endl;
return 0;
}
Compiling
g++ -Wall -std=c++11 -l boost_filesystem main.cpp
This question was asked 15 years ago, so the existing answers are now incorrect. If you're using C++17 or greater, the solution is very straightforward today:
#include <filesystem>
std::cout << std::filesystem::current_path();
See cppreference.com for more information.

fstat: st_atime and st_mtime not a member?

I am doing an fstat on my file descriptor and dumping that into a struct stat. I read the documentation for fstat (link below) and it claims there are members st_atime and st_mtime.
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/stat.h.html
GCC let's me compile, but stepping through GDB, I cannot print out those members (i.e. I can print every other member). GDB claims they don't exist.
In fact, when I print out the struct stat, st_atime is spelt st_atim (i.e. same thing with st_mtime). Then it looks like it's a tuple or something because it holds two values, tv_sec and tv_nsec.
Does anyone know why GDB is claiming they don't exist?
Also, does anyone know how to pass it to memcpy? I am using C90.
This is the line of code it complains about saying I can't pass a time_t in here. How would I cast it to make this line work?
memcpy(&temp.otar_adate, file_statistics.st_atime, OTAR_DATE_SIZE);
MY OS: CentOS
On Linux, at least certain versions, st_atime and some other time fields in struct stat are inside struct timespec and contain proper timestamps with full nanosecond precision. On those systems st_atime is a define to something else. On my CentOS machine it is defined to st_atim.tv_sec.
Throw your code into the preprocessor to see what it is on your system:
$ cat foo.c
#include <sys/stat.h>
void
foo(void)
{
struct stat st;
(void)st.st_atime;
}
$ cc -E foo.c | tail -7
void
foo(void)
{
struct stat st;
(void)st.st_atim.tv_sec;
}
Gdb doesn't know about preprocessor defines, so it can't know how your code got preprocessed. It only knows about the real definition of the struct.

Cygwin cannot find dos.h and conio.h on compilation

I am trying to compile the following code in Cygwin 64 bit terminal using gcc, but it seems to be unable to find conio.h or dos.h
#include <stdlib.h>
#include <dos.h>
#define MEM 0X12
main()
{
struct WORDREGS
{
unsigned int ax;
unsigned int bx;
unsigned int cx;
unsigned int dx;
unsigned int si;
unsigned int di;
unsigned int flags;
};
struct BYTEREGS
{
unsigned char al,ah;
unsigned char bl,bh;
unsigned char cl,ch;
unsigned char dl,dh;
};
union REGS
{
struct WORDREGS x;
struct BYTEREGS h;
};
union REGS regs;
unsigned int size;
int86(MEM, &regs, &regs);
size = regs.x.ax;
printf("Memory size is %d Kbytes", size);
}
The compiler says it is unable to locate dos.h or conio.h, showing a fatal error notice. I want to know what the reason for this is and how it can be dealt with.
Cygwin is a Linux-Environment for Windows (see https://cygwin.com ). This is probably the main reason because there very well exists a header file called 'dos.h'.
Concerning the compilation problem a solution is explained in the mail archive of the cygwin mailing list ( https://www.cygwin.com/ml/cygwin/2007-04/msg00180.html ).
It seems that dos.h and conio.h (header-files) are part of the mingw-runtime-WHATEVER.VERSION package, which you can download from cygwin.com (better install it with the cygwin install and update program setup-x86.exe or setup-x86_64.exe).
The link in that mail mentioned above is broken, but you can find the package by yourself, when choosing 'Search Packages' on the left side bar of the cygwin.com homepage. Then you can put 'dos.h' or 'conio.h' into the input field and after hitting 'Go' you get listed all packages, which contain these header files. According to the answer in that mail above, you only need the
mingw-runtime-WHATEVER.VERSION package, which you have to download and install.
After installing that package you very probably need to instruct your gcc-compiler with the
option '-I' (upper-case letter 'i'!) and the path (within quotation marks!) to the dos.h file, for instance:
gcc program.c -I'C:\cygwin\usr\i686-pc-mingw32\sys-root\mingw\include'
Attention: Probably the path on your system is different, particularly when you are working with 64-bit-cygwin!
Instead of using the '-I' option, you can define an environment variable with following command in the terminal:
export C_INCLUDE_PATH='C:\cygwin\usr\i686-pc-mingw32\sys-root\mingw\include'
At least the errors with the not found header-files are then eliminated, but there are probably still other errors (for instance: undefined reference to 'int86'?).
Because they are MS-DOS headers and are not available in cygwin. Also, the correct signature of main() is int main().

readdir() 32/64 compatibility issues

I'm trying to get some old legacy code working on new 64-bit systems, and I'm currently stuck. Below is a small C file I'm using to test functionality that exists in the actual program that is currently breaking.
#define _POSIX_SOURCE
#include <dirent.h>
#include <sys/types.h>
#undef _POSIX_SOURCE
#include <stdio.h>
main(){
DIR *dirp;
struct dirent *dp;
char *const_dir;
const_dir = "/any/path/goes/here";
if(!(dirp = opendir(const_dir)))
perror("opendir() error");
else{
puts("contents of path:");
while(dp = readdir(dirp))
printf(" %s\n", dp->d_name);
closedir(dirp);
}
}
The Problem:
The OS is Red Hat 7.0 Maipo x86_64.
The legacy code is 32-bit, and must be kept that way.
I've gotten the compile for the program working fine using the -m32 flag with g++. The problem that arises is during runtime, readdir() gets a 64-bit inode and then throws an EOVERFLOW errno and of course nothing gets printed out.
I've tried using readdir64() in place of readdir() to some success. I no longer get the errno EOVERFLOW, and the lines come out on the terminal, but the files themselves don't get printed. I'm assuming this is due to the buffer not being what dirent expects.
I've attempted to use dirent64 to try to alleviate this problem but whenever I attempt this I get:
test.c:19:22 error: dereferencing pointer to incomplete type
printf(" %s\n", dp->d_name);
I'm wondering if there's a way to manually shift the dp->d_name buffer for dirent to be used with readdir(). I've noticed in Gdb that using readdir() and dirent results in dp->d_name having directories listed at dp->d_name[1], whereas readdir64() and dirent gives the first directory at dp->d_name[8].
That or somehow get dirent64 to work, or maybe I'm just on the wrong path completely.
Lastly, it's worth noting that the program functions perfectly without the -m32 flag included, so I'm assuming it has to be a 32/64 compatibility error somewhere. Any help is appreciated.
Thanks to #Martin in the comments above I was led to try defining the dirent64 struct in my code. This works. There's probably a #define that can be used to circumvent pasting libc .h code into my own code, but this works for now.
The code I needed was found in <bits/dirent.h>
I guess I should also note that this makes it work using both readdir64() and dirent64
In order to get a 64-bit ino_t with GCC and Glibc, you need to define the features _XOPEN_SOURCE and _FILE_OFFSET_BITS=64.
$ echo '#include <dirent.h>' | gcc -m32 -E -D_XOPEN_SOURCE -D_FILE_OFFSET_BITS=64 - | grep ino
__extension__ typedef unsigned long int __ino_t;
__extension__ typedef __u_quad_t __ino64_t;
typedef __ino64_t ino_t;
__ino64_t d_ino;
I say this from documentation reading and checking the preprocessor, not from deep experience or testing with a filesystem with inode numbers above 2^32, so I don't guarantee that you won't run into other problems down the line.

No warning from gcc when function definition in linked source different from function prototype in header

I had a problem with a part of my code, which after some iterations seemed to read NaN as value of a double of a struct. I think I found the error, but am still wondering why gcc (version 3.2.3 on a embedded Linux with busybox) did not warn me. Here are the important parts of the code:
A c file and its header for functions to acquire data over USB:
// usb_control.h
typedef struct{
double mean;
short *values;
} DATA_POINTS;
typedef struct{
int size;
DATA_POINTS *channel1;
//....7 more channels
} DATA_STRUCT;
DATA_STRUCT *create_data_struct(int N); // N values per channel
int free_data_struct(DATA_STRUCT *data);
int aqcu_data(DATA_STRUCT *data, int N);
A c and header file with helper function (math, bitshift,etc...):
// helper.h
int mean(DATA_STRUCT *data);
// helper.c (this is where the error is obviously)
double mean(DATA_STRUCT *data)
{
// sum in for loop
data->channel1->mean = sum/data->N;
// ...7 more channels
// a printf here displayed the mean values corretly
}
The main file
// main.c
#include "helper.h"
#include "usb_control.h"
// Allocate space for data struct
DATA_STRUCT *data = create_data_struct(N);
// get data for different delays
for (delay = 0; delay < 500; delay += pw){
acqu_data(data, N);
mean(data);
printf("%.2f",data->channel1->mean); // done for all 8 channels
// printf of the mean values first is correct. Than after 5 iterations
// it is always NaN for channel1. The other channels are displayed correctly;
}
There were no segfaults nor any other missbehavior, just the NaN for channel1 in the main file.
After finding the error, which was not easy, it was of course east to fix. The return type of mean(){} was wrong in the definition. Instead of double mean() it has to be int mean() as the prototype defines. When all the functions are put into one file, gcc warns me that there is a redefinition of the function mean(). But as I compile each c file seperately and link them afterwards gcc seems to miss that.
So my questions would be. Why didn't I get any warnings, even non with gcc -Wall? Or is there still another error hidden which is just not causing problems now?
Regards,
christian
When each .c file is compiled separately, the only information the compiler knows is the function prototype you have given.
Because every file is compiled separately, there is no way the compiler process of main.c knows the definition of mean in helper.c is wrong.
After the .c file is compiled, the signature will be stripped, so the linker cannot know the mean is wrong either.
A simple fix is always include the interface .h file in the implementation .c file
// in helper.c:
#include "helper.h"
double mean(DATA_STRUCT *data);
Then the compiler process of helper.c will notice that inconsistent type and warn you.
A mean usually is a real value so double is ok. Here you define mean as returning double, but the prototype says int mean(...).
The only way gcc can be aware of the fact that there's a redefinition, is if the redefinition occurs for real... When you compile files separately likely the mean prototype is missing... it is not shown in your code fragment at least: you should include helper.h also into helper.c. Doing so, gcc -c helper.c must give you a warning. I have gcc 4.3.2, but I am almost sure it must be so also for the version you have. In the main, you just use mean, so here the gcc trusts what is said in helper.h. When you link, there is no more information about the size of arguments and returning value, and bad things happen (like reading an int as a double).
Another detail: you say you get NaN for an int of the struct... well, in the struct there's a double, and int can't be NaN!

Resources