C学习小问题2

1.一维数组: float mark[100];

每个数据元素占用的字节数,就是基类型的字节数一个元素占4个字节

2.如果想使一个数组中全部元素值为0,可以写成:

      int  a10={0,0,0,0,0,0,0,0,0,0};   

     int a10={0};

      不能写成:int a10={0*10};

 

3. 数组的地址,a&a

int a[10]    a和&a

一个师的兵力站成一列,也就是十三连和十三连的第一个人分别在什么位置...

4. 我们可以把二维数组看作是一种特殊的一维数组:它的元素又是一个一维数组。

可以把a看作是一个一维数组,它有3个元素:a0]、a1]、a2],每个元素又是一个包含4个元素的一维数组。

      a[3][4]

 

5. 4种方法对二维数组初始化:

.分行给二维数组赋初值。

例如: int a[3][4]={{1234}{5678},  

 {9101112}};

 

.可以将所有数据写在一个花括号内,按数组排列的顺序对各元素赋初值。

例如:

int a[3][4]={123456789101112};

.可以对部分元素赋初值。

例如: int a[3][4]={{1}, {5}, {9}};也可以对各行中的某一元素赋初值,如int a[3][4]={{1}, {0,6}, {0, 0, 0, 11}};

 

.如果对全部元素都赋初值,则定义数组时对第一维的长度可以不指定,但第二维的长度不能省。

例如:

int a[3][4]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};等价于:、int a[ ][4]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

 

 

6.数组a[3][4],哪个不能表示a[1][1]

*(a[1] + 1)    

*(&a[1][1])

(*(a + 1))[1]

*(a + 5)

 

1)用“%s”格式符输出字符串时,printf函数中的输出项是字符数组名,而不是数组元素名。

2)如果数组长度大于字符串实际长度,也只输出到遇′\0′结束。

4)如果一个字符数组中包含一个以上′\0′,则遇第一个′\0′时输出就结束。

5)可以用scanf函数输入一个字符串。

 

7.   C程序:

只包含一个主函数main()

也可以包含一个主函数和若干个其它函数(库函数和自定义函数)

 

库函数(Library function)是把函数放到库里,供别人使用的一种方式。.方法是把一些常用到的函数编完放到一个文件里,供不同的人进行调用。调用的时候把它所在的文件名用#include<>加到里面就可以了。一般是放到lib文件里的。

 

 

8. 形参与实参

形式参数:定义函数时函数名后面括号中的变量名

  比较两个数并输出大者

#include <stdio.h>

void main()

{   int a,b,c;

    scanf("%d,%d",&a,&b);

    c=max(a,b);

    printf("Max is %d",c);

}

int max(int  x, int  y)

{   int z;

    z=x>y?x:y;

    return(z);

}

 

9. extern

 

 

 

10. Autoregisterexternstatic关键字的使用,详细说明

 

首先得说明什么叫编译单元。每个 .c 文件会被编译为一个 .o 文件,这个就是一个编译单元。最后所有的编译单元被链接起来,就是一个库或一个程序。 

一个变量/函数,只要是在全局声明的,链接之后都隐含地在所有编译单元中可见。但你的声明可能仅出现在一个 .c 文件中,这就暗示你不想把这个名字暴露给其它编译单元,这种情况下就得用 static 关键字,表示这个名字具有内部链接,只对当前编译单元有效。但还有一种可能,你确实想暴露这个名字,但其它的编译单元希望知道这个名字被声明为什么类型,所以你需要在别的编译单元中用 extern 关键字描述这个声明,表示它具有外部链接,是在别的编译单元中定义的。不过通常的办法是在头文件中写出这个声明,让需要这个声明的文件包含它。 

那么函数中的 static 变量是怎么回事呢?前面已经说过,static 代表内部链接,就是说这个变量是定义在编译单元上的,程序开始执行前就已经存在,所以会有函数退出后仍保持值的效果;与此相对,函数中定义的自动变量是定义在栈上的,函数执行结束函数调用的活动记录就被清除。 

总结下来就是,extern/static 指出一个名字具有外部链接还是内部链接;名字的作用域只和名字被定义的位置有关。 

 

 

 

 

C中的autostaticregisterextern的区别

 

