Setting errno from user defined function - c

As far as I am aware of, most if not all standard C functions will set the global errno on failure to represent what happened, and thus the value can be used in logging, debugging or testing. Is it advisable for a user defined function to use this same behavior, or should we mimic it with a global variable local_errno that accepts the same values with the same meanings?
As am example, I’m writing a calculator, and I want an Addition function to report overflow:
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
Add( int, int );
int
main( void )
{
int a = 0, b = 0, res0 = 0;
scanf(“%d %d”, &a, &b );
res0 = Add(a,b);
if( res0 == INF )
{
fprintf(stderr, “Error %s in Add\n”, strerror(errno));
return(errno);
}else
{
printf(“%d\n”, res0);
}
return(EXIT_SUCCESS);
}
int
Add( int l, int r )
{
if( l == INT_MAX || r == INT_MAX )
{
errno = EOVERFLOW;
return(INF);
}
return(l+r);
}

Related

How to initialize global constant variable in main() function using pure C?

How can I do global constant initialization like this? Is it possible at all? Or there is another way to do what I want? I mean I need global parameters gained from main() and they must be constants.
#include <stdio.h>
#include <stdlib.h>
const int var;
int main(int argc, char *argv[]) {
var = atoi(argv[1]);
/* ... */
return 0;
}
I need global parameters gained from main() and they must be constants.
No portable way to do directly as OP wants.
Code needs different access for reading and writing. Effectively hiding the access to the true data.
A close solution it to set and get data via functions defined in another file. Then no way to change data once set and only settable once.
main_var.h
int main_var_get(void);
void main_var_set(int v);
main_var.c
#include <stdlib.h>
#include "main_var.h"
static int var; // This could instead be a struct of many members.
// Or a pointer to a struct with many members.
static int var_init;
int main_var_get(void) {
if (!var_init) {
// Handle call of get before set, perhaps exit or return default value
exit(EXIT_FAILURE);
}
return var;
}
void main_var_set(int v) {
if (var_init) {
// Handle 2nd set, perhaps exit or ignore
exit(EXIT_FAILURE);
}
var = v;
var_init = 1;
}
main.c
#include <stdio.h>
#include "main_var.h"
int main(void) {
main_var_set(42);
...
printf("%d\n", main_var_get());
}
Another is to use a const int *. Access before setting is the same no-no as dereferencing NULL. Attempting to write *main_var_addr is UB like writing any const object.
main_var.h
extern const int *main_var_addr;
void main_var_set(int v);
main_var.c
#include <stdlib.h>
#include "main_var.h"
const int *main_var_addr = NULL;
static int var;
void main_var_set(int v) {
if (main_var_addr) {
// Handle 2nd set attempt, perhaps exit or ignore
exit(EXIT_FAILURE);
}
var = v;
main_var_addr = &var
}
main.c
#include <stdio.h>
#include "main_var.h"
int main(void) {
main_var_set(42);
...
printf("%d\n", *main_var_addr);
}
I don't think C allows you to initialize a constant variable elsewhere. However, you can just change var from const to static.
This is not possible, actually const doesn't mean the variable is constant in C, it's only mean that you are not allowed to change the value of the variable, but someone else could.
Global value are initialize before the main run, that mean you can't initialize at runtime, how this initialization is done is implementation behavior so there is no "pure C" way to do what you ask.
However, I don't see why you could not encapsulate your global:
my_var.h:
int init_my_var(int argc, char **argv);
int get_my_var(void);
my_var.c
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
static int var;
int init_my_var(int argc, char **argv) {
#ifndef NDEBUG
#include <stdbool.h>
#include <assert.h>
{
static bool first = true;
assert(first);
first = false;
}
#endif
if (argc < 2) {
return 1;
}
errno = 0;
long ret = strtol(argv[1], NULL, 10);
if (errno || (ret < INT_MIN || ret > INT_MAX)) {
return 2;
}
var = (int)ret;
return 0;
}
int get_my_var(void) {
return var;
}
main.c:
#include <stdio.h>
int main(void) {
printf("%d\n", get_my_var());
if (init_my_var(2, (char *[]){"", "42"})) {
return EXIT_FAILURE;
}
printf("%d\n", get_my_var());
if (init_my_var(2, (char *[]){"", "0"})) {
return EXIT_FAILURE;
}
}

How can i read a number in c with a function and use it in main?

