向接受二维数组的函数传递指针数组时的输出异常问题
为什么func函数中的
printf("%s\n", *(str+1));无法输出"World"? 先看你的代码:
#include <stdio.h> char *gstr[] = { "Hello", "World" }; void func(char str[][8]) { printf("%p\n", (void *)str); printf("%p\n", (void *)(str + 1)); printf("%s\n", *(str + 1)); } int main(void) { printf("%p\n", (void *)gstr); printf("%p\n", (void *)(gstr + 1)); printf("%s\n", *(gstr + 1)); printf("Calling Function\n"); func(gstr); return 0; }
运行输出:
0x556f11ddd010 0x556f11ddd018 World Calling Function 0x556f11ddd010 0x556f11ddd018 $��oU
咱们直接说核心问题:你传入func的参数类型和函数期望的类型不匹配,这直接导致了指针解析出错。
- 先看全局变量
gstr:它是char *gstr[],本质是一个指针数组——数组里的每个元素都是指向字符串的char*指针。你的环境是64位系统,每个指针占8字节,所以gstr+1会偏移8字节,刚好指向数组里的第二个指针(也就是指向"World"的那个指针)。 - 再看
func的参数char str[][8]:这是声明了一个二维字符数组,当它作为函数参数时,会自动退化为指向char[8]的指针(也就是char (*str)[8])。这时候str+1的偏移量是8字节,因为它指向的是8字节大小的字符数组元素。
现在矛盾点来了:你把char**类型的gstr传给了期望char (*)[8]类型参数的func。虽然两者的地址值看起来一样(输出的前两个地址完全相同),但指针的类型决定了它如何解析内存中的内容:
- 在
main函数里,*(gstr+1)是取指针数组的第二个元素,也就是那个指向"World"的char*指针,所以printf("%s")能正确识别并打印字符串。 - 在
func函数里,str被当作char (*)[8]类型处理,*(str+1)会从str的地址偏移8字节后,取出一段8字节的内容当作字符数组。但实际上这个位置存储的是gstr数组的第二个元素(也就是指向"World"的指针值),而不是字符串本身!把指针的二进制值直接当作字符串输出,自然就会出现乱码——因为这些二进制值并不是有效的ASCII字符序列,也没有字符串结束符'\0'来终止输出。
那怎么修复?只需要把func的参数类型改成和gstr匹配的类型就行,比如写成char *str[](或者等价的char **str):
void func(char **str) { printf("%p\n", (void *)str); printf("%p\n", (void *)(str + 1)); printf("%s\n", *(str + 1)); }
修改之后,func里的str就和main里的gstr是同一种指针类型了,*(str+1)能正确拿到指向"World"的指针,printf也就可以正常输出字符串了。
内容的提问来源于stack exchange,提问作者Shockline
相关产品推荐
相关产品推荐

