day 6

复习

int a; 整型变量

int a[10]; 整型数组10个元素

int *a; 整型指针

int *a[10]; 整型指针的数组,数组中的元素是10个整型的指针

int (*a)[10]; 数组指针,指向的是由10个int类型元素组成的数组, 用来指向二维数组

int (*a[3])[10]; 指针类型的数组,3个元素,每个元素都是指向10个int类型元素的数组

int *a(int); 函数,是指针函数,返回值是int类型指针的函数,参数是int类型

int (*a)(int); 函数指针,指向参数是int,返回值是int的函数。

int *(*a)(int); 函数指针,指向参数是int,返回值是int*的函数。

int (*a[2])(int); 指针数组,2个元素,元素值函数指针,函数参数int,返回值是int。

作业:

选择题

  1. [单选题-C语言]

关于if语句,下面哪一种说法是错误的 ( D ) (牛客网)

A: 一个if只能有一个else与之配对

B: if语句中可以有多个else if子句

C: if语句中可以包含循环语句

D: if语句中不能包含switch语句

  1. [单选题-位运算]

下面关于位运算符的叙述,正确的是?( ) (牛客网)

A: #表示"按位异或"的运算

B: &表示"按位或"的运算

C: ~表示"按位取反"的运算

D: ||表示"按位或"的运算

3.[单选题-C语言]

下面哪个语句无法通过编译? ( B ) (牛客网)

A: if (x>y);

B: if (x=y) && (x!=0) x+= y;

C: if (x!=y) scanf("%d",&x); else scanf("%d",&y);

D: if (x<y) {x++; y++;}

  1. [单选-linux]

若基于Linux操作系统所开发的ARM应用程序源文件名为test.c,

那么要生成该程序代码的调试信息,编译时使用的GCC命令正确的是? ( D ) (阿里巴巴)

A: arm-linux-gcc -c -o test.o test.c

B: arm-linux-gcc -S -o test.o test.c

C: arm-linux-gcc -o test test.c

D: arm-linux-gcc -g -o test test.c

  1. [单选-C]

若整型变量a、b、c、d中的值依次为:1、4、3、2。则条件表达式a<b?a:c<d?c:d的值 ( A ) 。(牛客网)

A: 1

B: 2

C: 3

D: 4

6.[单选题-优先级]

已知int i=1, j=2;,则表达式i+++j的值为( C )。

A: 1

B: 2

C: 3

D: 4

  1. [单选题]

在软件生命周期中,( B )阶段负责“写出正确、易懂,容易维护的程序模块”。

A: 详细设计

B: 编码和单元测试

C: 确认测试

D: 总体设计

  1. [单选题]

break和continue两个都是( A ) (美行科技)

(A)控制循环指令 (B) 数据结构

© 相等的判断 (D) 不包含在C++中

  1. [单选题]

有以下程序

main()

{ int a=666,b=888;

printf("%d\n",a,b);

}

程序运行后的输出结果是( B )。

A: 错误信息

B: 666

C: 888

D: 666,888

编程题:

编写函数,[采用递归方法]实现将输入的字符串按反序输出。(北京麦邦)

函数自己调用自己

并没有改变字符串,仅仅是反着输出 “abc” 输出"cba"

void out_char(char *p)

{

}

#include <stdio.h>

void out_char(char* p)
{
	if(*p == '\0')
	{
		return;
	}
	out_char(p+1);
	printf("%c", *p);
}

int main()
{
	char* p = "hello world";
	out_char(p);
	printf("\n");
	return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q2RzL5dq-1645665244017)(C:\Users\mudonghai\Desktop\linux&C高级\day6\image-20220210102651493.png)]

一、const

作用: 使变量常量化

两种情况:

1、常量没有名字,给常量起名字,这个时候如果使用宏,全局有效。如果只在一个小作用域内使用常量,我们可以使用const定义一个变量,就相当于给常量起名字。

2、函数传参数,有一些不想被改变的参数,这个时候会使用const来定义,比如:

