I'm writing a program to check to see if a port is open in C. One line in particular copies one of the arguments to a char array. However, when I try to compile, it says:
error: incompatible types in assignment
Heres the code. The error is on the assignment of addr
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
u_short port; /* user specified port number */
char addr[1023]; /* will be a copy of the address entered by u */
st开发者_开发技巧ruct sockaddr_in address; /* the libc network address data structure */
short int sock = -1; /* file descriptor for the network socket */
port = atoi(argv[1]);
addr = strncpy(addr, argv[2], 1023);
bzero((char *)&address, sizeof(address)); /* init addr struct */
address.sin_addr.s_addr = inet_addr(addr); /* assign the address */
address.sin_port = htons(port); /* translate int2port num */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (connect(sock,(struct sockaddr *)&address,sizeof(address)) == 0) {
printf("%i is open\n", port);
}
if (errno == 113) {
fprintf(stderr, "Port not open!\n");
}
close(sock);
return 0;
}
I'm new to C, so I'm not sure why it would do this.
addr
is an array so you can't assign to it directly.
Change addr = strncpy(addr, argv[2], 1023);
to strncpy(addr, argv[2], 1023);
A pointer to what you passed in is returned, but this value isn't needed. The call to strncpy
alone will copy the string from argv[2]
to addr
.
Note: I notice sometimes you pass in the address of your array and sometimes you pass in the array itself without the address of operator.
When the parameter only asks for char*
...
Although both will work passing in addr
instead of &addr
is more correct. &addr
gives a pointer to a char array char (*)[1023]
whereas addr
gives you a char*
which is the address of the first element. It usually doesn't matter but if you do pointer arithmetic then it will make a big difference.
You've gotten a couple of answers that address exactly what you asked. My advice would be to step back and just eliminate that step, as it's completely unnecessary. I'd change these lines:
u_short port; /* user specified port number */
char addr[1023]; /* will be a copy of the address entered by u */
struct sockaddr_in address; /* the libc network address data structure */
port = atoi(argv[1]);
addr = strncpy(addr, argv[2], 1023);
bzero((char *)&address, sizeof(address)); /* init addr struct */
address.sin_addr.s_addr = inet_addr(addr); /* assign the address */
address.sin_port = htons(port); /* translate int2port num */
to something like this:
struct sockaddr_in address = {0};
address.sin_port = htons(atoi(argv[1]));
address.sin_addr.s_addr = inet_addr(argv[2]);
The existing code is doing a lot of unnecessary copying, making the code bigger and slower without accomplishing anything.
Edit: looking at it again, you should probably add a bit of error checking code (before what's above), something like:
if (argc != 3) {
fprintf(stderr, "Usage: %s <port_num> <address>", argv[0]);
return EXIT_FAILURE;
}
The line
addr = strncpy(addr, argv[2], 1023);
should be just
strncpy(addr, argv[2], 1023);
note that strncpy doesn't null-terminate if the 1023 limit is reached so you should also have
addr[1023] = `\0`;
though I suppose there's other assumptions made in the code as well.
an alternative is to use a char * instead:
char *addr;
addr = strdup(argv[2]);
strdup is basically a shortcut that does a malloc and a strcpy, and you don't have to worry about the size of addr upfront.
Don't forget to free addr once you're done.
Note that if argv[2] is NULL you will get a segfault.
精彩评论