罗列一下自己在工作和学习中知道的编写C程序的一些方法和技巧:
1. 在自己写的代码中,如果运行后报出段错误的提示,结合gdb调式可以进行定位,现在当前调试环境的shell中输入,ulimit -c unlimited 命令,这样在运行代码是如果出现段错误,就会在当前的运行shell中尝试core文件,此文件就是用来定位段错误的,然后在调试模式下输入,gdb a.out core ,当然必须在gdb调试模式下,然后输入where,就能定位到产生段错误的代码行。
2. 如果要在某一段程序中有这样的需求,需要在自己申请的一段内存中以某种格式填充数据,那么用结构体就能实现这样的功能,如下代码:
typedef struct {
int flag1;
int flag2;
mtxt[1];
}data_t;
在这个结构体声明中,数组的定义不需要定义成自己所需要的,在实际中,我没也不定会知道这个结构中的具体大小,这个声明,只是定义了有这么一个结构,我们在使用中,往往需要自己去malloc自己需要的大小为N的内存块,如下:
char *pdata = (char *) malloc(N*sizeof(char));
data_t *data = (data_t*)pdata // 这里对pdata进行类型强转,然后对指针data所指向的内存块进行填充,mtxt数组的空间可以在不超过malloc申请的数据大小的空间内进行填充。
典型的应用:在进程间通信方式中消息队列,中对于消息的定义结构:
struct msgbuf{
long mtype; //消息类型
char mtext[N]; //消息正文。
}
3. 在学习网络编程中,学习了一个接口,bind(int fd, const struct sockaddr *addr, socklen_t addrlen), 其中第二参数,是一个结构定义:
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
但是在实际传参的时候,根据不同的协议族,其传输的结构体是不一样的,但是为了统一接口的参数,把该参数统一成这样一个结构,比如如 果要做TCP传输,需要填充的结构体是:
/* Structure describing an Internet socket address. */
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_); // unsigned short int sin_family;
in_port_t sin_port; /* Port number. */ 0 ~ 65535
struct in_addr sin_addr; /* Internet address. */ 网络地址
/* Pad to size of `struct sockaddr'. */ 没有任何意义,主要进行大小填充 char sin_zero[8];
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
这样的设计,又体现了结构体中定义数组的优势,这个数组只是规定了这个结构类型的大小,具体的内容,可以在不超出大小的情况下,我们自 行进行填充,这样体现了设计的灵活性和兼容性。
未完待续