字符串操作函数

int strcmp(const char* s1, const char* s2);

在函数内部不可以对这两个参数修改。

两种使用情况都是为了防止我们无意间修改了不想修改的变量。

示例1:

int main()
{	
    const int a = 10;//还可以等价的写成  int const a = 10;
    a = 20;//任何尝试去修改变量a的操作,都是语法错误
    return 0;
}

linux@ubuntu:~/809$ gcc test.c -o test

test.c: In function ‘main’:

test.c:7:2: error: assignment of read-only variable ‘a’

示例2:

#include <stdio.h> 

int main()
{
	int a = 100, b = 20;
	int * const p = &b;//使用const修饰指针变量 
	p = &a;//改变指针变量p的指向   语法错误
	*p=11;//通过指针变量改变指向的变量的值
	printf("%d\n", *p);
}


#include <stdio.h>


int main()
{
	int a = 100, b = 20;
 	int const* p = &b;//可以等价写成const int* p = &b;
	p = &a;
	*p = 11;
	printf("%d\n", b);
	return 0;
}

重点:

const修饰指针变量,const可能出现在*的左边也可能出现在*的右边;出现在*的左边,修饰*p(不能通过指针去修改指针指向的变量);出现在*右边,修饰p(不能修改指针的指向)。

const出现在*左边,叫 常量指针

const出现在*右边,叫 指针常量

被const修饰的变量必须初始化。

示例3:

#include <stdio.h> 

int main()
{
	int a = 100;
	const int *p = &a; 
	a = 80;
	*p = 60;
	printf("%d\n", a);
	return 0;
}

二、数据存储类型

4种。 自动(auto)、寄存器(register)、静态存储(static)、外部存储(extern)

auto就是我们在栈空间定义的局部变量

register针对硬件编程才能用到,就是硬件中的寄存器

1. extern

静态外部链接

示例4:

///  a.c   

int a = 200;//全局变量

///  b.c   

#include <stdio.h> 

extern int a;//使用在其他文件中定义的全局变量a, a.c和b.c中的a是同一个变量

int main()
{
	printf("a = %d\n", a);
	return 0;
}

执行过程: gcc a.c b.c

2. static

修饰静态

1)static 修饰全局变量:

如果全局变量被 static 修饰,则该全局变量只能在当前文件中使用,不能被外部使用。

一个文件中的函数一般都是具有相关逻辑的,有时候同文件的函数之间需要定义全局变量,但是这个全局变量的逻辑仅仅是当前文件中的函数可以使用。这个时候要把全局变量定义层静态全局变量。

示例5:

/  a.c    

static int a = 200; //static修饰全局变量a,那么这个a只能在a.c文件中被使用  

///  b.c   

#include <stdio.h> 

extern int a; 

int main()
{
	printf("a = %d\n", a);
    return 0;
}

编译报错,因为static修饰全局变量,只能在定义它的文件中使用这个全局变量。

2)static 修饰局部变量

普通的局部变量被定义在内存什么空间?栈,函数开始执行变量被创建,函数执行完毕变量删除。

static修饰局部变量,将局部变量定义在静态空间。

被修饰的局部变量,只初始化一次。生命周期,从进程开始到结束,作用域:就在原来的作用域内。

示例6:

#include <stdio.h> 

void fun()
{
	static int a = 90; //静态局部变量,是在程序开始运行的时候创建的,作用域只能在定义它的{}里使用
    //这段代码 a只能在fun中使用
	printf(" %d \n", a);
	a++;
}

int main()
{
	fun();
	//printf(" a = %d\n",a );//语法错误,因为a的作用域只在fun函数中
	fun();
	fun();
	return 0;
}

执行结果: 90 91 92

3)static 修饰函数: 被修饰的函数,限定在当前文件内使用。

示例7:

/a.c///

static void fun()//static修饰fun函数,fun函数只能在a.c中调用
{
	printf(“hello world\n”);
}

/b.c///

