【错误记录】关于C语言指针和数组

最近在写一道算法题目时犯了一个关于C语言的指针的错误,写下这篇帖子记录一下,避免再犯。

错误主要关于传递一个初始长度不定的二维数组参数,然后通过指针的方式读写该数组。主要错误代码如下:

#include <stdio.h>
#include <stdlib.h>
#define N 5    //假设N大于2且在程序运行之前是未定的
void  PointerTest(char ** param );

int main()
{
    char test[N][N];
    int i ,j;
    for (i = 0; i < N; i++)
       for (j = 0; j < N; j++)
            test[i][j] = -1;
    PointerTest(test );
    return 0;
}

void  PointerTest(char ** param)

{

    char temp;
    temp = param[1][1];//此句发生错误

}

每次执行到 temp = param[1][1];时就会发生错误,提示非法访问。

我苦逼的在调用之前各种找,各种检查,就是没发现错误哭。后来仔细检查指针才发现是指针的使用出错了。

param是一个char**类型的形参,所以param[0]=*param,*param是一个char*型的变量,所以*param是一个指针数据四个字节,就是原数组test[0][0]~test[0][3]的数据。而原数组test[0]是一个char[5]型数据,就是指向test[0][0]的指针。也就是说若test地址为0x00123456,param+1的地址就是0x123456+4=0x12345A,一个指针的长度;而test+1的地址就是0x123456+5=0x12345B,一个char[5]的长度。

这样也就能解释访问param[1][1]出错了,因为param[1]的值是test[0][4]~test[0][7],是非法的地址空间。

因此要正确的访问就应该使用*(param+i)这种方式读取test数组的值。

下面一段程序就很直观的显示了我所犯的的错误。


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

void  PointerTest(char ** param1 ,char param2[][5]);

int main()
{
	char test[5][5];
	int i ,j,m=0;
	for (i = 0; i < 5; i++)
	for (j = 0; j < 5; j++)
		test[i][j] = m++;


	PointerTest(test ,test);
	return 0;
}

void  PointerTest(char ** param1 ,char param2[][5])
{
	printf("Param1 Addr=0x%08X\n",param1);
	printf("Param2 Addr=0x%08X\n" ,param2);
	printf("Param1 size=0x%08X\n" ,sizeof(param1));
	printf("Param2 size=0x%08X\n" ,sizeof(param2));
	printf("****************************\n");
	printf("*Param1 Addr=0x%08X\n" ,*param1);
	printf("*Param2 Addr=0x%08X\n" ,*param2);
	printf("****************************\n");
	printf("*Param1+1 Addr=0x%08X\n" ,*(param1 + 1));
	printf("*Param2+1 Addr=0x%08X\n" ,*(param2 + 1));
	printf("****************************\n");
	printf("Param1[0] Addr=0x%08X\n" ,param1[0]);
	printf("Param1[1] Addr=0x%08X\n" ,param1[1]);
	printf("Param1[2] Addr=0x%08X\n" ,param1[2]);
	printf("------------------------------\n");
	printf("Param2[0] Addr=0x%08X\n" ,param2[0]);
	printf("Param2[1] Addr=0x%08X\n" ,param2[1]);
	printf("Param2[2] Addr=0x%08X\n" ,param2[2]);
	printf("****************************\n");
	printf("Param1[0][0] Addr=0x%08X\n" ,&param1[1][1]);
	printf("Param2[0][0] Addr=0x%08X\n" ,&param2[0][0]);
	printf("****************************\n");
	system("pause");
	return;


}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值