每日一题(四)

9.11 结构体元素偏移

//int 占 2 个字节,char 占 1 个字节,float 占 4 个字节
struct stu{
    union{
        char bj[5];
        int  bn[2];
    }class;//5
    char  xm[8];//8
    float cj;//4
}xc;

问题:求sizeof(xc)?

我的答案:32

正确答案:20

分析:

无论结构体还是联合体,都讲究一个字节对齐,按照其内部最大元素内存大小对齐!!!

所以union中最大元素类型是int,这里是2字节,所以union按照2字节对齐,char bj[5]占了5字节,按照2字节对齐的时候再补一个字节,所以union的大小是6Byte;在struct中,class已经占了前6字节,char xm[8]中每一个char占1字节,所以char数组可以紧接着存放8个字节,现在内存大小为6+8=14字节,由于float需要4字节对齐,所以float从第16字节开始存储,占用4字节。至此struct内存大小占用20字节!

注意:结构体涉及数组的时候,我觉得可以把数组拆分开看作一个个元素,就好多了,只出现数组是不可以按照数组整体来内存对齐的.

结构体定义如下:

//int 占 2 个字节,char 占 1 个字节,float 占 4 个字节
struct stu{
    union{
        char bj[5];
        int  bn[2];
    }class;//5
    char  xm[8];//8
    float cj;//4
}xc;

问题:若xc地址为0X1000,求&xm[0]的值?

我的答案:0X1006

根据上面的内容,union大小为6Byte,所以相对于结构体的偏移地址是6,则紧挨着的xm[0]的地址就是0X1000+6=0X1006

为了提高 CPU 的存储速度,编译器会对一些变量的起始地址做了“对齐”处理。
对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量)
char 偏移量必须为 sizeof(char) 即 1 的倍数
int 偏移量必须为 sizeof(int) 即 4 的倍数 (跟编译器有关,有可能是 2)
float 偏移量必须为 sizeof(float) 即 4 的倍数
double 偏移量必须为 sizeof(double) 即 8 的倍数
short 偏移量必须为 sizeof(short) 即 2 的倍数

9.12 指针、数组的声明

题目:

用变量a给出下面的定义

1、一个整型数(An integer)

2、一个指向整型数的指针( A pointer to an integer)

3、一个指向指针的的指针,它指向的指针是指向一个整数( A pointer to a pointer to an intege)

4、一个有10个整型数的数组( An array of 10 integers)

5、一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to integers)

6、 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers)

7、 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)

8、一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer

答案:
1:int a

2:int *a

3:int **a

4:int a[10]

5:int* a[10]

6:int (*a)[10]

7:int (*a)(int)

8:int (*a[10])(int)

[]的优先级比*要高,所以可以根据题中的要求来判断[]*的先后执行顺序。

比如5题:一个10个指针的数组,指针指向整型数;首先是一个10个元素的数组,所以首先a[10],然后指定数组元素是指针指向整型,所以声明元素为int *

再比如6题:一个指针,指向有10个整型数的数组;首先是一个指针,所以先声明指针,即*a,然后指针的指向是一个10个元素的整型数组,所以就成了int (*a)[10]

当涉及到函数的时候,分为三部分:函数返回值类型、指向函数的类型、函数的参数类型。指向函数的格式就是加上一个括号,代表函数体。

所以7题分析为:返回值和参数都是整型数,所以int () (int)确定了两部分,然后是指向函数的指针,所以就有了int (*a)(int)

同理8题:返回值和参数都是整型,指向函数的是一个10个元素数组,数组的元素指向函数,所以就有int (*a[10])(int)

9.13 负数的求余运算

运行下列语句,求出x的值:

int x=10;
x += 3+x%(-3);//x=x+3+x%(-3)=13+

答案:14

分析:

x += 3+x%(-3)中,+=运算比较好判断,主要是x%(-3)的判断不知道是1还是-1,在求余运算中,余数的符号与被除数的符号相同,所以在这里x=10,则得数就是1,即x += 3+1易得x的值为14.

9.14 阅读代码

阅读下列代码,分析该代码的功能:

char *func(char *dest, const char *src, int count)    
{    
    char *tmp = dest;    
    while (count) {    
        if ((*tmp = *src) != 0)    
            src++;    
        tmp++;    
        count--;    
    }    
    return dest;    
}   

分析:

先看参数和返回值,参数中第二个参数是const修饰的(指向的地址不可改变),所以第二个参数位置的字符串肯定是不能改变的,然后返回值也是一个char类型的指针,初步推断可能是一个字符串操作类的函数。

然后往函数内部分析,先创建了一个字符指针,指向传进来的dest

在while中根据count的大小进行遍历

if ((*tmp = *src) != 0)中,先是将*tep = *src*然后判断*tmp是否为空,相当于字符拷贝,然后自增、coun自减

可以看出此函数就是拷贝字符串的函数。

实际上strncpy的源码如下:

/*   

 * strncpy - Copy a length-limited, %NUL-terminated string   

 * @dest: Where to copy the string to   

 * @src: Where to copy the string from   

 * @count: The maximum number of bytes to copy   

 *   

 * The result is not %NUL-terminated if the source exceeds   

 * @count bytes.   

 *   

 * In the case where the length of @src is less than that of   

 * count, the remainder of @dest will be padded with %NUL.   

 */   

char *strncpy(char *dest, const char *src, size_t count)    //从 src 复制count个字符 到 dest 
{    
    char *tmp = dest;    
    while (count) {    
        if ((*tmp = *src) != 0)    //把 src 的值 复制到 dest ,如果 src 的值 非空,那么指针自加。
                                   //否则 指针不加,src 后续都是指向 0 ,即字符串结束,后续的 dest值都为 0

            src++;    
        tmp++;                     // dest 的指针 自加
        count--;                   //最大计数值 减 1
    }    
    return dest;    c
}   

9.15 逗号表达式细节

求如下程序的输出:

int a[3][2] = {(0,1),(2,3),(4,5)};
int *p = a[0];
printf("%d",p[0]);

答案:1

分析:
这里分析一下程序,p指针指向a[0],也就是指向二维数组的首地址,所以p[0]的值就是二维数组的第一个值。

再看一下二维数组的定义:int a[3][2]={(0,1),(2,3),(4,5)},这里要注意,这里的初始化不是分段赋值,正常的分段赋值应该是这样:int a[3][2]={{0,1},{2,3},{4,5}},这里是逗号分隔的,所以是逗号表达式,实际的是连续赋值:int a[3][2]={1,3,5},所以p[0]=1.

posted @ 2020-09-15 06:55  Aspirant-GQ  阅读(69)  评论(0编辑  收藏  举报