void fun();
int main()
{
	fun();
	return 0;
}

编译报错

小总结:

static和const经常在面试中被一起问到,但是他俩又没有任何关系。

static修饰局部变量 生命周期变得和程序一样长,但是作用域不变

static修饰全局变量 缩小了全局变量的访问范围,只能在定义全局变量的文件中使用全局变量,生命周期没有改变

static修饰函数 缩小了函数的访问范围,只能在定义函数的文件中使用

const 将变量修饰成只读的。

常量指针 指向常量的指针,*p不能变。 const在*左边

指针常量 不能改变指向的指针,p不能变。const在*右边

三、带参宏

#define HEIGHT 21

#define WIDTH 12

宏的特点:

1) 宏是在预处理阶段完成的事,完成了用宏值把宏名替换掉。

2) 宏值是没有类型的。 宏只是简单的符号替换。无脑替。

3) 宏名字一般用大写。为了和变量做以区分。

错误范例:

//宏值后面有; 是错误,在for循环中替换宏名的时候,会把;也替换过去
#define NUM 10; 
int main()
{	
    int i;	
    for(i = 0;i < NUM;i++)
    {		
        printf("hello\n");	
    }	
    return 0;
}

宏的优势:

  1. 一改全改

  2. 使得常量有意义

示例8:

#include <stdio.h> 
//x就是带参宏的参数
#define EXPAND(x)  (10*(x))

int main()
{
    //替换后(10*(2))
	//printf(" %d \n", EXPAND(2));
    //#define EXPAND(x)  (10*x)  替换后 10*2+1
    printf(" %d \n", EXPAND(2+1));
	return 0;
}

不写括号的错误范例

#define EXPAND(X) 10*X 
int main()
{	
    printf("%d\n", EXPAND(2+3));
    return 0;
}

练习1:

使用带参宏实现功能: 求一个整数的平方

#include <stdio.h> 
#define POW(a) ((a)*(a))

int main()
{
	printf("%d\n", POW(1+1));
	return 0;
}

带参宏 和 函数调用的区别

带参宏 : 在预处理阶段就完成了 宏值替换掉宏名。 运行效率高。在预处理阶段就替换好了要运行的代码,省去了函数的调用过程。

带参宏因为只是替换,所以要考虑作用域命名冲突的问题。

带参宏不会对参数类型进行检查。

带参宏不能定义返回值。

带参宏不具备函数调用的灵活性。

函数调用: 在程序执行之后才进行函数调用。 运行效率没有带参宏的效率高。因为执行阶段才调用。有类型检查,有作用域,有生命周期。

四、条件编译

1. #ifdef

if如果 def define 定义

如果有宏定义,就进行以下的编译

条件编译有什么用?

可以帮助我们自动不编译一些调试输出。

跨平台开发,针对不同的平台可能代码会有微调。

比如WIN,就是windows下逻辑;LINUX就是linux下的逻辑

示例9:

#include <stdio.h> 

int main()
{
   //如果定义过宏名 DEBUG 才会编译printf("hello world\n");  这行代码
#ifdef DEBUG   				
	printf("hello world\n");  
    //ifdef的控制范围到endif结束
#endif
	printf("hello farsight\n");
	return 0;
}

条件编译不是选择性的执行代码,而是选择性的编译代码,并不是代码的执行逻辑。

2. #else #elif

示例10:

#include <stdio.h> 
#define TEST
int main()
{
#ifdef DEBUG
	printf("hello world\n");
	printf("hello farsight\n");  
#else
	printf("hello test\n");    
#endif
	return 0;
}

#include <stdio.h> 
#define TEST 2

int main()
{
#if TEST == 1	
	printf("hello world\n");  
#elif TEST == 2
	printf("hello test\n");
#endif
	printf("hello farsight\n");
	return 0;
}

3. #ifndef

if not define

一般的使用在头文件中,防止头文件中定义的结构体、枚举、联合等类型重复定义。

C++的每个头文件都要加#ifndef

