LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2464|回复: 12

给指针赋值的问题

[复制链接]
发表于 2004-9-8 16:45:09 | 显示全部楼层 |阅读模式
俺的书上说,不能直接给指针赋值,可能发生溢出
书上举的例子是这样的:
  1. swap(int *p1,int *p2)
  2. {
  3.     int *temp;
  4.     *temp=*p1;
  5.     *p1=*p2;
  6.     p2=*temp;
  7. }
复制代码


据说这样的程序有时候能正确运行,但是*temp变量没有确定的地址址,可能会产生不可遇见的情况;

不过,偶到另一本书上的例子
  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <arpa/inet.h>
  5. #include <netdb.h>
  6. char *host_name="127.0.0.1";
  7. int port=8000;
  8. void main(int argc,char *argv[]){
  9.     char buf[8129];
  10.     char message[256];
  11.     int socket_descriptor;
  12.     struct sockaddr_in pin;
  13.     struct hostent *server_host_name;

  14.     char *str="A default test string";
  15.     if(argc<2){
  16.         printf("Usage:test "Any test string"\n");
  17.         printf("We will send a default test string.\n");
  18.     }

  19.     else{
  20.         str=argv[1];
  21.     }

  22.     if((server_host_name=gethostbyname(host_name))==0)
  23.     {
  24.         perror("Error resolving local host\n");
  25.         exit(1);
  26.     }

  27.     bzero(&pin,sizeof(pin));
  28.     pin.sin_family=AF_INET;
  29.     pin.sin_addr.s_addr=htonl(INADDR_ANY);
  30.     pin.sin_addr.s_addr=((struct in_addr *)(server_host_name->h_addr))->s_addr;
  31.     pin.sin_port=htons(port);

  32.     if((socket_descriptor=socket(AF_INET,SOCK_STREAM,0))==-1){
  33.         perror("Error opening socket\n");
  34.         exit(1);
  35.     }
  36.     if(connect(socket_descriptor,(void *)&pin,sizeof(pin))==-1){
  37.         perror("Error connecting to socket\n");
  38.         exit(1);
  39.     }

  40.     if(send(socket_descriptor,str,strlen(str),0)==-1){
  41.         perror("Error in send\n");
  42.         exit(1);
  43.     }

  44.     printf("..sent message.. wait for response...\n");
  45.     if(recv(socket_descriptor,buf,8192,0)==-1){
  46.         perror("Error in receiving response form server\n");
  47.         exit(1);
  48.     }

  49.     printf("\nResponse from server:\n\n%s\n",buf);
  50.     close(socket_descriptor);
  51. }
复制代码


第15行 char *str="A default test string";可以吗?
编译器能够自动分配地址吗?

第25行 if((server_host_name=gethostbyname(host_name))==0)
gethostbyname返回一个指针struct hostent类型的指针,这个指针的地址是什么是什么时候分配的?

还有,第34行 pin.sin_addr.s_addr=((struct in_addr *)(server_host_name->h_addr))->s_addr;
到底是什么东西,不很理解
查了struct hostent
  1. struct hostent
  2. {
  3.   char *h_name;                 /* Official name of host.  */
  4.   char **h_aliases;             /* Alias list.  */
  5.   int h_addrtype;               /* Host address type.  */
  6.   int h_length;                 /* Length of address.  */
  7.   char **h_addr_list;           /* List of addresses from name server.  */
  8. #define h_addr  h_addr_list[0]  /* Address, for backward compatibility.  */
  9. };
复制代码


发现最后一行#define h_addr  h_addr_list[0],不明白在struct里#define是怎么一回事;

还有,第34行是对pin.sin_addr.s_addr赋值,那么第33行对pin.sin_addr.s_addr赋值又有什么意义?

问题有点多
发表于 2004-9-8 18:28:55 | 显示全部楼层
1: char *str="A default test string"定义了一个指针,这个指针指向一个字符串常量,该常量在编译时放在数据段中。
2:gethostbyname返回一个指针struct hostent类型的指针,该指针是在gethostbyname中分配的。
3:pin.sin_addr.s_addr=((struct in_addr *)(server_host_name->h_addr))->s_addr;中,h_addr 就是h_addr_list[0], h_addr_list数组保存了in_addr类型的数据,所以用(struct in_addr *)将其转化为(struct in_addr *)类型.
建议看一看Unix网络编程第1卷(stevens著),里面很详细的讲了这些结构体的作用和细节。
发表于 2004-9-8 18:44:46 | 显示全部楼层
(1)第一个程序中 p2=*temp 是把 int 型赋给 int* 型,都不知道 *temp 中是个什么数,就把它当地址用了,当然可能导致内存错误

