起源
事情是这样的,我在编写一段Unicode解析的代码时,需要先判断输入的Unicode后面从’\u’后是否为4位16进制数,如果是的话,就将这几位复制到一段字符串中并进行解析,如果不是的话则抛出异常。
这段代码如下:
1 2 3 4 5 6 7 8 9
| char *high = NULL, *low = NULL; p = charcpy(p, high); if(!p)return NULL; if(*p == '\\'){ p++; p = charcpy(p, low); if(!p)return NULL; }
|
其中,charcpy
函数的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| static const char* charcpy(const char* p, char* target){ target = (char *)malloc(5 * sizeof(char)); int len; for(len = 0; len < 4; len++){ int flag = ((*p)>='0' && (*p)<='9') || ((*p)>='A' && (*p)<='F') || ((*p) >= 'a' && (*p) <= 'f'); if(!flag)return NULL; target[len] = *p; p++; } printf("\n"); target[len] = '\0'; for(len = 0; len < 4; len++){ printf("%c",target[len]); } printf("\n"); return p; }
|
首先为target分配内存,然后循环判断p的值是否为16进制数,是的话则赋值给target,否则就直接返回空。
想法很美好,然而现实很崩溃。当我编译运行时则爆出segmentation fault,,这时我debug的时候,发现high仍为空,也就是说charcpy这个函数里的操作并没有改变high。
传值与传指针
C函数传递参数有两种参数,值传递与指针传递。而事实上指针传递也可以看成是值传递,只不过传的类型是指针。当我们将high指针传入函数时,此时的target指向high,但当我们为target指针分配内存的时候,此时target指针将不再指向high,而是脱离出来重新分配内存。解决方法则是使用二重指针传递,当我们使用二重指针的时候,此时target与&high等价,因此我们对*target进行分配内存时,则可以对high进行修改了。
修改后代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| static const char* charcpy(const char* p, char** target){ *target = (char *)malloc(5 * sizeof(char)); int len; for(len = 0; len < 4; len++){ int flag = ((*p)>='0' && (*p)<='9') || ((*p)>='A' && (*p)<='F') || ((*p) >= 'a' && (*p) <= 'f'); if(!flag)return NULL; (*target)[len] = *p; p++; } (*target)[len] = '\0'; for(len = 0; len < 4; len++){ printf("%c",(*target)[len]); } printf("\n"); return p; }
|