- #include <stdio.h>
-
- int main(int argc, char **argv)
- {
- char c = 0x80;
-
- printf("%02x\n", (unsigned char)c);
-
- return 0;
- }
因为%x格式化的类型是int或unsigned int, 所以c会被提升为int,
当c大于等于0x80时会被当作负数处理,为保留符号位,因此提升时
c会变为0xffffff80, 显然不正确。
C、C++中没有提供 直接获取数组长度的函数,对于存放字符串的字符数组提供了一个strlen函数获取长度,那么对于其他类型的数组如何获取他们的长度呢?其中一种方法是使 用sizeof(array) / sizeof(array[0]), 在C语言中习惯上在 使用时都把它定义成一个宏,比如#define GET_ARRAY_LEN(array,len) {len = (sizeof(array) / sizeof(array[0]));} 。而在C++中则可以使用模板 技术定义一个函数,比如:
template <class T>
int getArrayLen(T& array)
{
return (sizeof(array) / sizeof(array[0]));
}
例如:int main()
{
char a[] = {'1','2','3','4'};
int len;
GET_ARRAY_LEN(a,len)
//调用预定义的宏,取得数组a的长度,并将其存储在变量len中
printf("%d\n",len);
system("pause");
return 0;
}
3. 用数组名做函数参数可以用数组名作函数参数,此时实参与形参都应用数组名(或指针变量)。
例2:有一个一维数组score,内放10个学生成绩,求平均成绩。
float average(float array[10]){
int i;
float aver,sum=array[0];
for(i=1; i<10; i++)sum=sum+array[i];
aver=sum/10;
return aver;
}
main(){
float score[10],aver;
int i;
printf("input 10 scores:/n");
for(i=0; i<10; i++)scanf("%f",&score[i]);
printf("/n");
aver=average(score);//数组名作为函数参数
printf("average score is %5.2f",aver);
}
说明:
l 用数组名称作函数参数,应该在主调函数和被调函数分别定义数组,本例中array是形参数组名,score是实参数组名,分别在其所在的函数中定义,不能只在一方定义。
l 实参数组与形参数组类型应该保持一致(这里都为float型),如不一致,结果将出错。
l 在被调用函数中声明了形参数组的大小为10,但在实际上,指定其大小是不起任何作用的,因为C编译器对形参数组大小不做检查,只是检查实参数组的首地址传给形参数组。因此,score[n]和array[n]指的是同一单元。
l 形参数组也可以不指定大小,在定义数组时在数组名后面跟一个空的方括号,有时为了在被调用函数中处理数组元素的需要,可以另设一个参数,传递需要处理的数组元素的个数,上例可以改写为下面的形式:
float average(float array[], int n){
int i;
float aver,sum=array[0];
for(i=1; i<n; i++)sum=sum+array[i];
aver=sum/n;
return aver;
}
main(){
float score_1[5]={98.5,97,91.5,60,55};
float score_2[10]={67.5,89.5,99,69.5,77,89.5,76.5,54,60,99,5};
printf("the average of class A is %6.2f/n", average(score_1, 5));
printf("the average of class B is %6.2f/n", average(score_2, 10));
}
最后应该说明一点:用数组名作为函数实参的时,不是吧数组元素的值传递给形参,而是把实参数组的起始地址传递给形参数组。
形参数组中各个元素的值如果发生变化会使实参数组元素的值同时发生变化,从上图是很容易理解的。这一点与变量做函数参数的情况是不同的,务必注意!在程序设计中可以有意识地利用这一点。
4.总结一下C语言定义数组的几种形式:
以一维数组为例
int arr[10];
int arr[] = {1,2,4};
int arr[10] = {1,2};
int *arr = new int[10];
前面三种常常都可以用到,但使用第四种时需要注意。在.c文件里使用这种形式编译会不能通过, 但.cpp文件里是可以的,可以推断出这是C++对C的扩展。
上面的结论完全来自于Visual Studio环境下的实践,对于tc,bdc,gcc等情况下是否成立有待考证。
bug最多的还是程序端没有被执行,一般使用Debug调试,但是有的时候成百上千次的循环中不适合断点调试,所以使用串口打印,最常用的错误定位方法是:
#define MARK(s) printf("%s,%d,%s\r\n",__FILE__,__LINE__,s)
使用就是例如MARK("tangquan");,打印出来就是main.c,115,tangquan
事实上除非出现很麻烦的问题一般我不用debug,串口大部分问题都能搞定的。