C专家编程整理笔记

C专家编程整理笔记


转自:<<C专家编程>>


1.关于限定符


C语言规定,合法的指针赋值两个操作数都是指向有限定符或无限定符的相容类型的指针。左边指针所指向的类型
必须是右边指针所指向类型的全部限定符。比如,

char *cp;
const char *ccp;
ccp = cp;

左操作数是一个指向有const限定符的char的指针,右操作数是指向没有限定符的char的指针。char与char相容,左边包含右边,所以赋值合法。但是反过来就会有编译警告。

"error C2440: '=' : cannot convert from 'const char *' to 'char *'"



2.关于联合


联合与结构最大的区别是后者每个成员依次存储,而联合每个成员都从偏移地址零开始存储,每个成员的位置重叠在一起,某个时刻只有一个成员真正被使用。


一个比较常用的是如下面这样的用法,
union bits32_tag
{
	int whole;
	struct {char c0, c1, c2, c3;} byte;
}value;

使用时可以提取一个32位的整数,也可以提取某个字节。


3.关于指针的初始化


定义指针时,并不分配空间,只是分配指针本身的空间。除非在定义时用字符串常量初始化,
char *p = "breadfruit";

只有字符串常量才可以这样初始化,其它不行,比如,
float *pip = 3.14; //error

另外注意,指针字符串常量是不可以修改的。


4.数组之间不能直接赋值


有一样操作只能在指针里进行而无法在数组中进行,就是修改直接修改数组值,看下面的代码


int array[100], array2[100];


void fun1(int *ptr)
{


	ptr[1] = 3;
	*ptr = 3;
	ptr = array2;
}


void fun1(int arr[])
{
	
	arr[1] = 3;
	*arr = 3;
	arr = array2;
}


int main(int argc, char* argv[])
{
	


	array[1] = 3;
	*array = 3;
	array = array2;// error,这里会报错。




	return 0;
}

fun2里数组之所以能被直接赋值,是因为它作为参数传进来时已经被当作指针处理了。


5.用指针数组代替二维数组


下面两种写法作用是一样的,


char vegetables[][10] = {
		"carrot",
		"celery",
		"corn",
};


char *vegetables[] = {
	"carrot",
		"celery",
		"corn",
};

但是注意这样的用法只能用在字符串常量上,其它类型是不能这样的,比如下面的代码就会报错,

int *weights[] = {
	
		{1,2,3,4,5},
		{6, 7},
		{8,9,10}


	};


如果非要这样做,可以先创建几个单独的数组,在用这些数组初始化原先的数组,如下:
int row_1[] = {1,2,3,4,5};
int row_2[] = {6, 7};
int row_3[] = {8,9,10};


int *weights[] = {
	
		row_1,
		row_2,
		row_3


	};
	


6.关于数组和指针的地址


看下面代码的输出结果,


char ga[] = "abcdef";


void my_array_func(char ca[10])
{


	printf("addr of array param = %#x \n",  &ca);
	printf("addr of array param = %#x \n",  ca);
	printf("addr of array param[0] = %#x \n",  &(ca[0]));
	printf("addr of array param[1] = %#x \n",  &(ca[1]));
}


void my_pointer_func(char *pa)
{


	printf("addr of ptr param = %#x \n",  &pa);
	printf("addr of ptr param = %#x \n",  pa);
	printf("addr of ptr param[0] = %#x \n",  &(pa[0]));
	printf("addr of ptr param[1] = %#x \n",  &(pa[1]));
}






int main(int argc, char* argv[])
{
	printf("addr of ga = %#x \n",  &ga);
	printf("addr of ga = %#x \n",  ga);
	printf("addr of ga param[0] = %#x \n",  &(ga[0]));
	printf("addr of ga param[1] = %#x \n",  &(ga[1]));
	printf("****************************** \n");
	my_array_func(ga);
	printf("****************************** \n");
	my_pointer_func(ga);


	return 0;
}

输出:

addr of ga = 0x425168
addr of ga = 0x425168
addr of ga param[0] = 0x425168
addr of ga param[1] = 0x425169
******************************
addr of array param = 0x12fef8
addr of array param = 0x425168
addr of array param[0] = 0x425168
addr of array param[1] = 0x425169
******************************
addr of ptr param = 0x12fef8
addr of ptr param = 0x425168
addr of ptr param[0] = 0x425168
addr of ptr param[1] = 0x425169
Press any key to continue

只说比较难理解的。第一段,&ga当然是数组的地址,ga为什么也是同样的结果呢?这只是刚好C语言规定数组名就是数组地址,所以&ga和ga结果相同。第二段,&ca和ca不相等,这是因为数组作为参数传递时就会变为指针,&ca是取的指针的地址(也就是数组的地址所在的地址)。第三段与第二段原理一样。


你可能感兴趣的:(c,数组,指针,专家编程)