i try to read a number from keyboard with a function, but it doesn't work. This is the code
#include <stdio.h>
#include <stdlib.h>
void write(int *n);
int main()
{
int *n,*m,p;
write(&n);
write(&m);
p = *n + *m;
printf("p = %d",p);
}
void write(int *n)
{
scanf("%d",&n);
}
applying all the comments to the posted code and following the axiom:
only one statement per line and (at most) one variable declaration per statement.
and checking the returned value from scanf() to assure the operation was successful
results in:
#include <stdio.h> // scanf(), printf(), fprintf()
#include <stdlib.h> // exit(), EXIT_FAILURE
void getInteger(int *n);
int main( void )
{
int n;
int m;
int p;
getInteger(&n);
getInteger(&m);
p = n + m;
printf("p = %d",p);
}
void getInteger(int *n)
{
if( 1 != scanf("%d",n) )
{
fprintf( stderr, "scanf failed" );
exit( EXIT_FAILURE );
}
}
and when run with an input of: '1 3' the output is
p = 4

How to resolve this pointer issue?

i want to assign value of an integer array to integer pointer. The pointer takes a different value of assignment. Please help me on this.
I have assigned 2 for port_val variable. But, after assigning that to ofport_request var, the value becomes different.
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
int main ()
{
printf("INSIDE MAIN..\n");
int64_t of_port[100];
int count=2;
int i;
int port_val = 2;
int port_next_val = 4;
size_t n_ofport_request = 1;
int64_t *ofport_request = malloc(sizeof *ofport_request * (n_ofport_request));
for(i=0;i<count;i++) {
if(i == 0) {
of_port[i] = port_val;
} else {
of_port[i] = port_next_val;
}
ofport_request[0] = of_port[i];
printf("OFPORT VAL = %d\n",ofport_request);
}
return 0;
}
If you want to print the pointer variable, you have to use the * before the variable name.
Use the below printf statement it will work.
printf("OFPORT VAL = %lld\n",*ofport_request);

Strtol doesn't set errno on overflow conversion

My strtol function fails to set errno during overflown conversion.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <getopt.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc, char **argv) {
errno = 0;
int e = strtol("1000000000000000", NULL, 10);
printf("%d %d\n", errno, e);
return 0;
}
returns
0 -1530494976
What do I do wrong?
Compiler
gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2
Options
gcc -Wall -std=gnu99 -O2
There is nothing wrong with the implementation of strtol() but there is with your code.
The return type of this function is long (see the trailing l) and apparently the value 1000000000000000 can be represented by the long integer type. However the return value is assigned to e whose type is int which is unable to represent this value. What then happens is implementation-defined.
So change int e to long e and "%d %d\n" to "%d %ld\n". If you want to keep it as int, then you have to check if the value is outside of its range of representable values by yourself:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <limits.h> // for INT_{MIN,MAX}
int
main(void)
{
errno = 0;
long f = strtol("1000000000000000", NULL, 10);
if (errno == ERANGE) {
puts("value not representable by long (or int)");
} else if (f < INT_MIN || f > INT_MAX) {
puts("value not representable by int");
} else {
int e = f;
printf("%d\n", e);
}
}
It seems like both Microsoft [1] and Apple [2] implementations have the setting of errno commented out.
[1] http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/strtol.c.htm
[2] http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/libkern/strtol.c

vsprintf on OS X: EXC_BAD_ACCESS

I've discovered weird behavior of vsprintf on OSX.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#if defined(WIN32)
#include <windows.h>
#define VSNPRINTF _vsnprintf
#elif defined(LINUX) || defined (DARWIN)
#define VSNPRINTF vsnprintf
#include <sys/types.h>
#include <unistd.h>
#endif
char *f(const char *fmt, ...)
{
char *out = NULL;
const int step = 32;
int n = -1, lout = step;
va_list arg;
if(fmt!=NULL)
{
va_start(arg, fmt);
do
{
if(!out)
{
free(out);
out = NULL;
}
out = (char*)malloc(lout + 1);
if(!out) break;
memset(out, 0, lout + 1);
n = VSNPRINTF(out, lout, fmt, arg);
if(n == -1 || n + 1 > lout)
{
lout += step;
n = -1;
}
}while(n == -1);
va_end(arg);
}
return out;
}
int main()
{
char *msg = NULL;
unsigned long x = 0xDEADBEEF;
msg = f("%X%X%X%X", x, x, x, x);
if(!msg) return -1;
puts(msg);
return 0;
}
The function shall return allocated string (char*) containing formatted text. It works correctly on Linux and Windows. It returns badly formatted text on OSX and sometimes it leads to Segmentation fault (EXC_BAD_ACCESS). Btw, I know that I can use vasprintf.
What can be the problem?
Your problem is most likely that you're calling vsnprintf with the same va_list multiple times. This doesn't work in some ABIs.
Look up the man page of va_copy. The short version is to do something like this:
va_list c;
va_copy(c, arg);
n = VSNPRINTF(out, lout, fmt, c);
va_end(c);

Resources