0

I'm writing a client-server program and I need to take a port number from command line arguments to add to the sockaddr_in struct. Currently I am casting the port number like this:

char* portName = argv[3];
int portNumber = (int) portName;

can someone tell me what's wrong with it and if there is a better way to do it? Thanks.

kodzuken
  • 3
  • 1
  • 1
    Your code right now converts a char array (i.e. pointer) to integer. Check out `int atoi(const char*)` for literal conversion. The function, however, isn't safe against bad inputs. – YiFei Oct 18 '20 at 20:51
  • @YiFei No, it converts a `char*` pointer to `int`. Arrays are not pointers. `portName` is an expression of array type, which *decays* to a pointer to its first element. – Keith Thompson Oct 18 '20 at 20:58

2 Answers2

1

as @YiFei told in the comments

#include<stdlib.h>

int main(int argc,char** argc){
  char* a = argv[3]; //this gives you pointer to a string (or a char array)
  int port = atoi(a); //atoi functions converts string literal to int
}

Sample conversion

"123"-----> 123
"123a"----> 123
"a123"----> 0
"abc"-----> 0
"123\0123" ----> 123

as soon anything other than numeric literal is encountered then, the function will return whatever value it has calculated before the non-numeric encounter happens

Also if you want more safety using strtol as pointed by @ Jonathan Leffler, his Correct usage of strtol()

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
Abhinav Singh
  • 302
  • 3
  • 15
  • 1
    Using `strtol()` allows for errors to be detected, and avoids undefined behaviour because of overflow. It requires care though — see [Correct usage of `strtol()`](https://stackoverflow.com/a/14176593/15168) for the details (or, at least, one version of the details). – Jonathan Leffler Oct 18 '20 at 21:22
0

You can analyse a string (const char *) in order to retrieve the integer value it describes as text thanks to the sscanf() standard function.

With a similar idea as printf(), a format string describes what we expect: here we want an integer so "%d" is used. This function returns the number of conversion that were successfully performed. Here we want only one conversion ("%d") so the expected result is 1. If this result is not 1, it means that the input string did not describe an integer so no value was extracted and it makes no sense using the integer (which is still uninitialised).

/**
  gcc -std=c99 -o prog_c prog_c.c \
      -pedantic -Wall -Wextra -Wconversion \
      -Wc++-compat -Wwrite-strings -Wold-style-definition -Wvla \
      -g -O0 -UNDEBUG -fsanitize=address,undefined

  $ ./prog_c 2 abc 10 def
  argv[0] is <./prog_c>
  argv[1] is <2>
    square of value is 4
  argv[2] is <abc>
  argv[3] is <10>
    square of value is 100
  argv[4] is <def>
**/

#include <stdio.h>

int
main(int argc,
     char **argv)
{
  for(int i=0; i<argc; ++i)
  {
    printf("argv[%d] is <%s>\n", i, argv[i]);
    int value;
    if(sscanf(argv[i], "%d", &value)==1)
    {
      printf("  square of value is %d\n", value*value);
    }
  }
  return 0;
}
prog-fh
  • 13,492
  • 1
  • 15
  • 30
  • It seems odd to try converting the program name to an integer. – Jonathan Leffler Oct 18 '20 at 21:20
  • @JonathanLeffler Yes, it was intentional, in order to show that unlike `atoi()` you can test whether the string contained the expected information or not (`argv[0]` is just a regular argument from this point of view). – prog-fh Oct 18 '20 at 21:24