'What is the right way to print a value of type rlim_t?
I am using the getrlimit() function to get the maximum stack size on my system. This function stores both the current limit and the maximum limit in a struct with two rlim_t fields. I want to print these values.
I found this link that suggests that rlim_t is an unsigned integer type, so I used the PRIuMAX macro for the conversion specifier, casting the value to (uintmax_t). I noticed that I could omit the cast without generating any warnings; is the cast really necessary here?
After digging through several header files, I found that rlim_t is a typedef for unsigned long on my system. So I could also use the %lu conversion specifier, and do away with the cast.
I don't think that I can assume that rlim_t is always an unsigned long, so it seems better to use the first method to improve portability. I found this answer that suggests that %llu may not always be a valid conversion specifier for rlim_t, and advocates casting to long long. What is the best way to print a value of type rlim_t?
Here is a short, illustrative program:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/resource.h>
int main(void)
{
struct rlimit stacklim;
rlim_t cur_bytes, max_bytes;
if (getrlimit(RLIMIT_STACK, &stacklim) == 0) {
cur_bytes = stacklim.rlim_cur;
max_bytes = stacklim.rlim_max;
} else {
perror("Error in getrlimit()");
exit(EXIT_FAILURE);
}
puts("Maximum Stack Size");
printf("Soft limit: %" PRIuMAX " bytes\n", (uintmax_t)cur_bytes);
printf("Hard limit: %" PRIuMAX " bytes\n", (uintmax_t)max_bytes);
return 0;
}
Solution 1:[1]
As mentioned in the comments to the original question, the cast is necessary to ensure that the type matches the conversion specification. The system headers may not define the type of rlim_t to be uintmax_t, but since rlim_t is an unsigned integer type, the cast to uintmax_t is safe.
The above solution using the PRIuMAX macro is fine, but since C99 there has also been the j type modifier, used for printing values of type intmax_t and uintmax_t:
printf("Soft limit: %ju bytes\n", (uintmax_t)cur_bytes);
printf("Hard limit: %ju bytes\n", (uintmax_t)max_bytes);
Solution 2:[2]
The accepted solution is great. It is a safe route.
I thought that it is worth adding that in the relevant Linux manual page, the sole example provided (very bottom of the webpage) uses
intmax_t
for displaying each member of a rlimit structure when the first argument of getrlimit is the macro RLIMIT_CPU (limit, in seconds, on the amount of CPU time that the process can consume).
This can be "unlimited". An "unlimited" value occurs when the member has value equal to the value of the RLIM_INFINITY macro, which on my system is defined as 0xffffffffffffffffuLL or 264 - 1.
This would suggest that it is safe to cast to intmax_t which has associated specifier %jd.
Although you did not ask for this, the following program may be of help to others that read this post. The following program prints the values of the members of each rlimit structure for every possible value of the resource argument (the first argument) of getrlimit. This program casts to intmax_t (with specifier %jd) as an example, though casting to uintmax_t (with specifier %ju) is also perfectly acceptable.
#include <sys/resource.h> // for rlimit struct, getrlimit(), and macros
#include <stdio.h> // for printf
#include <stdint.h> // for uintmax_t
#include <string.h> // for strlen()
/* "Get Variable Name": direct preprocessor to stringize variable v. */
#define GVN(v) (#v)
int main(void) {
/* Array containing int macros */
int limits[] = {
RLIMIT_AS, RLIMIT_CORE, RLIMIT_CPU, RLIMIT_DATA, RLIMIT_FSIZE,
RLIMIT_LOCKS, RLIMIT_MEMLOCK, RLIMIT_MSGQUEUE, RLIMIT_NICE,
RLIMIT_NOFILE, RLIMIT_NPROC, RLIMIT_RSS, RLIMIT_RTPRIO,
RLIMIT_RTTIME, RLIMIT_SIGPENDING, RLIMIT_STACK
};
/* Array containing the names of above macros */
char* limits_names[] = {GVN(RLIMIT_AS), GVN(RLIMIT_CORE), GVN(RLIMIT_CPU),
GVN(RLIMIT_DATA), GVN(RLIMIT_FSIZE), GVN(RLIMIT_LOCKS),
GVN(RLIMIT_MEMLOCK), GVN(RLIMIT_MSGQUEUE), GVN(RLIMIT_NICE),
GVN(RLIMIT_NOFILE), GVN(RLIMIT_NPROC), GVN(RLIMIT_RSS),
GVN(RLIMIT_RTPRIO), GVN(RLIMIT_RTTIME), GVN(RLIMIT_SIGPENDING),
GVN(RLIMIT_STACK)
};
/* getrlimit modifies this structure */
struct rlimit limit;
/* get length of the arrays */
size_t len_limits = sizeof(limits) / sizeof(limits[0]);
/* stores number of characters of longest macro name */
size_t max_len_names = 0;
for (size_t i = 0, temp; i < len_limits; i++)
if ((temp = strlen(limits_names[i])) > max_len_names)
max_len_names = temp;
printf("\n");
for (size_t i = 0; i < len_limits; i++) {
/* getrlimit returns 0 on success, -1 otherwise */
if (getrlimit(limits[i], &limit) != 0) {
printf("\n%s (error in getrlimit() with this arg)\n\n",
limits_names[i]);
continue;
}
/* RLIM_INFINITY is 0xffffffffffffffffuLL on my setup */
/* RLIM_INFINITY denotes no limit on a resource */
if (limit.rlim_cur == RLIM_INFINITY)
printf("%-*s (soft): unlimited\n", (int) max_len_names,
limits_names[i]);
else
printf("%-*s (soft): %ju\n", (int) max_len_names, limits_names[i],
(uintmax_t) limit.rlim_cur);
if (limit.rlim_max == RLIM_INFINITY)
printf("%-*s (hard): unlimited\n", (int) max_len_names,
limits_names[i]);
else
printf("%-*s (hard): %ju\n", (int) max_len_names, limits_names[i],
(uintmax_t) limit.rlim_max);
}
printf("\n");
return 0;
}
Solution 3:[3]
I believe it is an unsigned long.
printf("Soft limit: %lu" PRIuMAX " bytes\n", cur_bytes);
printf("Hard limit: %lu" PRIuMAX " bytes\n", max_bytes);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | ad absurdum |
| Solution 2 | |
| Solution 3 | aggaton |