C语言中的每一个变量和函数有两个属性:数据类型和数据的存储类别。数据类型(整形、字符型等),存储类别是指数据在内存中存储的方法,存储方法有两大类:静态存储类和动态存储类。具体包括四种:自动的(auto),静态的(static),寄存器的(register)和外部的(extern)。

 

auto变量:函数中的局部变量,如不专门声明static,一般都是动态地分配存储空间。自动变量:在调用该函数时系统会给他们分配存储空间,一旦函数调用结束这些存储空间就会自动释放。关键字“auto”可以省略,不写则隐含确定为自动存储类别,属于动态存储方式。

 

static声明变量:用static声明的静态局部变量,在函数调用结束后不消失,反而保留当前的数据,在下一次该函数调用时,该变量现有的值就是上一次函数调用结束时的值。

 

一般用static声明一个变量的作用有二:(1)对局部变量用static声明,则为该变量分配的空间在整个程序执行期间始终存在。(2)对全部变量用static声明,则该变量的作用域只限于本文件模块,即被声明的文件中。

 

egf(int a)

 

       {

 

           auto b=0;               //b定义为auto类型。

 

           static c=3;              //c定义为static类型。

 

           b=b+1,c=c+1;

 

           return(a+b+c);

 

        }

 

      main()

 

       {

 

        int a=2,i;

 

        for(i=0;i<3;i++)

 

         printf("%d",f(a));

 

       }

 

在第一次调用f函数时b=0,c=3,第一次调用结束后b=1,c=4a+b+c=7;执行完之后由于c是静态局部变量,在函数调用结束后,它并不释放,所以保留c=4。而b还是0。所以程序输出7,8,9

 

static还可以声明函数,egstatic int funint a, int b)称fun为内部函数,或者静态函数。内部函数的使用只限于所在文件,而且不同文件中的同名内部函数互不干扰。

 

register变量:一般变量的值都是存储在内存中,(当程序需要用到哪一个变量的值,由控制器发出指令将内存中该变量的值送到运算器,完了如果需要存数,再从运算器将数据送到内存中存放。)所以就引出一个问题,如果我们进行一段频繁的运算,则存储变量的值肯定要花费不少时间,所以C语言允许将局部变量的值存放在寄存器中,这样需要时就直接搬用,不必再进行过内存。提高运算速度。

 

extern声明外部变量:外部变量(即全局变量)是在函数的外部定义的。作用域为从变量的定义处开始,到本程序文件的结尾。可以在一个文件内声明外部变量,如:

 

     main()

 

     {

 

       extern A,B;

 

       printf("%d",max(A,B));

 

     } int A=13,B=-8;

 

也可以在多文件的程序中声明外部变量。

 

extern还可声明函数,egextern int funint a, int b);声明的外部函数可供其他文件调用,在C中,定义函数时省略extern,则隐含为外部函数

另附加一个两个关键字constvolitate  

 

别人问起,不能简单说const表示常数,这样会让别人觉得很外行。或许可以说是只读,其实也不完全正确。务必要弄清楚一下几个定义的含义:

 

const int a;       //a是一个常整型数

int const a;      //a是一个整型常数

const int *a;    //a是一个指向常整型数的指针,从这里可以看出整型数不可以修改,但指针可以。

int * const a;   //a是一个指向整型数的常指针,整型数可以修改,指针不能修改。

int const * a const;   //a是一个指向常整型数的常指针。

 

如果能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字 const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:

1). 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)

2). 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。

3). 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

 

关键字volatile有什么含意 并给出三个不同的例子。

 

 

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

1). 并行设备的硬件寄存器(如:状态寄存器)

2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

3). 多线程应用中被几个任务共享的变量

回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。

假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。

1). 一个参数既可以是const还可以是volatile吗?解释为什么。

2). 一个指针可以是volatile 吗?解释为什么。

3). 下面的函数有什么错误:

int square(volatile int *ptr)

{

return *ptr * *ptr;

}

下面是答案:

1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

3). 这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

int square(volatile int *ptr)

{

int a,b;

a = *ptr;

b = *ptr;

return a * b;

}

由于*ptr的值可能被意想不到地该变,因此ab可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:

long square(volatile int *ptr)

{

int a;

a = *ptr;

return a * a;

}

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值