示例11:

///person.h

#ifndef PERSON_H
#define PERSON_H

struct Person
{
	char name[20];
	int age;
};

#endif

在不加条件编译的情况下,多个.c文件包含person.h头文件,会编译出错,提示Person结构体重复定义。

#ifndef PERSON_H这个条件编译,是为了避免头文件中的内容被重复定义。

五、linux标准main函数

格式:

//argv不是数组指针,它就是一个二级指针
int main(int argc, const char *argv[]) //int main(int argc, const char **argv)
{
	return 0;   
}

参数 argc : argument count 运行程序时的参数个数 touch a.c b.c

参数 argv : argument value 运行程序是参数的值

在函数的形参列表中,参数的类型用[]修饰,和用*修饰是一个意思,之所以可以将*换成[]是为了增强程序可读性。

void fun(int* p)
{
    
}

void fun2(int p[])
{
    
}
/*
fun中的p和fun2中的p语法是一样的!fun2中的p给人传达的信息是指针p是专门用来指向数组的。此时[]中不必写数字,就算写了也是白写。
*/

示例12:

#include <stdio.h>
//标准main函数的两个参数,就是传了一个字符指针数组。
int main(int argc, const char *argv[])
{
	if( argc < 4 )	
	{
		return -1;
	}
    printf("argc  :  %d\n", argc);	
	printf("argv[0]:  %s\n", argv[0]);
	printf("argv[1]:  %s\n", argv[1]);
	printf("argv[2]:  %s\n", argv[2]);
	printf("argv[3]:  %s\n", argv[3]);
	return 0;
}

linux@ubuntu:~/22011$ ./test hehe haha enen
argc : 4
argv[0]: ./test
argv[1]: hehe
argv[2]: haha
argv[3]: enen

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HF3zpi3s-1645665244021)(C:\Users\mudonghai\Desktop\linux&C高级\day6\image-20220210154638891.png)]

六、函数的递归调用

自己调用自己,叫做函数的递归调用。

示例13:

调用形式:

void fun()
{
	fun();
}

示例14:

求阶乘 4!

4! = 4 * 3!

3! = 3 * 2!

2! = 2 * 1!

1! = 1

n = 1 num(n) = 1

n > 1 num(n) = n * num(n-1)

#include <stdio.h> 
//求n的阶乘
int mul(int n)  
{
	if( n == 1 )//当递归到1的时候,不再递归,返回1的阶乘1
    {
       return 1; 
    }
    int num = n * mul(n-1);//n的阶乘就是n乘以n-1的阶乘
	return  num;
}

int main()
{
	printf("%d\n", mul(6));
}

要成功使用递归函数,需要注意的是:

一定要写明结束条件。 在满足结束条件后就不再递归了。

递归的结束条件,有时可以作为思考递归的一个逻辑入口。

七、字节序:

1. 分类

大端字节序: 高地址存低位数据,低地址保存高位数据,就是大端序。

小端字节序: 高地址存高位数据,低。。。。低。。。,就是小端序。

了解:

主机字节序: 大部分都是小端序,也有大端序。

网络字节序: 大端字节序。

2. 字节序的检测

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7XJGkHnD-1645665244022)(C:\Users\mudonghai\Desktop\linux&C高级\day6\image-20220210163828716.png)]

当一个变量有多个字节组成时,最低位的地址代表这个变量的地址。

示例15:

#include <stdio.h>

int main()
{
	int a = 0x12345678;
    //强制类型转换,当赋值运算符左右两边的类型不一样,需要进行强制类型转换。
    //强制类型转换要十分小心,很可能数据本身不支持这样的转换。
    //&a 是int* 类型  p是char*类型
	char *p = (char *)&a;//指针p指向的是变量a的最低位的地址,指针定义成char类型,就是为了取一个字节的数据
	printf("%x\n", *p);
	return 0;
}

结果:0x78 说明我们的ubuntu系统是小端字节序

八、位运算

位运算有什么用?

±*/

