shell 可变参数_linux游戏模拟器

(1) 2024-09-22 16:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
shell 可变参数_linux游戏模拟器,希望能够帮助你!!!。

strcpy与strncpy

#include <string.h> char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, size_t n);

strcpy在拷贝字符串时会把结尾的'\0'也拷到dest中,因此保证了dest中是以'\0' 结尾的字符串。但是另外一个要注意的问题是,strcpy只知道src字符串的首地址,不知道长度,它会一直拷贝到'\0'为止,所以dest所指向的内存空间要足够大,否则有可能会越界,例如:

char buf[10]; strcpy(buf, "hello wrold");

strncpy的参数n 指定最多从src中拷贝n个字节到dest中,换句话说,如果拷贝到'\0'就结束,如果拷贝到n个字节还没有碰到'\0', 那么也结束,使用者需要提供适当的n值,以确保读写不会越界,比如让n的值等于dest所指向的内存空间的大小:

char buf[10]; strncpy(buf, "hello world", sizeof(buf));

文档中特别用Warning指出,这意味着dest有可能不是以'\0'结尾的。上面的调用,虽然把"hello wrold"截断到10个字符拷贝到buf中,但buf不是以'\0'结尾的,如果在printf(buf)就会读越界,需要确保dest以'\0'结束,可以这么调用:

char buf[10]; strncpy(buf, "hello world", sizeof(buf)); buf[sizeof(buf) - 1] = '\0';

malloc与free

#include <stdlib.h> void *malloc(size_t size); 返回值:成功返回所分配内存空间的首地址,出错返回NULL。 void free(void *ptr);

malloc 的参数size表示要分配的字节数,如果分配失败(可能由于系统内存耗尽)则返回NULL。由于malloc 函数不知道用户拿到这块内存要存放一些什么类型的数据,所以返回通用指针void *, 用户程序可以转换成其它类型的指针再访问这块内存。malloc 函数保证它返回的指针所指向的地址满足系统的对齐要求,例如在32位平台上返回的指针一定对齐到4字节边界。以保证用户程序把它转换成任何类型的指针都能用。

动态分配的内存用完之后可以用free释放掉,传给free的参数正是先前malloc返回的内存块首地址,如下:

#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { int number; char *msg; } unit_t; int main(void) { unit_t *p =(unit_t*)malloc(sizeof(unit_t)); if (p == NULL) { printf("out of memory\n"); exit(1); } p->number = 3; p->msg = (char*)malloc(20); strcpy(p->msg, "Hello world!"); printf("number: %d\nmsg: %s\n", p->number, p->msg); free(p->msg); free(p); p = NULL; return 0; }

需要注意以下几点:

  1. unit_t p = malloc(sizeof(unit_t)); 等号右边是void 类型,等号左边是unit_t 类型,编译器会做隐式类型转换,void* 和任何指针类型之间可以相互隐式转换。
  2. 虽然内存耗尽是很不常见的错误,但写程序要规范,malloc 之后应该判断是否成功。
  3. free(p) 之后,p 所指的内存空间是归还了,但是p的值并没有变,p现在指向的内存空间已经不属于用户了,p 成了野指针,为避免出现野指针,在free(p)之后手动置p = NULL。
  4. 先free(p->msg), 再free(p), 如果先free(p), p成了野指针,就不能通过p->msg访问内存了。
  5. 内存泄漏的Bug很难找到,因为它不会像访问越界一样导致程序运行错误,少量内存泄漏并不影响程序的正确运行,大量的内存泄漏会使系统内存紧缺,导致频繁换页,不仅影响当前进程,而且把整个系统都拖得很慢。

可变参数

带可变参数的函数printf:

int printf(const char *format, ...);

要处理可变参数,需要使用C标准库的va_list 类型和 va_start, va_arg, va_end宏,这些定义在stdarg.h头文件中。

还用一种方法可以确定可变参数的个数,就是在参数列表的末尾传一个Sentinel, 例如NULL。实现一个printlist 函数,可以打印若干个传入的字符串。

#include <stdio.h> #include <stdarg.h> void printlist(int begin, ...) { va_list ap; char *p; va_start(ap, begin); p = va_arg(ap, char *); while (p != NULL) { printf("%s\n", p); p = va_arg(ap, char*); } va_end(ap); } int main(void) { printlist(0, "hello", "world", "foo", "bar", NULL); return 0; }

printlist 的第一个参数begin的值并没有用到,但是C语言规定至少要定义一个有名字的参数,因为va_start宏要用到列表中最后一个有名字的参数,从它的地址开始找可变参数的位置。

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复