C语言:指针与数组的用法比较

  • Post author:
  • Post category:其他


数组是一个内存连续的整体,指针的值是另外一个变量的地址,两者的操作是有区别的。

数组名可以看作一个指针常量(但在sizeof的情况下是不成立的)

。可以查看以下例子进行比较:

// 定义
int array[10];				// 合法
int array[10] = {0, 1, 2};	// 合法
int *p;						// 合法,编译通过,但是是野指针,注意赋值,否则运行时可能出错
int *p = NULL;				// 合法

// 大小(32位机器)
sizeof(array);				// 40
sizeof(p);					// 4 

// 转换
int *p = array;				// 合法,数组名array就是个地址,等价于&array[0]
int *p = &array;			// 非法,数组名array就是个地址
int *p = array + 1;			// 合法,得到的是&array[1]
int *p = (int*)(&array + 1);// 合法,偏移整个数组,指向数组尾部的下个单元,要小心操作
p = array;					// 合法,p是用来存放地址,数组名就是该数组的起始地址
array = p;					// 非法,数组地址不可以改变
p = &array[0];				// 合法,array[0]存放的是值不是地址,所以p是要取址
*p = array[0];				// 合法,*p是存放值,可以直接赋值

// 赋值
p[1] = 1;					// 合法,指针可以类似数组一样使用,前提是指针p所指向的地址是分配内存了的
array[1] = 1;				// 合法,基本用法
*p = 2;						// 合法,基本用法
*array = 2;					// 合法,既然数组名是地址,那么加上*就可以装值,等价于array[0] = 2;

// 偏移
p++;						// 合法,指针指向下一个地址
array++;					// 非法,数组地址不可以改变
*p++ = 1;					// 合法,给p指向的地址赋值,注意优先级: ++ 高于 *
*(array++) = 1;				// 非法,数组地址不可以改变
(*p)++;						// 合法,指针指向地址的值加1
(*array)++;					// 合法,数组名是地址,等价于array[0]++;
*(p + 1) = 2;				// 合法,给p指向的下一个地址赋值,前提是指针p所指向的地址是分配内存了的
*(array + 1) = 2;			// 合法,数组名是地址,只要不修改array本身的值(地址)即可


定义字符串

char str[] = "Hello";
char *p = "Hello";

str[1] = 'E';
p[1] = 'E';		// 存储在常量区(只读),编译时不会报错,运行时出错


函数传参


数组和指针作为函数形参时,作用都是传递一个地址,而不是拷贝一个数组进去,所以参数可以写成a[]或*a,因为都只是传递一个地址。而数组作为形参传递进去之后是可以进行a++的,这个和数组变量不一样,另外,不能对传进来的参数进行sizeof计算字符串长度,因为传递进来的是一个地址。

也只有在作为函数形参时,一级指针和一维数组是完全等价的,二级指针和二维数组可就不一样了。

例如:

// 32位机器上运行
int test(char arr[100]char *p)
{
	printf("size: %d\n", sizeof(arr));	// 一直都是4,传的是地址
	printf("size: %d\n", sizeof(p));
}



版权声明:本文为weixin_44498318原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。