char 1byte 8bit

只对变量中我们想操作的位进行操作,而不是对整个变量操作。

1. 按位与 & 二元运算

真值表:

a & b 结果

-------------------

0 0 0

1 0 0

0 1 0

1 1 1

示例: 14 && 24 = 1 (真)

14 & 24

​ 0000 1110

& 0001 1000

-------------------

​ 0000 1000

2. 按位或 |

真值表:

a | b 结果

-------------------

0 0 0

1 0 1

0 1 1

1 1 1

示例: 14 || 24 = 1 (真)

14 | 24

0000 1110

| 0001 1000


​ 0001 1110

3. 按位异或 ^

真值表:

a ^ b 结果 (相同为0,不同为1)

-------------------

0 0 0

1 0 1

0 1 1

1 1 0

示例:

14 ^ 24

​ 0000 1110

^ 0001 1000

-------------

​ 0001 0110

4. 按位取反

真值表:

a ~a

---------

0 1

1 0

示例: !100 = 0 (假)

~100

~ 0110 0100

1001 1011

5.左移右移

左移,向数据高位移,和内存没关系。

每一位都向高位移动,低位补0,高位溢出。

8 << 2

​ 0000 1000

<<2 0010 0000

右移,向数据低位移,和内存没关系。

每一位都向低位移动,低位溢出,高位补(无符号数补0,有符号数补符号位),位运算时

绝大部分情况下都是无符号。

有符号数

1 最高位 0

-1 最高位 1

无符号

8 >> 3

​ 0000 1000

>>2 0000 0001

有符号,最高位是符号位,正数符号位0,负数符号位是1

-8 >>2

​ 1000 1000

>>2 1110 0010

注意:

使用位运算不要计算变量的值是多少,不是不能算,因为没意义。如果在意变量的值是多少,说明根本就不需要位运算。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rAtCUZiE-1645665244023)(C:\Users\mudonghai\Desktop\linux&C高级\day6\wps26EA.tmp.jpg)]

这道题出的本身就有问题,只是在强调位运算的数学规律,并不是位运算的目的。

经过位运算的某一位或者某些位的值是0还是1。

6. 运用

按位与: 置0 或者 读取值

按位或: 置1

异或: 取反

置零

unsigned char x;

x = x&~(1<<n); 将变量x的n位置0

假设x 的二进制值 0000 1010

假设n的值是3

1 ------ 0000 0001

1<<3 ------0000 1000

~(1<<3)—1111 0111

​ 0000 1010

& 1111 0111

​ 0000 0010 结果是将x3号位的1变成了0,其他位都没变

置1

unsigned char x;

x = x|1<<n; 将变量x的n位置1

假设x 的二进制值 0000 1010

假设n的值是2

1 ------ 0000 0001

1<<2 ------0000 0100

​ 0000 1010

| 0000 0100

​ 0000 1110 结果,把x的2号位值置1,其他位没变

int status = 0;

0 位表示中毒

1 位表示冰冻

2 位表示残废

3 位表示眩晕

status | 1<<1;

status | 1<<2;

status | 1<<3;

status | 1<<0;

读取

unsigned char x;

if( (x&1<<n)   == 0) 
{
//结果位真说明x的n位是0
}
else
{
//结果位假,说明x的n位是1
}

假设x 的二进制值 0000 1010

假设n的值是2

1 -------- 0000 0001

1<<2-------- 0000 0100

​ 0000 1010

& 0000 0100

​ 0000 0000 结果是0,说明x的2号位是0

假设x 的二进制值 0000 1010

假设n的值是3

1 -------- 0000 0001

1<<3-------- 0000 1000

​ 0000 1010

& 0000 1000

0000 1000 结果不为0,所以x的3号位是1

取反

unsigned char x;

x = x^1<<n; 将变量x的n位取反,和不一样,是把所有的位取反

假设x 的二进制值 0000 1010

假设n的值是3

​ 0000 0010 0000 1010

^ 0000 1000 0000 1000

