Linux入门学习教程:GNU C及将Vim打造成C/C++的半自(2)

void func1(void* __restrict__ p1, void* __restrict__ p2, void* __restrict__ p3, int size){ for(int i=0; i<size; i++){ p3[i] = p1[i] + p2[i]; } }

相当于明确告诉编译器这几块内存不会重叠,所以编译器就可以放心大胆对程序进行优化。

  另一个关键字是_Complex,C99才引入,而且需要包含<complex.h>头文件。其实在GNU C中,早就有__complex__、__real__、__imag__等扩展关键字。如下代码:

1 #include <stdlib.h> 2 #include <stdio.h> 3 4 int main(){ 5 __complex__ a = 3 + 4i; 6 __complex__ b = 5 + 6i; 7 __complex__ c = a + b; 8 __complex__ d = a * b; 9 __complex__ e = a / b; 10 printf("a + b = %f + %fi\n", __real__ c, __imag__ c); 11 printf("a * b = %f + %fi\n", __real__ d, __imag__ d); 12 printf("a / b = %f + %fi\n", __real__ e, __imag__ e); 13 return 0; 14 }

  可以看到,在C语言中也可以直接对复数进行计算。数值计算再也不是Fortran的专利。

感悟二:指针和数组还真是不一样

  从学C语言开始,老师就教导我们说指针和数组是一样的,它们可以用同样的方式进行操作。而事实上,指针和数组还是有差别的。直到多年后读《C专家编程》,才直到所谓指针和数组一样是一个美丽的错误,只是因为在《The C Programming Language》这本书里,把“作为函数参数时,指针和数组一样”这样一句话前后分开分别印到了两页而已。

  比如,指针不保存数据的长度信息,而数组有,如下代码:

1 #include <stdlib.h> 2 #include <stdio.h> 3 4 int main(){ 5 int* p = (int*)malloc(100*sizeof(int)); 6 int arr[100] = {0}; 7 printf("The size of p: %d\n", sizeof(p)); 8 printf("The size of arr: %d\n", sizeof(arr)); 9 return 0; 10 }

这段代码的运行结果为:

The size of p: 8 The size of arr: 400

  我们经常可以使用如下的代码片段来获得一个数组中有多少个元素,如下:

int arr[100]; size_t length = sizeof(arr)/sizeof(int);

  但是,当使用数组作为函数的参数的时候,数组会退化成指针。如下代码:

1 #include <stdlib.h> 2 #include <stdio.h> 3 4 void test_array(int arr[]){ 5 printf("The size of arr in function: %d\n", sizeof(arr)); 6 return; 7 } 8 9 int main(){ 10 int arr[100] = {0}; 11 printf("The size of arr in main: %d\n", sizeof(arr)); 12 test_array(arr); 13 return 0; 14 }

这段代码的运行结果为:

The size of arr in main: 400 The size of arr in function: 8

感悟三:C语言中的不完全类型(Incomplete Types)

  在GNU C中可以定义不完全类型,不完全类型主要有两种,一种是空的结构,一种是空的数组,比如:

struct point; char name[0];

空的结构不能定义变量,只能使用空结构的指针。空结构可以在后面再将它补充完整,如下:

struct point{ int x,y; };

空结构在定义链表的时候经常用到,如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/16706.html