(2)str="A default test string" 中的 "A default test string" 是在编译的时候放在只读数据段一个常量字符串,运行时将其指针赋给了str。

(3)#define 放在 struct 里面还是外面我认为是没有区别的,因为 #define 的功能是在预处理时完成的,而 struct 的作用域是在编译时处理的。而且我 man gethostbyname 时看到 #define 就是写在 struct 外面的。写在里面的目的大概是让看程序的人明白要定义的对象是 struct 的成员。

(4)pin.sin_addr.s_addr 连续赋了两次值,我认为是个错误。
 楼主| 发表于 2004-9-8 20:43:28 | 显示全部楼层
明白了,多谢了
发表于 2004-9-8 20:53:15 | 显示全部楼层
To doubleelec:
(1)"
第一个程序中 p2=*temp 是把 int 型赋给 int* 型,都不知道 *temp 中是个什么数,就把它当地址用了,当然可能导致内存错误
"
The answer has some mistakes, "p2=*temp 是把 int 型赋给 int* 型" is wrong.
"p2=*temp" :
here "*" is deference sign not pointer sign, it obtains the content of variable pointed by temp.Therefore, it's not "assign int to int*",but "assign int to int".
The problem lies in "pointer temp is not initiated".
(2)
"运行时将其指针赋给了str" give the address where keep const char string to pointer str.
(3)
"pin.sin_addr.s_addr 连续赋了两次值,我认为是个错误。"
see JBug's reply.
 楼主| 发表于 2004-9-8 21:59:38 | 显示全部楼层
最初由 quanliking 发表
To doubleelec:
(1)"
第一个程序中 p2=*temp 是把 int 型赋给 int* 型,都不知道 *temp 中是个什么数,就把它当地址用了,当然可能导致内存错误
"
The answer has some mistakes, "p2=*temp 是把 int 型赋给 int* 型" is wrong.
"p2=*temp" :
here "*" is deference sign not pointer sign, it obtains the content of variable pointed by temp.Therefore, it's not "assign int to int*",but "assign int to int".
The problem lies in "pointer temp is not initiated".
(2)
"运行时将其指针赋给了str" give the address where keep const char string to pointer str.
(3)
"pin.sin_addr.s_addr 连续赋了两次值,我认为是个错误。"
see JBug's reply.


不好意思,第一段代码我写错了,应该这样:
swap(int *p1,int *p2)
{
    int *temp;
    *temp=*p1;
    *p1=*p2;
    *p2=*temp;
}
关于赋了两次值的问题,好像JBug好像没有说到啊。
发表于 2004-9-8 22:08:37 | 显示全部楼层
I have a mistake too, sorry to doublelec. "*p2 = *temp" is right, it is "assgin int to int".
 楼主| 发表于 2004-9-8 22:17:25 | 显示全部楼层
刚才看了man gethostbyname,还有问题

       
JBug说在gethostbyname中分配struct hostent结构,这个结构是在编译时分配还是在运行中分配?如果编译时分配,名字过长的话会不会溢出?

另外,man上说, h_addr也是struct hostent的成员,总共6个成员。可是偶看不明白这种表达方法,偶是说,明明是5个成员,难道#define也算一个成员?手头没有Unix网络编程,不好意思了
发表于 2004-9-9 08:34:16 | 显示全部楼层
(1)一般从函数返回的结构或字符串指针是在函数里面 malloc 的(如果这个指针没有直接或间接的通过参数传给函数),注意编译时分配的变量应该是全局的、static 的或 const 的。

(2)说 struct hostent 有6个成员应该是从接口角度讲的,你说有5个成员是从实现角度讲的,使用这个结构的程序员来讲关注的主要是接口。

有偏颇或不足请高手补充。
发表于 2004-9-9 16:52:41 | 显示全部楼层
(1)一般从函数返回的结构或字符串指针是在函数里面 malloc 的(如果这个指针没有直接或间接的通过参数传给函数)

也有可能是static的,这样的函数不可重入
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表