​ 0000 1010 0000 0010 结果是将x的3号位取反。

九、数据类型:

基本数据类型: char int short long float double

构造数据类型: 指针。 数组。 结构体。 共用体。 枚举。

空类型: void

1. 枚举 enum

switch(score)

front 0

mid 1

back 2

Z轴

(1)定义:

enum TimeofDay
{
	morning,
	afternoon,
	evening
};

(2)注意要点:

1)枚举类型中,声明的第一个枚举成员默认值为0

2)以后每个枚举成员值将是前一个枚举成员的值加1得到的。

3)定义枚举类型时,可以为枚举成员显示赋值。允许多个枚举成员有相同的值。

4)没有显示赋值的枚举成员的值,总是前一个枚举成员的值+1

(3) 使用示例:

枚举的使用,一般不会定义枚举类型变量,因为没有意义,枚举的每个成员都是常量。

enum TimeofToday
{	
    morning,	
    halfmorninig = 0,	//强制让halfmorninig是0
    afternoon,	
    halfafternoon = 0,	//强制让halfafternoon是0
    evening,  //枚举的最后一个成员后面有没有逗号都无所谓
}; 
int main(int argc, const char** argv)
{	
    printf("%d %d %d %d %d\n", morning, afternoon, evening,	halfmorninig, halfafternoon);
}

(4) 为什么使用枚举

枚举中每个成员都是常量,当定义好枚举之后,成员的值不能改变。

使用枚举的场合:当我们需要很多变量,不在乎值是多少,只在乎他们的值没有重复,最好还有大小关系,这时会将这些变量定义成枚举。

我们不会去定义枚举变量,枚举里的成员都是当作常量直接使用的。

2. 共用体 union

也叫联合体

(1)定义

union data 
{
	int a;
	char b;
};

(2)要点:

​ -> 使用内存的方式,与结构体不同。

​ -> 共用体的各个成员共用内存,各个成员的起始地址是相同的。(占内存小的成员,是在大成员的低位地址)

​ -> 整个共用体占用的存储空间以长度最大的成员为准。

​ -> 一个共用体变量,如果对多个成员赋值,会覆盖掉其他成员的数据。

(3) 代码示例: 测试主机序。

#include <stdio.h> 

union data 
{
	int a; 
    char c;  
};

int main()
{
	union data x;
	x.a = 0x12345678;  
	printf("%x\n", x.c);
	return 0;
}

(4)共用体的作用

1.作为数据泛型,一个共用体变量可以表示多种类型的数据。
2.实现巧妙的数据转换,比如将成员a转换为成员b。

(5) 共用体对比结构体

结构体每个成员都有独立的内存,而共用体所有成员共用同一段内存。

3. 位域

有时用一个字节去存储信息,还是会很浪费内存,此时就可以使用位域。使用位域的目的是为了节省内存。

(1) 定义:

struct data 
{
	unsigned int a : 2;  //a占了int类型的前0位和1位
	unsigned int b : 4;  //b 占了int类型的 2 3 4 5位
	unsigned int : 0;  /* 空域 *///占了int类型剩下的所有位6~31位
	unsigned int c : 3;	//c占了另一个int的0 1 2位
};

//占8字节  a b 空域 占一个int  c独占一个int
struct data
{
	unsigned int a:2;  //int 0 1
	unsigned int b:4;  //int 2 3 4 5
	unsigned int c:3;  //int 6 7 8
	unsigned int:0;    //空域  9~31
};
//占4字节

(2) 注意要点:

1)各位域必须存储在同一个类型长度中,不能跨两个类型长度。

2)位域占用的位数,不能超过类型长度。

3)允许位域无域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。

作业:

选择题

1.若数组名作实参而指针变量作形参,函数调用实参传给形参的是 ( )

A.数组的长度

B.数组第一个元素的值

C.数组所有元素的值

D.数组第一个元素的地址

2.变量的指针含意是指变量的 ( )

A.值 B.地址 C.存储 D.名字

