resolving redefinition of timespec in time.h - c

I am writing a program which includes both /usr/include/linux/time.h and /usr/include/stdlib.h.
The problem is:
stdlib.h includes /usr/include/time.h, which defines 'struct timespec', and /usr/include/linux/time.h also defines one. This introduces a compilation error of redefinition.
I've examined the definitions of 'struct timespec' in these two header files:
in /usr/include/time.h:
struct timespec
{
__time_t tv_sec; /* Seconds. */
long int tv_nsec; /* Nanoseconds. */
};
in /usr/include/linux/time.h:
struct timespec {
__kernel_time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
It seems that these definitions are indeed equivalent, but I can't prove it.
My question is: is there a robust way to resolve this redefinition?
Links to discussions on this problem are also highly appreciated. Thanks.

One way to resolve the double-definition error is to rename one of these definitions:
#include <time.h>
#define timespec linux_timespec
#include <linux/time.h>
#undef timespec
And then assert at compile time that both definitions have the same layout:
typedef int assert_same_size[sizeof(struct linux_timespec) == sizeof(timespec) ? 1 : -1];
typedef int assert_same_alignment[__alignof(struct linux_timespec) == __alignof(timespec) ? 1 : -1];
typedef int assert_same_tv_sec[offsetof(struct linux_timespec, tv_sec) == offsetof(struct timespec, tv_sec) ? 1 : -1];
typedef int assert_same_tv_nsec[offsetof(struct linux_timespec, tv_nsec) == offsetof(struct timespec, tv_nsec) ? 1 : -1];

I got the same error in Ecliepse Neon IDE and i resolved it by adding -DHAVE_STRUCT_TIMESPEC in C/C++ Build -> Settings -> GCC C++ Compiler -> Miscellaneous -> Others flag

Related

Macros defined in time.h not recognized

Originally, I wanted to cast a struct timeval to a timespec one.
At first, it did not seem difficult, as a solution is proposed there:
Is there a standard way to convert a struct timeval into a struct timespec?
A macro, TIMEVAL_TO_TIMESPEC is supposed to do the job.
As indicated in the docs (https://www.daemon-systems.org/man/TIMEVAL_TO_TIMESPEC.3.html) it only asks for sys/time.h to be included.
But I still get the same answer when I try to compile:`warning: implicit declaration of function ‘TIMEVAL_TO_TIMESPEC’ [-Wimplicit-function-declaration]
I even tried to compile the example given in the docs:
#include<time.h>
#include <assert.h>
#include<sys/time.h>
static void example(struct timespec *spec, time_t minutes) {
struct timeval elapsed;
(void)gettimeofday(&elapsed, NULL);
_DIAGASSERT(spec != NULL);
TIMEVAL_TO_TIMESPEC(&elapsed, spec);
/* Add the offset for timeout in minutes. */
spec->tv_sec = spec->tv_sec + minutes * 60;
}
int main(){
return 0;
}
When compiling I get:
test.c: In function ‘example’:
test.c:10:2: warning: implicit declaration of function ‘_DIAGASSERT’ [-Wimplicit-function-declaration]
_DIAGASSERT(spec != NULL);
^
test.c:11:2: warning: implicit declaration of function ‘TIMEVAL_TO_TIMESPEC’ [-Wimplicit-function-declaration]
TIMEVAL_TO_TIMESPEC(&elapsed, spec);
^
/tmp/ccqWnL9I.o: In function `example':
test.c:(.text+0x43): undefined reference to `_DIAGASSERT'
test.c:(.text+0x5b): undefined reference to `TIMEVAL_TO_TIMESPEC'
collect2: error: ld returned 1 exit status
What did I do that was wrong ?
You linked to a NetBSD man page. There is no guarantee that what you read there will have anything to do with Linux or any other OS. On what OS are you developing?
It looks like the macros are standard in glibc, which is the C library you're using on just about any Linux system. However, if you inspect the sys/time.h file, you'll see that the macros are gated by an #ifdef:
#ifdef __USE_GNU
/* Macros for converting between `struct timeval' and `struct timespec'. */
# define TIMEVAL_TO_TIMESPEC(tv, ts) { \
(ts)->tv_sec = (tv)->tv_sec; \
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
}
# define TIMESPEC_TO_TIMEVAL(tv, ts) { \
(tv)->tv_sec = (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
}
#endif
So you would need to #define __USE_GNU before including sys/time.h in order to expose these macros. As #alk points out in the comments, you get this and more by defining _GNU_SOURCE. You can read more about that here.

Timespec redefinition error [duplicate]

This question already has answers here:
Visual Studio error with 'timespec' structure
(5 answers)
Closed 6 years ago.
While executing a Pthread program in C using Visual Studio 2015, I got the following error:
Error C2011 'timespec': 'struct' type redefinition
The following is my code:
#include<pthread.h>
#include<stdlib.h>
#include<stdio.h>
void *calculator(void *parameter);
int main(/*int *argc,char *argv[]*/)
{
pthread_t thread_obj;
pthread_attr_t thread_attr;
char *First_string = "abc"/*argv[1]*/;
pthread_attr_init(&thread_attr);
pthread_create(&thread_obj,&thread_attr,calculator,First_string);
}
void *calculator(void *parameter)
{
int x=atoi((char*)parameter);
printf("x=%d", x);
}
The pthread.h header file contains the following code related to timespec:
#if !defined(HAVE_STRUCT_TIMESPEC)
#define HAVE_STRUCT_TIMESPEC
#if !defined(_TIMESPEC_DEFINED)
#define _TIMESPEC_DEFINED
struct timespec {
time_t tv_sec;
long tv_nsec;
};
#endif /* _TIMESPEC_DEFINED */
#endif /* HAVE_STRUCT_TIMESPEC */
No other header file which I use uses the timespec struct, so there is no chance of redefining. There is no chance of a corrupted header file because it has been downloaded from pthread opensource website.
pthreads-win32 (which I assume you're using) may internally include time.h (time.h is also commonly included by other libraries/headers) - and time.h already declares timespec (also, it does so in a way compatible with pthreads) - yet the pthreads-win32's pthread.h doesn't have the valid include guards for this case (shame on them!). pthreads tries to declare it because it needs it internally, but since it's possible it won't need the entire time.h, it tries to declare only the timespec if possible. Still, you can simply add
#define HAVE_STRUCT_TIMESPEC
before #include <pthread.h> - that will tell the pthreads-win32 header that you already have a proper timespec, and will let your code compile properly.
Alternatively, if you're using pthreads extensively, you may wish to edit the header file itself - simply add that #define HAVE_STRUCT_TIMESPEC to it somewhere near the beginning, and you're good to go.
Further reading: http://mingw-users.1079350.n2.nabble.com/mingw-error-redefinition-of-struct-timespec-td7583722.html

struct accessible without declaration?

I have the following Code
#ifdef ENV_TI
typedef struct timespecT
{
Uint32 tv_sec;
Uint32 tv_nsec;
}timespec;
#endif
#ifndef ENV_TI
struct timespec currentTime; // This Line
#else
timespec currentTime;
#endif
How is the currentTime accessible if i have NOT defined ENV_TI flag and the timespec is defined under the ENV_TI flag?
I am running this code on Linux, gcc compiler.
struct timespec is a type name used in e.g. Linux, see the manual page for clock_gettime(). You get the type declaration by doing #include <time.h> on systems that support it. According to the manual page, this is POSIX standard functionality.
I think the code you're looking at is using the #ifdef to declare the type for environments that don't support it natively.
timespec is also the name of a struct defined in time.h

Any specific reason why localtime throws warning with struct tm* & stat* , in linux ?

I have this simple code (part of a project) :
void displayFileProperties(struct stat* file,char* outputProperties , char * path)
{
struct tm* time;
// code
// code
time = localtime(&file->st_mtim);
// code
}
Where eclipse keeps throwing me a warning :
passing argument 1 of ‘localtime’ from incompatible pointer type [enabled by default] main.c /ex4 line 340 C/C++ Problem
Any idea how to fix this ? thanks
st_mtim is a struct timespec (seconds and nanoseconds). You want st_mtime.
You'll want to use this instead:
time = localtime(&file->st_mtime);
Note the added 'e' at the end. st_mtim is a timespec, with 'e' added it's a time_t (what you need).
Completely changed answer:
SUGGESTIONS:
1) Make sure you #include these headers:
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
2) Cast your pointer to "const"
time = localtime((const time_t *)&file->st_mtime);
3) Post back what happens
=====================================================
ADDITIONAL SUGGESTIONS:
1) Please read these two links:
C stat struct does not have st_ctime field but only st_ctim
http://linux.die.net/man/2/lstat
Since kernel 2.5.48, the stat structure supports nanosecond resolution
for the three file timestamp fields. Glibc exposes the nanosecond
component of each field using names of the form st_atim.tv_nsec if the
_BSD_SOURCE or _SVID_SOURCE feature test macro is defined. These fields are specified in POSIX.1-2008, and, starting with version 2.12,
glibc also exposes these field names if _POSIX_C_SOURCE is defined
with the value 200809L or greater, or _XOPEN_SOURCE is defined with
the value 700 or greater. If none of the aforementioned macros are
defined, then the nanosecond values are exposed with names of the form
st_atimensec. On file systems that do not support subsecond
timestamps, the nanosecond fields are returned with the value 0.
2) Clearly, the makefile (that "works") has a #define that Eclipse doesn't, or vice versa.
Probably either/both _POSIX_C_SOURCE and/or _XOPEN_SOURCE.
Run this command to see what exists in the command line (makefile?) environment:
gcc -dM -E - < /dev/null | less
3) Please post back what you find!
I had the same issue with Eclipse:
Field st_mtime could not be resolved (semantic error)
Fixed the issue in Eclipse by right-clicking the project, choose Index->"Freshen All Files"
#include <malloc.h>
#include <time.h>
#include <stdio.h>
static struct tm* alarmTime(void);
int main(){
printf("Hour :%i\n", alarmTime()->tm_hour);
printf("Minute :%i\n", alarmTime()->tm_min);
return 0;
}
static struct tm* alarmTime(void){
time_t now = time(NULL);
struct tm* ptm;
#ifdef HAVE_LOCALTIME_R
struct tm tmbuf;
ptm = localtime_r(&now, &tmbuf);
#else
ptm = localtime(&now);
#endif
return ptm;
}

Getting problem with timing in C in visual studio 2010

I have a function for getting system time. The function is defined as follows.
int getSystemTime(struct timeval tv, void * tz);{
DWORD milliseconds;
milliseconds = timeGetTime();
tv->tv_sec = milliseconds / 1000;
tv->tv_usec = (milliseconds % 1000) * 1000;
return 0;
}
Precisely following are the problems:
1.error: identifier DWORD is undentified .
2.error: identifier timeGetTime() is undefined.
3.error: identifier suseconds_t is undefined.
I tried to include windef.h where DWORD is defined. But the problem is, I got the error like:
1. error: identifier PCONTEXT is undefined.
The header file for time included is time.h. Here the timeval defined is:
#ifndef _WINSOCK_H
struct timeval {
time_t tv_sec;
suseconds_t tv_usec;
};
Could you please tell me what shall I do to make this function run in windows environment?
[EDIT]
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#ifdef HAVE_MMSYSTEM_H
#include <mmsystem.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
You need to include windows.h at the top of your C file.

Resources