3.某文件中定义的静态全局变量(或称静态外部变量)其作用域是 ( )

A.只限某个函数 B.本文件 C.跨文件 D.不限制作用域

4.以下对结构体类型变量的定义中,不正确的是( )。

A: typedef struct aa

{

​ int n;

​ float m;

} AA;

AA td1;

B: #define AA struct aa

AA {

​ int n;

​ float m;

} td1;

C: struct

{

​ int n;

​ float m;

} aa;

stuct aa td1;

D: struct

{

​ int n;

​ float m;

} td1;

5.short a[100],sizeof(a)返回? ( ) (百度笔试)

A 2 B 4 C 100 D 200 E 400

  1. 以下代码执行后,val的值是( )

unsigned long val = 0;

char a = 0x48;

char b = 0x52;

val = b << 8 | a;

A 20992 B 21064 C 72 D 0

简答题

  1. 为什么在头文件的最前面都会看到这样的代码 ?

#ifndef STDIO_H

#define STDIO_H

​ 2.局部变量和全局变量是否能重名,简述一下当两者同时存在是会有什么结果?

编程1:

已知 strcpy 函数的原型是

void strcpy(char *strDest, const char *strSrc);

其中 strDest 是目的字符串,strSrc是源字符串。

不调用 C++/C 的字符串库函数,请编写 函数 strcpy。(注意检查参数的有效性) (东软汽车电子)

编程2:

编写一个函数 taxis()实现数组的升序排序,在函数中调用 带参宏swap()实现两个数的交换。

打印出排序结果
; //c占了另一个int的0 1 2位
};

//占8字节 a b 空域 占一个int c独占一个int




 

```C
struct data
{
	unsigned int a:2;  //int 0 1
	unsigned int b:4;  //int 2 3 4 5
	unsigned int c:3;  //int 6 7 8
	unsigned int:0;    //空域  9~31
};
//占4字节

(2) 注意要点:

1)各位域必须存储在同一个类型长度中,不能跨两个类型长度。

2)位域占用的位数,不能超过类型长度。

3)允许位域无域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。

作业:

选择题

1.若数组名作实参而指针变量作形参,函数调用实参传给形参的是 ( )

A.数组的长度

B.数组第一个元素的值

C.数组所有元素的值

D.数组第一个元素的地址

2.变量的指针含意是指变量的 ( )

A.值 B.地址 C.存储 D.名字

3.某文件中定义的静态全局变量(或称静态外部变量)其作用域是 ( )

A.只限某个函数 B.本文件 C.跨文件 D.不限制作用域

4.以下对结构体类型变量的定义中,不正确的是( )。

A: typedef struct aa

{

​ int n;

​ float m;

} AA;

AA td1;

B: #define AA struct aa

AA {

​ int n;

​ float m;

} td1;

C: struct

{

​ int n;

​ float m;

} aa;

stuct aa td1;

D: struct

{

​ int n;

​ float m;

} td1;

5.short a[100],sizeof(a)返回? ( ) (百度笔试)

A 2 B 4 C 100 D 200 E 400

  1. 以下代码执行后,val的值是( )

unsigned long val = 0;

char a = 0x48;

char b = 0x52;

val = b << 8 | a;

A 20992 B 21064 C 72 D 0

简答题

  1. 为什么在头文件的最前面都会看到这样的代码 ?

#ifndef STDIO_H

#define STDIO_H

​ 2.局部变量和全局变量是否能重名,简述一下当两者同时存在是会有什么结果?

编程1:

已知 strcpy 函数的原型是

void strcpy(char *strDest, const char *strSrc);

其中 strDest 是目的字符串,strSrc是源字符串。

不调用 C++/C 的字符串库函数,请编写 函数 strcpy。(注意检查参数的有效性) (东软汽车电子)

编程2:

编写一个函数 taxis()实现数组的升序排序,在函数中调用 带参宏swap()实现两个数的交换。

打印出排序结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

encounter♌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值